Default vs Impl quando si implementano le interfacce in Java

32

Dopo aver letto i nomi dei pacchetti dovrebbero essere singolari o plurali? mi è venuto in mente che non ho mai visto un dibattito adeguato che copre uno dei miei animaletti: denominazione di implementazioni di interfacce.

Supponiamo che tu abbia un'interfaccia Order che deve essere implementata in vari modi, ma esiste solo l'implementazione iniziale quando il progetto viene creato per la prima volta. Vai per DefaultOrder o OrderImpl o qualche altra variante per evitare la falsa dicotomia? E cosa fai quando arrivano più implementazioni?

E la cosa più importante ... perché?

    
posta Gary Rowe 12.05.2011 - 22:09
fonte

8 risposte

57

I nomi hanno l'opportunità di trasmettere un significato. Perché dovresti buttare via quell'opportunità con Impl?

Prima di tutto, se avrai solo un'implementazione, elimina l'interfaccia. Crea questo problema di denominazione e non aggiunge nulla. Ancora peggio, potrebbe causare problemi con le firme dei metodi incoerenti nelle API se tu e tutti gli altri sviluppatori non state attenti a utilizzare sempre solo l'interfaccia.

Detto questo, possiamo supporre che ogni interfaccia abbia o possa avere due o più implementazioni.

  • Se ne hai uno solo adesso e non sai in che modo l'altro potrebbe essere diverso, Predefinito è un buon inizio.

  • Se ne hai due adesso, assegna un nome a ciascuno in base al suo scopo.

    Esempio: recentemente abbiamo avuto una classe concreta Contesto (in riferimento a un database). Ci siamo resi conto che dovevamo essere in grado di rappresentare un contesto non in linea, quindi il nome Context è stato utilizzato per una nuova interfaccia (per mantenere la compatibilità per le vecchie API) e una nuova implementazione è stata creata, OfflineContext . Ma indovina a cosa è stato rinominato l'originale? Esatto, ContextImpl (yikes).

    In questo caso, DefaultContext probabilmente andrebbe bene, e la gente lo otterrebbe, ma non è così descrittivo come potrebbe essere. Dopotutto, se è non offline , che cos'è? Quindi siamo andati con: OnlineContext .

Caso speciale: Uso del prefisso "I" sulle interfacce

Una delle altre risposte suggerito usando il prefisso I sulle interfacce. Preferibilmente, non hai bisogno di per farlo.

Tuttavia, se hai bisogno di un'interfaccia, per le implementazioni personalizzate, ma hai anche un'implementazione concreta primaria che verrà utilizzata spesso, e il nome di base è troppo semplice per rinunciare a un'interfaccia da solo, quindi puoi considerare di aggiungere "I" all'interfaccia (anche se va benissimo se non si adatta ancora a te e alla tua squadra).

Esempio: molti oggetti possono essere un "EventDispatcher". Per ragioni di API, questo deve essere conforme a un'interfaccia. Tuttavia, si desidera fornire anche un dispatcher di eventi di base per la delega. DefaultEventDispatcher andrebbe bene, ma è un po 'lungo, e se ne vedrai spesso il nome, potresti preferire usare il nome base EventDispatcher per la classe concreta e implementa IEventDispatcher per le implementazioni personalizzate:

/* Option 1, traditional verbose naming: */
interface EventDispatcher { /* interface for all event dispatchers */ }
class DefaultEventDispatcher implements EventDispatcher {
  /* default event dispatcher */
}

/* Option 2, "I" abbreviation because "EventDispatcher" will be a common default: */
interface IEventDispatcher { /* interface for all event dispatchers */ }
class EventDispatcher implements IEventDispatcher {
  /* default event dispatcher. */
}
    
risposta data 12.05.2011 - 22:30
fonte
12

Decido la denominazione in base al caso d'uso dell'interfaccia.

Se l'interfaccia viene utilizzata per disaccoppiamento , quindi scelgo Impl per le implementazioni.

Se lo scopo dell'interfaccia è astrazione comportamentale , le implementazioni sono denominate in base a ciò che stanno facendo concretamente. Spesso aggiungo il nome dell'interfaccia a quello. Quindi se l'interfaccia si chiama Validator , io uso FooValidator .

Trovo che Default sia una scelta pessima. Prima inquina le funzionalità di completamento del codice, perché i nomi iniziano sempre con esso. L'altra cosa è che un valore predefinito è soggetto a modifiche nel tempo. Quindi, ciò che prima potrebbe essere un valore predefinito può essere un po 'di tempo dopo essere una funzionalità deprecata. Quindi, inizi sempre a rinominare le tue classi non appena cambiano le impostazioni predefinite o vivi con nomi fuorvianti.

    
risposta data 06.01.2013 - 17:12
fonte
7

Sono d'accordo con la risposta di Nicole (in particolare che l'interfaccia probabilmente non è necessaria nella maggior parte dei casi), ma per il gusto della discussione lancerò un'altra alternativa oltre a OrderImpl e DefaultOrder : nascondi l'implementazione dietro un metodo factory statico come Orders.create() . Ad esempio:

public final class Orders {
  public static Order create() {
    return new Order() {
      // Implementation goes here.
    };
  }
}

Con questo approccio, l'implementazione potrebbe essere una classe interna anonima, oppure potrebbe essere una classe privata con Default o Impl nel nome, oppure potrebbe essere denominata qualcos'altro interamente. A prescindere da quale sia la scelta, il chiamante non ha bisogno di preoccuparsi, così avrai più flessibilità ora e in seguito quando / se decidi di cambiarlo.

In pratica, alcuni ottimi esempi di questo modello sono le classi di utilità java.util.Collections e java.util.concurrent.Executors , i cui metodi restituiscono implementazioni nascoste. Come efficace Java menziona (nell'elemento 1), questo modello può aiutare a mantenere più piccolo il "Peso concettuale" dell'API.

    
risposta data 04.01.2013 - 22:16
fonte
2

Vado sempre per OrderImpl semplicemente perché appare in ordine alfabetico subito dopo l'interfaccia Order .

    
risposta data 12.05.2011 - 22:13
fonte
0

Puoi dare un nome all'interfaccia con il prefisso I (IWhatever) e quindi rendere l'implementazione Whatever.

Le convenzioni ufficiali del codice Java non parlano di questo tipo di denominazione per le interfacce, tuttavia questo tipo di denominazione aiuta il riconoscimento e la navigazione.

    
risposta data 12.05.2011 - 22:15
fonte
0

Penso che mentre Default può avere senso in alcuni casi, sarebbe più utile descrivere l'implementazione. Quindi se la tua interfaccia è UserProfileDAO allora le tue implementazioni possono essere UserProfileSQLDAO o UserProfileLDAPDAO o qualcosa del genere.

    
risposta data 17.12.2011 - 04:59
fonte
0

se possibile, dai un nome a cosa / come fa la sua cosa.

solitamente l'approccio peggiore è nominarlo dopo come dovrebbe essere usato.

Se si suppone che sia usato come classe base per l'implementazione, puoi usare BaseX o AbstractX (se è astratto (ma prova a squeze in quello che fa, perché se non facesse nulla non lo creeresti, hai già un'interfaccia). Se fornisce la funzionalità più semplice possibile e dovrebbe essere utilizzato direttamente (non estendendolo) quando tale funzionalità è sufficiente, è possibile chiamarlo SimpleX o BasicX.

Se viene utilizzato a meno che non venga fornita un'altra implementazione, denominarlo DefaultX

    
risposta data 07.01.2013 - 14:21
fonte
-2

La maggior parte di queste risposte descrive cosa viene fatto ma non perché.

Che cosa è successo ai principi OO? Cosa mi dice Impl di una classe e di come usarla? Dovresti preoccuparti di capire gli usi non come è costruito.

Se creo un'interfaccia Person, che cos'è PersonImpl? Senza senso. Almeno DefaultPerson mi dice che chiunque abbia codificato non dovrebbe aver creato un'interfaccia.

Le interfacce stanno scrivendo per il polimorfismo e dovrebbero essere utilizzate come tali.

    
risposta data 13.11.2013 - 15:00
fonte

Leggi altre domande sui tag