Domanda

Lo standard .NET di prefisso di un nome di interfaccia con un I sembra essere molto diffuso e non è più limitato a .NET. Mi sono imbattuto in un sacco di codice Java che utilizza questa convenzione (quindi non mi sorprenderebbe se Java lo usasse prima di C #). Anche Flex lo usa e così via. La collocazione di un I all'inizio del nome è però nota della notazione ungherese e quindi non mi sento a mio agio nell'usarlo.

Quindi la domanda è: esiste un modo alternativo per indicare che Something è un'interfaccia, piuttosto che una classe e c'è comunque bisogno di denotarlo in questo modo. O è un caso è diventato uno standard e quindi dovrei semplicemente accettarlo e smettere di provare a suscitare "guerre di religione" suggerendo che sia fatto diversamente?

È stato utile?

Soluzione

Dal libro delle linee guida per la progettazione del framework:

  

Anche le interfacce che rappresentano le radici di una gerarchia (ad es. IList) dovrebbero usare nomi o frasi di nomi. Le interfacce che rappresentano le capacità dovrebbero usare aggettivi e frasi di aggettivo (ad es. IComparable, IFormattable).

Inoltre, dalle annotazioni sulla denominazione dell'interfaccia:

  

KRZYSZTOF CWALINA: Uno dei pochi   i prefissi utilizzati sono & # 8220; I & # 8221; per interfacce   (come in ICollection), ma è per   ragioni storiche. A posteriori, io   penso che sarebbe stato meglio usare   nomi di tipo regolari. Nella maggioranza di   gli sviluppatori di casi non se ne preoccupano   qualcosa è un'interfaccia e non un   classe astratta, per esempio.

     

BRAD ABRAMS: D'altra parte, & # 8220; I & # 8221; il prefisso sulle interfacce è un chiaro   riconoscimento dell'influenza di COM   (e Java) su .NET Framework. COM   reso popolare, anche istituzionalizzato,   la notazione che iniziano le interfacce   con & # 8220; I. & # 8221; Anche se abbiamo discusso   divergendo da questo modello storico   abbiamo deciso di portare avanti il   come molti dei nostri utenti   già familiarità con COM.

     

JEFFREY RICHTER: Personalmente, mi piace il   & # 8220; I & # 8221; prefisso e vorrei che avessimo di più   cose come questa. Piccolo personaggio unico   i prefissi fanno molto per mantenersi   codice conciso e tuttavia descrittivo. Come me   detto prima, io uso i prefissi per il mio   campi di tipo privato perché trovo   questo molto utile.

     

BRENT RECTOR Nota:   questa è davvero un'altra applicazione di   Notazione ungherese (anche se una senza   gli svantaggi della notazione   utilizzare nei nomi delle variabili).

È diventato uno standard ampiamente adottato e, sebbene sia una forma di ungherese, come afferma Brent, non presenta gli svantaggi dell'uso della notazione ungherese nei nomi delle variabili.

Altri suggerimenti

Lo accetterei, per essere onesti. So cosa intendi per essere un po 'come la notazione ungherese (o almeno l'abuso della stessa), ma penso che offra un valore sufficiente per valere la pena farlo in questo caso.

Con l'iniezione di dipendenza in voga, spesso scopro di avere un'interfaccia e una singola implementazione di produzione. È utile renderli facilmente distinguibili solo con il prefisso I.

Un piccolo punto di dati: lavoro sia con Java che con C #, e mi trovo regolarmente a dover controllare quali tipi in Java sono in realtà interfacce, in particolare attorno al framework di raccolta. .NET lo rende semplice. Forse non disturba gli altri, ma mi dà fastidio.

+1 per IFoo da parte mia.

Come programmatore .NET (per la maggior parte), in realtà preferisco la convenzione Java di rilasciare qui I , per un semplice motivo: spesso, piccole riprogettazioni richiedono il passaggio da un'interfaccia a una classe base astratta o viceversa. Se devi cambiare il nome, questo potrebbe richiedere molti refactoring non necessari.

D'altra parte, l'utilizzo per il client dovrebbe essere trasparente, quindi non dovrebbe interessarsi a questo tipo di suggerimento. Inoltre, l '& # 8220; capace & # 8221; suffisso in `Thingable & # 8221; dovrebbe bastare un suggerimento. Funziona abbastanza bene in Java.

/ EDIT: vorrei sottolineare che il ragionamento di cui sopra mi ha spinto a eliminare il prefisso I per i progetti privati. Tuttavia, dopo aver verificato uno di questi con il set di regole FxCop, sono tornato prontamente all'uso di I . La coerenza vince qui, anche se una coerenza folle è l'oblò delle piccole menti .

È tutto su stile e leggibilità . Prefisso interfacce con " I " è semplicemente una convenzione di denominazione e una linea guida di stile che ha preso piede. I compilatori stessi non potrebbero fregarsene di meno.

Lo standard di codifica per Symbian ha interfacce (classi C ++ astratte pure) denotate con una M anziché con una I.

Altrimenti, l'unico altro modo che ho visto di indicare interfacce è attraverso il contesto.

Per .NET, il libro Microsoft Framework Design Guidelines lo raccomanda assolutamente, e sì, è molto standard. Non l'ho mai visto diversamente, e creare una nuova convenzione servirebbe solo a confondere le persone.

Dovrei aggiungere che non mi piace anche la notazione ungherese, ma questo e il caso del prefisso delle variabili di classe con un carattere di sottolineatura sono buone eccezioni per me, perché rendono il codice molto più leggibile.

Ho sempre pensato che questa convenzione di denominazione fosse un po 'un dinosauro. Oggi gli IDE sono abbastanza potenti da dirci che qualcosa è un'interfaccia. Aggiungendo che ho reso il codice più difficile da leggere, quindi se vuoi davvero avere una convenzione di denominazione che separa le interfacce dalle classi, aggiungerei Impl al nome della classe di implementazione.

public class CustomerImpl implements Customer

Hai chiesto un'alternativa, quindi eccone una che ho riscontrato:

Utilizza il prefisso no sulla classe dell'interfaccia, ma usa un prefisso c o C sulle classi concrete corrispondenti. La maggior parte del codice farà generalmente riferimento all'interfaccia, quindi perché inquinarla con il prefisso e non con il tipo concreto generalmente molto meno utilizzato.

Questo approccio introduce un'incongruenza nel fatto che alcuni tipi concreti saranno prefissati (quelli con interfacce corrispondenti) e altri no. Ciò può essere utile poiché ricorda agli sviluppatori che esiste un'interfaccia e il suo uso dovrebbe essere preferito al tipo concreto.

Ad essere sincero, I uso il prefisso sull'interfaccia, ma penso che sia più perché mi sono abituato e mi sento a mio agio con esso.

La mia ipotesi principale è che la cosa più importante sia mantenere la leggibilità nella parte del dominio dell'implementazione. Pertanto:

  • Se hai un comportamento e una possibile implementazione, non creare un'interfaccia:

    StackOverflowAnswerGenerator di classe pubblica {}

  • Se hai un comportamento e molte possibili implementazioni, non ci sono problemi e puoi semplicemente rilasciare " I " ;, e avere:

    interfaccia pubblica StackOverflowAnswerGenerator {}

    StupidStackOverflowAnswerGenerator di classe pubblica: StackOverflowAnswerGenerator {}

    RandomStackOverflowAnswerGenerator di classe pubblica: StackOverflowAnswerGenerator {}

    GoogleSearchStackoverflowAnswerGenerator di classe pubblica: StackOverflowAnswerGenerator {}

    // ...

  • Il vero problema si presenta quando hai un comportamento e una possibile implementazione ma hai bisogno di un'interfaccia per descriverne il comportamento (ad esempio per test convenienti, a causa della convenzione nel tuo progetto, usando una libreria / framework che lo impone , ...). Possibili soluzioni, oltre al prefisso dell'interfaccia, sono:

    a) Prefisso o suffisso per l'implementazione (come indicato in alcune altre risposte in questo argomento)

    b) Utilizza uno spazio dei nomi diverso per l'interfaccia:

    spazio dei nomi StackOverflowAnswerMachine.Interfaces { interfaccia pubblica StackOverflowAnswerGenerator {} }

    spazio dei nomi StackOverflowAnswerMachine {   classe pubblica StackOverflowAnswerGenerator: Interfaces.StackOverflowAnswerGenerator {} }

    c) Utilizza uno spazio dei nomi diverso per l'implementazione:

    spazio dei nomi StackOverflowAnswerMachine { interfaccia pubblica StackOverflowAnswerGenerator {} }

    spazio dei nomi StackOverflowAnswerMachine.Implementations { classe pubblica StackOverflowAnswerGenerator: StackOverflowAnswerMachine.StackOverflowAnswerGenerator {} }

Attualmente sto sperimentando l'ultima possibilità. Tieni presente che nel file di origine dell'implementazione puoi ancora avere " usando StackOverflowAnswerMachine; " e avere un comodo accesso agli oggetti del dominio.

AGGIORNAMENTO: Anche se penso ancora che l'ultima possibilità sia la più pulita, il suo svantaggio è che anche se " usando StackOverflowAnswerMachine; " ti dà accesso a tutti gli oggetti di dominio devi anteporre a tutte le interfacce di dominio da non confondere con le loro implementazioni. Può sembrare qualcosa di non molto conveniente, ma in una progettazione pulita di solito una classe non utilizza molti altri oggetti di dominio e, soprattutto, è necessario utilizzare il prefisso solo nella dichiarazione di campo e nell'elenco dei parametri del costruttore. Quindi, questa è la mia attuale raccomandazione.

Il client con funzionalità di dominio non dovrebbe aver bisogno di sapere se sta usando un'interfaccia, una classe astratta o una classe concreta. Se hanno bisogno di saperlo, allora c'è un problema serio in un tale progetto, perché ha una logica di dominio e preoccupazioni infrastrutturali mescolate sullo stesso livello di astrazione. Pertanto raccomando " a " o " c " soluzioni.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top