2011-05-22 12 views
6

La separazione tra la progettazione dell'API e la relativa implementazione è spesso consigliata nelle implementazioni di software di grandi dimensioni. Ma da qualche parte, devono essere ricollegati (vale a dire, l'implementazione deve essere ricollegata all'API).La separazione tra API e Implementazione dovrebbe essere totale?

Il seguente esempio mostra un disegno API e l'invocazione della sua attuazione tramite l'oggetto GRADO:

import java.util.List; 

public abstract class Separation { 

    public static final Separation INSTANCE = new SeparationImpl(); 

    // Defining a special list 
    public static interface MySpecialList<T> extends List<T> { 
     void specialAdd(T item); 
    } 

    // Creation of a special list 
    public abstract <T> MySpecialList<T> newSpecialList(Class<T> c); 

    // Merging of a special list 
    public abstract <T> MySpecialList<? extends T> specialMerge(
     MySpecialList<? super T> a, MySpecialList<? super T> b); 

    // Implementation of separation 
    public static class SeparationImpl extends Separation { 

     @Override 
     public <T> MySpecialList<T> newSpecialList(Class<T> c) { 
      return ...; 
     } 

     @Override 
     public <T> MySpecialList<? extends T> specialMerge(
      MySpecialList<? super T> a, MySpecialList<? super T> b) { 
      return ...; 
     } 

    } 

} 

Alcuni sosterranno che API non dovrebbe fare riferimento al codice di implementazione. Anche se separiamo il codice API dall'implementazione tramite file separati, spesso è necessario importare il codice di implementazione (almeno il nome della classe) nell'API.

Esistono tecniche per evitare tali riferimenti utilizzando una rappresentazione stringa del nome completo. La classe viene caricata con quella stringa e quindi istanziata. Rende il codice più complicato.

La mia domanda: c'è qualche vantaggio nel separare completamente o isolare il codice API dal codice di implementazione? O è solo il tentativo di un purista di raggiungere la perfezione con pochi vantaggi pratici?

risposta

6

ho sempre capito l'esigenza di un'interfaccia separata dall'implementazione nel senso che non mescolare il come della vostra implementazione con l'quello. Pertanto, nell'esempio sopra riportato, mixare API e implementazione significherebbe esporre nell'API qualcosa che era specifico di come SeparationImpl ha implementato la tua API.

Ad esempio, osservare come viene eseguita l'iterazione in varie classi di raccolta. Esistono modi più specifici per recuperare elementi in raccolte specifiche (ad es. Per posizione in ArrayList), ma quelli non sono esposti in Collection perché sono specifici del modo in cui viene implementato ArrayList concreto.

Ho anche visto progetti con enormi directory di interfacce, ognuna delle quali ha una singola implementazione concreta, e ognuna delle quali riproduce meccanicamente ogni metodo nella loro implementazione concreta, che sembra un'astrazione "finta" completamente inutile, come in realtà non fornisce alcuna astrazione logica.

3

Una tecnica che viene spesso utilizzata in OSGi consiste nell'avere l'API in un modulo separato per l'implementazione. L'API dovrebbe compilare da sola evitando qualsiasi riferimento all'implementazione direttamente.

+0

È una necessità assoluta per OSGi o solo buone pratiche? – JVerstry

+0

Per utilizzare alcuni dei framework come iPOJO è necessario, ma non è necessario farlo in tutti i casi (e io no) –

2

Le risposte di Peter e Steve sono sufficienti ma vorrei aggiungere altro - se si ha solo un'implementazione singola dell'interfaccia o della classe astratta, allora è inutile avere un'interfaccia o una classe astratta come le sue sconfitte lo scopo dell'astrazione.
Nel tuo caso non ho davvero capito - perché hai implementato Separation come una classe astratta, piuttosto SeparationImpl stesso può essere una classe API o se hai implementazioni diverse Separation può essere un inetrface e se hai qualche funzionalità comune allora puoi avere un'altra classe astratta che implementa la tua interfaccia e quindi SeparationImpl eredita da quella classe astratta.la gerarchia delle classi campione sarà simile

interface Separation --> AbstractSeparation --> SeparationImpl 

proprio come la libreria collezione standard

interface List --> AbstractList --> ArrayList 
+0

Anche se esiste solo una implementazione di produzione, gli ABC e le interfacce sono ancora spesso una buona cosa; in primo luogo, impongono una netta separazione delle preoccupazioni. In secondo luogo, consentono un facile test delle unità tramite mock. –

+0

Stavo cercando di illustrare il fatto che a volte è necessario accedere a un'istanza di un'API e in un modo è necessario fornirla dall'API stessa. Sono d'accordo, questo avrebbe potuto essere fatto solo con un'interfaccia. – JVerstry

+0

@Oli Charlesworth - possiamo prendere in giro le classi concrete, non c'è bisogno di avere interfacce per lo scopo di derisione almeno. – Premraj

1

aggiuntive ai buoni punti dagli altri autori vorrei ricordare gli scopi di unit test:

Mettere a punto gli oggetti è molto più facile quando si hanno interfacce in-tead delle classi.

Problemi correlati