I nomi delle interfacce dovrebbero iniziare con un prefisso "I"?

67

Ho letto " Pulisci codice " di Robert Martin, si spera, diventi un programmatore migliore. Anche se nessuno di questi è stato davvero rivoluzionario, mi ha fatto pensare in modo diverso al modo in cui progetto applicazioni e codice di scrittura.

C'è una parte del libro che non solo non sono d'accordo, ma non ha senso per me, in particolare per quanto riguarda le convenzioni di denominazione delle interfacce. Ecco il testo, tratto direttamente dal libro. Ho sfidato l'aspetto di questo trovo confuso e vorrei chiarimenti su.

I prefer to leave interfaces unadorned. The preceding I, so common in today’s legacy wads, is a distraction at best and too much information at worst. I don’t want my users knowing that I’m handing them an interface.

Forse è perché sono solo uno studente, o forse perché non ho mai fatto alcuna programmazione professionale o di gruppo, ma vorrei che l'utente sapesse che è un'interfaccia. C'è un grande differenza tra l'implementazione di un'interfaccia e l'estensione di una classe.

Quindi la mia domanda si riduce a "Perché dovremmo nascondere il fatto che parte del codice si aspetta un'interfaccia?"

Modifica

In risposta a una risposta:

If your type is an interface or a class is your business, not the business of someone using your code. So you shouldn't leak details of your code in this thrid party code.

Perché non dovrei "perdere" i dettagli se un dato tipo è un'interfaccia o una classe di un codice di terze parti? Non è importante che lo sviluppatore di terze parti utilizzi il mio codice per sapere se implementeranno un'interfaccia o estenderanno una classe? Le differenze semplicemente non sono così importanti come le sto facendo notare nella mia mente?

    
posta Charles Sprayberry 01.11.2011 - 22:50
fonte

7 risposte

64

Se ti fermi a pensarci, vedrai che un'interfaccia in realtà non è semanticamente molto diversa da una classe astratta:

  • Entrambi hanno metodi e / o proprietà (comportamento);
  • Né dovrebbero avere campi non privati (dati);
  • Nessuno dei due può essere istanziato direttamente;
  • Derivare da uno significa implementare qualsiasi metodo astratto che possiede, a meno che il tipo derivato sia anche astratto.

In effetti, le distinzioni più importanti tra classi e interfacce sono:

  • Le interfacce non possono avere dati privati;
  • I membri dell'interfaccia non possono avere modificatori di accesso (tutti i membri sono "pubblici");
  • Una classe può implementare più interfacce (al contrario di essere generalmente in grado di ereditare da una sola classe base).

Poiché le uniche distinzioni particolarmente significative tra classi e interfacce ruotano attorno a (a) dati privati e (b) tipo gerarchia - nessuno dei quali fa la minima differenza in un chiamante - in genere non è necessario sapere se un tipo è un'interfaccia o una classe. Sicuramente non hai bisogno dell'indicazione visual .

Tuttavia, ci sono alcuni casi angolari di cui essere a conoscenza. In particolare, se si utilizza la riflessione, l'intercettazione, i proxy / mixin dinamici, la tessitura del codice, la generazione del codice o qualsiasi cosa che implichi l'invio di direttamente al sistema di scrittura o al codice stesso dell'ambiente, allora è molto utile e a volte è necessario sapere subito se si ha a che fare con un'interfaccia o una classe. Ovviamente non vuoi che il tuo codice fallisca misteriosamente perché hai provato ad aggiungere una classe, piuttosto che un'interfaccia, come mixin.

Per codice di business logic tipico, vanilla, run-of-the-mill, tuttavia, le distinzioni tra classi astratte e interfacce non devono essere pubblicizzate perché non entreranno mai in gioco.

Tutto ciò detto, io tendo a prefisso le mie interfacce C # con I in ogni caso perché questa è la convenzione .NET utilizzata e sostenuta da Microsoft. E quando sto spiegando le convenzioni di codifica a un nuovo sviluppatore, è molto meno fastidioso usare le regole di Microsoft piuttosto che spiegare perché abbiamo le nostre regole "speciali".

    
risposta data 02.11.2011 - 02:20
fonte
13

In molti modi, la coerenza è più importante della convenzione. Finché sarai coerente nei tuoi schemi di denominazione, non sarà difficile lavorare con loro. Il prefisso si interfaccia con un I se ti piace, o lascia il nome disadorno, non mi importa finché scegli uno stile e lo mantieni!

    
risposta data 02.11.2011 - 15:13
fonte
11

Il libro è pieno di cose buone, ma aggiungerei ancora "I" al nome dell'interfaccia.

Immagina di avere public interface ILog con un'implementazione predefinita public class Log .

Ora, se decidi di avere public interface Log , all'improvviso devi cambiare la classe Log in public class LogDefault o qualcosa su quelle linee. Sei passato da un personaggio in più a sette - sicuramente è uno spreco.

C'è spesso una linea sottile tra teoria e pratica. In teoria questa è davvero una buona idea, ma in pratica non è così buona.

    
risposta data 08.04.2014 - 11:55
fonte
8

Beh, non si tratta di implementare l'interfaccia o di estendere una classe. In questi casi, sai comunque cosa stai facendo.

Tuttavia, quando il codice di terze parti (un altro modulo dell'applicazione per esempio) manipola i tuoi dati, questo codice non dovrebbe interessarti se stai presentando un'interfaccia o una classe.

Questo è l'intero punto dell'astrazione. Stai presentando a questo codice di terze parti un oggetto di un determinato tipo. Questo dato tipo ha una funzione membro che puoi chiamare. È abbastanza.

Se il tuo tipo è un'interfaccia o una classe è la tua attività, non l'attività di qualcuno che utilizza il tuo codice. Quindi non dovresti divulgare i dettagli del tuo codice a questo codice di terze parti.

A proposito, le interfacce e le classi sono tipi di riferimento alla fine. E questo è ciò che conta. Quindi questo è ciò che la tua convenzione di denominazione deve sottolineare.

    
risposta data 01.11.2011 - 22:58
fonte
5

La maggior parte delle risposte sembra presupporre che il linguaggio di programmazione sia Java o C # in cui esiste un concetto (o una parola chiave) per le interfacce / classi astratte. In questi casi, in un IDE decente, è immediatamente visibile con quale tipo di classe uno si occupa e scrivendo public interface IMyClass è una duplicazione non necessaria. È come se non scrivessi public final FinalMyClass - immagina di inserire ogni parola chiave nel nome della classe.

Tuttavia, a mio parere in C ++, la situazione è leggermente diversa dal momento che ci si deve immergere nel file di intestazione e vedere se la classe ha metodi virtuali per scoprire se si tratta di una classe astratta. In tal caso, posso chiaramente vedere un argomento per scrivere class AbstractMyClass .

Quindi la mia risposta sarebbe: Dipende dal linguaggio di programmazione.

Aggiornato il 2016: 2 anni di esperienza C ++ in seguito probabilmente ora considererei una cattiva pratica anteporre i nomi di classe a Abstract , anche se direi che probabilmente ci sono basi di codice così complesse che potrebbe avere un senso.

    
risposta data 08.04.2014 - 11:49
fonte
3

Segui gli idiomi della lingua che stai utilizzando.

Ogni lingua ha i suoi idiomi e le sue linee guida per la codifica. Ad esempio, in C #, è idioma anteporre le interfacce a I. In Go, non lo è.

    
risposta data 29.02.2016 - 11:03
fonte
0

Nel mio codice (Java), tendo ad avere questa convenzione nelle API che espongo ai chiamanti:

  • Le funzionalità vengono fornite tramite le interfacce e mai dalle classi.
  • Le parti non funzionali sono classi.

Per non funzionale, intendo cose come le strutture di dati puri (come le classi che fungono da ponti verso la serializzazione XML o l'ORM), le enumerazioni e le eccezioni, che non possono essere interfacce (beh, è possibile per le classi di dati puri, ma è molto lavoro per un guadagno molto piccolo in quanto non c'è nulla che quelle classi facciano tranne contengono dati).

In termini di convenzioni di denominazione, le interfacce tendono a mappare sia i nomi degli attori (ad esempio FooBarWatcher ) che gli aggettivi (ad esempio FooBarWatchable ) e sia le classi di dati sia le enumerazioni sono mappate su nomi non attivi (ad esempio% codice%); l'IDE può guidare il consumatore dell'API senza speciali convenzioni di denominazione. Le eccezioni seguono le consuete convenzioni Java ( FooBarStatus , FooBarException , FooBarError ), naturalmente.

Spesso inserisco le interfacce nel loro pacchetto o anche nella loro libreria, solo per assicurarmi di non essere tentato di infrangere le mie regole. (Questo mi aiuta anche a gestire la build quando sto ricavando il codice da fonti esterne come i documenti WSDL.)

    
risposta data 02.11.2011 - 12:42
fonte

Leggi altre domande sui tag