Dovresti sempre Code To Interfaces in Java

Comprendo i principi di Coding to Interfaces – per disaccoppiare l’implementazione dall’interfaccia e consentire l’implementazione e l’implementazione delle interfacce dell’interfaccia.

Devo codificare le interfacce per ogni class che scrivo o è eccessivo ? Non voglio raddoppiare il numero di file sorgente in un progetto a meno che non ne valga davvero la pena.

Quali fattori posso utilizzare per decidere se codificare tramite interfaccia o no?

In generale sono d’accordo con le altre risposte: usa un’interfaccia quando conosci o prevedi un cambiamento e / o un’implementazione diversa, o vai alla testabilità.

Ma non è sempre facile sapere in anticipo cosa potrebbe cambiare in futuro, specialmente se non sei così esperto. Penso che la soluzione per questo problema sia il refactoring: mantienilo semplice (= nessuna interfaccia) finché non è necessario. Quando si presenta la necessità, esegui semplicemente un refactoring “Introduci / Estrai interfaccia” (supportato da quasi tutti gli IDE decenti).

Quando lo fai, estrai solo i metodi effettivamente necessari ai chiamanti. Non aver paura di estrarre più di una interfaccia separata (se non tutti i metodi estratti sono veramente coerenti).

Un driver del refactoring potrebbe essere il test: se non è ansible testare facilmente qualcosa con le classi, considera solo l’introduzione di una / alcune interfacce. Ciò consentirà anche di utilizzare il mocking che può semplificare notevolmente i test in molti casi.

Modifica: basandomi sul commento di Tarski, ho realizzato uno scenario / aggiustamento più importante delle precedenti dichiarazioni:
Se fornisci un’API esterna (per altri [sotto] progetti, o la rilasci davvero “allo stato selvaggio”), utilizzare le interfacce nell’API (eccetto per le classi di valore semplice) è quasi sempre una buona idea.
Ti permetterà di cambiare l’impl se lo desideri senza disturbare il codice cliente. Avrai un problema solo se dovrai anche cambiare l’interfaccia. Non interrompere la compatibilità sarà molto difficile (se non imansible).

Lo uso quando almeno una delle seguenti condizioni è vera:

1) Voglio separare i moduli / classi non correlati l’uno dall’altro, e voglio che venga riflesso dalle dipendenze del pacchetto java.

2) Quando il disaccoppiamento è importante in termini di dipendenze di build

3) Quando l’implementazione può cambiare attraverso la configurazione o dynamicmente in fase di esecuzione (in genere a causa di alcuni schemi di progettazione)

4) Quando voglio che una class sia testabile, creo i suoi “punti di collegamento” alle interfacce delle risorse esterne, così da poter usare le implementazioni fittizie.

5) Meno comune: quando voglio avere un’opzione per limitare l’accesso ad alcune classi. In questo caso il mio metodo restituisce un’interfaccia invece della class effettiva, quindi il chiamante sa che non mi aspetto che faccia altre operazioni sul valore restituito.

No, ogni class non dovrebbe avere un’interfaccia. È overkill al quadrato.

Si utilizza un’interfaccia quando è necessario astrarre ciò che viene fatto da come è fatto e si è certi che l’implementazione può cambiare.

Dai un’occhiata all’API java.util Collections per un buon esempio. L’interfaccia List è una bella astrazione per l’idea generale di una List, ma puoi vedere che ci sono molti modi per implementarla: ArrayList, LinkedList, ecc.

AGGIORNAMENTO: Quindi, per quanto riguarda il caso in cui si progetta una class concreta, si decide dopo aver i client che è necessaria un’interfaccia e quindi si interrompono i client aggiungendo un’interfaccia? Sì, è quello che succede. Come puoi sapere cosa non sai? Nessun software o metodologia può risolverlo.

La buona notizia per te è che estrarre un’interfaccia da una class concreta è un facile rimodellamento da fare sia per te che per i tuoi clienti. Gli IDE gestiscono questo genere di cose regolarmente. Tu e i tuoi clienti dovreste approfittarne.

Direi che i livelli, come i servizi e la persistenza, dovrebbero sempre avere interfacce. Tutto ciò che può essere inviato con proxy dovrebbe avere un’interfaccia. Se stai facendo Spring AOP, tutto ciò che vuoi decorare con un aspetto dovrebbe avere un’interfaccia.

Gli oggetti modello o valore, come Persona o Indirizzo o Telefono, non dovrebbero avere un’interfaccia. Un object valore immutabile non dovrebbe avere un’interfaccia.

Il resto cade in aree grigie. Usa il tuo miglior giudizio.

Per farla breve, no. Sei il creatore dell’applicazione, quindi hai un’idea decente di cosa potrebbe cambiare. A mio avviso, alcuni dei modelli di design sono un po ‘pazzi, dal momento che sembrano spingere sempre il design verso interfacce e non implementazioni, non importa quale. A volte, è solo eccessivo. Per la mia ultima applicazione (di piccole dimensioni), ho un’interfaccia di database perché penso che ci sia la possibilità di portarla successivamente sul web e passare a MySQL. Naturalmente, in realtà, sarebbe facile creare un’interfaccia database in fondo alla strada dalla mia class esistente e aggiungere semplicemente “implementa myDbInterface” in seguito con un paio di piccole modifiche. Funziona perché io sono l’unico sviluppatore però. In una squadra più ampia o in un tipo diverso di prodotto, potrebbe essere una risposta diversa. Usa il tuo miglior giudizio (dopo aver letto tutte le risposte SO buone ovviamente).

Mi piace pensare che si utilizzino le interfacce quando è importante la connettività e il potenziale per un comportamento diverso. I servizi sono la soluzione perfetta. Si potrebbe volere un’implementazione predefinita, ma fingere (beffarsi) ecc. È un’altra. Questo ovviamente significa che ci dovrebbe essere un intf in quanto ci saranno sempre almeno 2 forms.

I tipi di valore d’altra parte dovrebbero essere le classi finali. Non dovrebbero mai essere estesi. I tipi di valore includono qualcosa come Suburb, MimeType. Se ci sono variazioni di queste composizioni d’uso. Come objective, cerco di mettere un po ‘di comportamento, se ce n’è uno, nei miei tipi di valore. Convalidare il tipo semplice che avvolge ecc. È probabilmente la cosa più complessa che fa. Ad esempio, una class di colors che accetta r / g / b dovrebbe verificare che ogni componente sia compreso tra 0 e 255 e questo sia.

Sì, usa l’interfaccia quando ti aspetti che un comportamento cambi. . In futuro.

O la tua class che può gestire i cambiamenti in modo chiaro.

per esempio.

public static void main(String s[]) { Employee e1=new Employee(new Salesman()); Employee e2=new Employee(new Manager()); system.out.println(e1.performaction()); system.out.println(e1.performaction()); } Class Employee { //which changes frequently Authority a; public Employee(Authority a) { this.a=a; } public String performAction() { a.action(); } } 

// ———————————————— ——————

 interface Authority { public String action(); } class Manager implements Authority { public String action() { returns "I manages People"; } class SalesMan implements Authority { public String action() { returns "I Sell things Company makes "; } }