Denominazione dell'interfaccia in Java [chiuso]


324

La maggior parte delle lingue OO prefissa i nomi delle loro interfacce con la I maiuscola, perché Java non lo fa? Qual era la logica per non seguire questa convenzione?

Per dimostrare cosa intendo, se volessi avere un'interfaccia utente e un'implementazione utente avrei due scelte in Java:

  1. Class = User, Interface = UserInterface
  2. Class = UserImpl, Interface = User

Dove nella maggior parte delle lingue:

Class = User, Interface = IUser

Ora, potresti sostenere che potresti sempre scegliere un nome più descrittivo per l'implementazione dell'utente e il problema scompare, ma Java sta spingendo un approccio POJO alle cose e la maggior parte dei contenitori IOC utilizzano ampiamente DynamicProxies. Queste due cose insieme significano che avrai molte interfacce con una singola implementazione POJO.

Quindi, suppongo che la mia domanda si riduca a: "Vale la pena seguire la più ampia convenzione di denominazione dell'interfaccia, specialmente alla luce di dove sembra che Java Frameworks stia andando?"


61
"Dove nella maggior parte delle lingue"? Quali lingue oltre a quelle .Net?
wds,

2
Comunità linguistiche diverse hanno convenzioni di denominazione diverse, e questo è stato vero per molto, molto tempo. Scoprire come hanno avuto origine le convenzioni di denominazione è a volte essenzialmente una ricerca folcloristica.
David Thornley,

4
Eclipse è un valore anomalo significativo che utilizza Java con denominazione in stile IFoo. wiki.eclipse.org/Naming_Conventions
David Leonard

2
Se si dà un'occhiata a nomi di interfacce di Android SDK (Java pure), si vedrà che hanno usato convenzione di avere parola Interface sulla fine di un nome di interfaccia, come NetworkInterface, DialogInterfacee così via
sandalone

21
Come può questa domanda essere "chiusa come non costruttiva" quando è così popolare e di interesse per così tante persone?
o il

Risposte:


329

Preferisco non usare un prefisso sulle interfacce:

  • Il prefisso danneggia la leggibilità.

  • L'uso delle interfacce nei client è il modo migliore standard per programmare, quindi i nomi delle interfacce dovrebbero essere il più brevi e piacevoli possibile. Le classi di implementazione dovrebbero essere più brutte per scoraggiarne l'uso.

  • Quando si passa da una classe astratta a un'interfaccia, una convenzione di codifica con prefisso I implica la ridenominazione di tutte le occorrenze della classe --- non va bene!


12
Completamente d'accordo. Un'altra chiave da digitare se si utilizza il completamento automatico. Molti file che iniziano con un I.
Kalecser,

85
Qualsiasi IDE decente semplifica la modifica del codice nel modo in cui stai descrivendo. Inoltre, quando si passa da una classe astratta a un'interfaccia sono abbastanza sicuro che i tuoi clienti dovranno comunque ricompilarsi.
Allain Lalonde,

63
Super tardi qui, ma: non importa affatto se un IDE rende facile cambiare il nome di qualcosa. Il codice che utilizza un'istanza di qualche tipo non dovrebbe mai, mai preoccuparsi se quel tipo è un'interfaccia o una classe o cosa. Come tale, esporre un tale dettaglio nel nome del tipo è inutile e dannoso per la comprensione. Il tipo e il contratto che espone sono ciò che conta!
ColinD,

11
Inoltre, se stai seguendo la rotta di IFoo, non dovrebbe essere CFoo per l'implementazione e, naturalmente, in caso di fallimento un metodo lancerebbe un EFoo.
Robin,

57
"Il prefisso fa male alla leggibilità" è puramente soggettivo. Come la maggior parte delle convenzioni di denominazione. È molto più importante che il tuo team stabilisca un accordo su cosa fare in modo che la base di codice sia coerente.
Dreadwail,

121

C'è davvero una differenza tra:

class User implements IUser

e

class UserImpl implements User

se tutto ciò di cui stiamo parlando sono convenzioni di denominazione?

Personalmente preferisco non precede l'interfaccia con Icome io voglio essere la codifica per l'interfaccia e ritengo che sia più importante in termini di convenzione di denominazione. Se chiami l'interfaccia, IUserogni consumatore di quella classe deve sapere che è un IUser. Se chiami la classe, UserImplsolo la classe e il tuo contenitore DI conoscono la Implparte e i consumatori sanno solo che stanno lavorando con una User.

Poi di nuovo, i tempi che sono stato costretto a usare Implperché un nome migliore non si presenta sono stati pochi e lontani tra loro perché l'implementazione prende il nome in base all'implementazione perché è lì che è importante, ad es.

class DbBasedAccountDAO implements AccountDAO
class InMemoryAccountDAO implements AccountDAO

Penso che vorresti sapere che è un DAO dal momento che descrive le funzionalità generali senza dover aprire la classe. Se sto esaminando i file della classe in un progetto, è facile vedere tutti i DAO cercando * DAO
Patrick,

6
DAO è un modello ben noto per l'accesso al database, quindi avere il modello nel nome rende facile sapere cosa fa la classe semplicemente osservandone il nome. PS Sarebbe meglio seguire rigorosamente la notazione del cammello ("AccountDao") come in mina.apache.org/changes-b Between
Esko Luontola,

4
@marker, non è come avere un I per indicare un'interfaccia. DAO ti dice che la classe o l'interfaccia è un oggetto per accedere ai dati dell'account, che è ciò che fa l'oggetto. Avere un io ti dice che è un'interfaccia, che non ha nulla a che fare con l'oggetto stesso, ma la semantica del linguaggio
tddmonkey,

Mentre lo presenti, il suo prefisso vs suffisso.
Andrei Rînea,

3
@Andrei: No, è la semantica ("DAO") rispetto alla decorazione non necessaria di un artefatto del linguaggio ("I" come nell'interfaccia; un fatto, che è menzionato nel codice comunque "interfaccia IFoo ...")
Dirk

75

Ci possono essere diversi motivi per cui Java generalmente non usa la convenzione IUser.

  1. Parte dell'approccio orientato agli oggetti è che non dovresti sapere se il client utilizza un'interfaccia o una classe di implementazione. Quindi, anche List è un'interfaccia e String è una classe reale, un metodo potrebbe essere passato a entrambi - non ha senso distinguere visivamente le interfacce.

  2. In generale, preferiremo in realtà l'uso di interfacce nel codice client (preferiamo List to ArrayList, ad esempio). Quindi non ha senso far risaltare le interfacce come eccezioni.

  3. La convenzione di denominazione Java preferisce nomi più lunghi con significati effettivi ai prefissi in stile ungherese. Quindi quel codice sarà il più leggibile possibile: un elenco rappresenta un elenco e un utente rappresenta un utente, non un utente.


72

C'è anche un'altra convenzione, utilizzata da molti progetti open source tra cui Spring.

interface User {
}

class DefaultUser implements User {
}

class AnotherClassOfUser implements User {
}

Personalmente non mi piace il prefisso "I" per la semplice ragione che è una convenzione opzionale. Quindi se adotto questo IIOPConnection significa un'interfaccia per IOPConnection? Che cosa succede se la classe non ha il prefisso "I", allora so che non è un'interfaccia..la risposta qui è no, perché le convenzioni non sono sempre seguite e il loro controllo creerà più lavoro che la convenzione stessa salva.


Mi piace questo, dal momento che ti aiuta anche a utilizzare le interfacce per le dipendenze esterne piuttosto che accoppiare le classi.
Matt Briggs,

47

Come diceva un altro poster, in genere è preferibile che le interfacce definiscano capacità e non tipi. Tenderei a non "implementare" qualcosa di simile a un "Utente" ed è per questo che "IUser" spesso non è realmente necessario nel modo descritto qui. Vedo spesso le classi come sostantivi e le interfacce come aggettivi:

class Number implements Comparable{...}  
class MyThread implements Runnable{...}
class SessionData implements Serializable{....}

A volte un aggettivo non ha senso, ma in genere utilizzerei comunque le interfacce per modellare comportamenti, azioni, capacità, proprietà, ecc., Non tipi.

Inoltre, se avessi davvero intenzione di creare un solo utente e chiamarlo utente, qual è il punto di avere anche un'interfaccia IUser? E se hai diversi tipi di utenti che devono implementare un'interfaccia comune, cosa ti consente di salvare un "io" nell'interfaccia nella scelta dei nomi delle implementazioni?

Penso che un esempio più realistico sarebbe che alcuni tipi di utenti devono essere in grado di accedere a una particolare API. Potremmo definire un'interfaccia di accesso e quindi avere una classe genitore "Utente" con le sottoclassi di SuperUser, DefaultUser, AdminUser, AdministrativeContact, ecc., Alcune delle quali implementeranno o meno l'interfaccia di Login (Loginable?) Secondo necessità.


Penso che gli esempi che fornisci per supportare "interfacce come aggettivi" siano distorti, dal momento che quelle interfacce sono pensate per essere più simili a mix-in (o tratti). Pertanto, le interfacce sono buone sia per gli aggettivi che per i nomi - ma probabilmente non per indefinite transitive verbs 8 ^ P
Stevel

Questo potrebbe essere cambiato negli ultimi anni. Il docu dell'oracolo. consente le interfacce come tipi: [link] docs.oracle.com/javase/tutorial/java/IandI/interfaceAsType.html
karlihnos

38

Bob Lee ha detto una volta in una presentazione:

che senso ha un'interfaccia se hai una sola implementazione?

quindi, inizi con una implementazione, cioè senza un'interfaccia. più tardi decidi, beh, qui c'è bisogno di un'interfaccia, quindi converti la tua classe in un'interfaccia.

allora diventa ovvio: la tua classe originale era chiamata Utente. la tua interfaccia ora è chiamata Utente. forse hai UserProdImpl e UserTestImpl. se hai progettato bene la tua applicazione, ogni classe (eccetto quelle che istanziano l'Utente) rimarrà invariata e non noterà che all'improvviso gli viene passata un'interfaccia.

così diventa chiaro -> Interfaccia Implementazione utente UserImpl.


18
L'uso delle interfacce aiuta a testare lo sviluppo guidato. Abbiamo riscontrato numerosi problemi senza il modello di dominio e i test perché abbiamo deciso di NON utilizzare le interfacce. Un mio amico una volta ha citato: "Tutto è un'interfaccia, ti salverà a lungo termine."
hooknc

4
Derisione e supporto proxy semplice. Sono sicuro che ci sono altri motivi per fornire anche interfacce.
MetroidFan2002,

3
Come ho detto di recente a un collega, non costa nulla introdurre un'interfaccia ora, ma può farti risparmiare un sacco di tempo in seguito.
tddmonkey,

2
Se potessi avere altre implementazioni in un futuro quasi medio, un'interfaccia sarebbe un vantaggio.
Stef,

3
Non mi piace l'argomento "Potrei aver bisogno di un altro impl in futuro". Preferisco un approccio YAGNI: non pianificare cose che non sono ancora accadute.
David Lavender,

24

In C # lo è

public class AdminForumUser : UserBase, IUser

Direbbe Java

public class AdminForumUser extends User implements ForumUserInterface

Per questo motivo, non credo che le convenzioni siano altrettanto importanti in Java per le interfacce, poiché esiste una differenza esplicita tra ereditarietà e implementazione dell'interfaccia. Vorrei solo scegliere qualsiasi convenzione di denominazione che desideri, purché tu sia coerente e usi qualcosa per mostrare alla gente che si tratta di interfacce. Non lavoro a Java da alcuni anni, ma tutte le interfacce si troverebbero nella loro directory e quella era la convenzione. Non ho mai avuto problemi con esso.


22
Forse sono un cattivo programmatore Java, ma preferisco lo stile C #, significa che tutte le interfacce iniziano con il prefisso 'I' :)
davs

7
Non sono sicuro da dove tu e altri state ricevendo questa presunta convenzione. Non è evidente nelle librerie Java ...
ChiefTwoPencils

6

Nella mia esperienza, la convenzione "I" si applica alle interfacce che intendono fornire un contratto a una classe, in particolare quando l'interfaccia stessa non è una nozione astratta della classe.

Ad esempio, nel tuo caso, mi aspetto solo di vedere IUserse l'unico utente che hai intenzione di avere è User. Se prevedi di avere diversi tipi di utenti - NoviceUser, ExpertUserecc. - mi aspetterei di vedere Userun'interfaccia (e, forse, una AbstractUserclasse che implementa alcune funzionalità comuni, come get/setName()).

Mi aspetto anche che le interfacce che definiscono le capacità - Comparable, Iterableecc. - vengano denominate in questo modo, e non come IComparableo IIterable.


Se l'unico utente che hai intenzione di avere è Utente, perché non usare solo Utente anziché l'interfaccia?
Carighan,

3
In alcune architetture client / server, il lato client deve conoscere le interfacce senza bisogno di implementazioni di server pesanti.
David Koelle,

5

Seguendo i buoni principi OO, il codice dovrebbe (per quanto pratico / possibile) dipendere da astrazioni piuttosto che da classi concrete. Ad esempio, è generalmente meglio scrivere un metodo come questo:

public void doSomething(Collection someStuff) {
    ...
}

di questo:

public void doSomething(Vector someStuff) {
    ...
}

Se segui questa idea, sostengo che il tuo codice sarà più leggibile se dai nomi alle interfacce come "Utente" e "BankAccount" (ad esempio), anziché "IUser", "UserInterface" o altre varianti.

Le uniche parti di codice che dovrebbero interessare le classi concrete concrete sono i luoghi in cui sono costruite le classi concrete. Tutto il resto dovrebbe essere scritto usando le interfacce.

Se lo fai, allora i nomi di "concrete" "brutte" come "UserImpl" dovrebbero essere nascosti in modo sicuro dal resto del codice, il che può continuare allegramente usando i nomi di "bella" interfaccia.


Ma perché preoccuparsi di creare un'interfaccia corrispondente per ogni classe del tuo programma quando hai solo bisogno di interfacce per una o due cose?
LegendLength

3

= v = Il prefisso "I" viene utilizzato anche nel framework Wicket, dove mi sono abituato rapidamente. In generale, accolgo con favore qualsiasi convenzione che accorcia ingombranti nomi di classe Java. È una seccatura, però, che tutto sia alfabetizzato sotto "I" nelle directory e nel Javadoc.

La pratica del codice Wicket è simile a Swing, in quanto molte istanze di controllo / widget sono costruite come classi interne anonime con dichiarazioni di metodi inline. Stranamente, differisce di 180 ° da Swing in quanto Swing utilizza un prefisso ("J") per le classi di implementazione.

Il suffisso "Impl" è un'abbreviazione birichina e non si internazionalizza bene. Se solo fossimo andati almeno con "Imp", sarebbe stato più carino (e più breve). "Impl" è usato per IOC, specialmente Spring, quindi per ora siamo un po 'bloccati. Tuttavia, diventa un po 'schizo seguendo 3 diverse convenzioni in tre parti diverse di una base di codice.


0

È una convenzione di denominazione più ampia in qualche senso reale? Sono più sul lato C ++ e non su Java e i discendenti. Quante comunità linguistiche usano la convenzione I?

Se hai una convenzione di denominazione standard di negozio indipendente dalla lingua qui, usala. In caso contrario, seguire la convenzione sulla denominazione delle lingue.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.