La necessità di aggiungere un'interfaccia ad ogni classe [duplicato]

2

Il mio collega e io stiamo discutendo molto su questo argomento. Sta pensando che ogni singola classe dovrebbe avere un'interfaccia implementata dalla classe (anche le singole implementazioni). Usa questo disegno per i principi della documentazione. Nella mia mente è obsoleto perché in Java puoi anche commentare le implementazioni.

Penso che le interfacce siano necessarie solo lì, dove devi pubblicare qualche tipo di API aperta, per te come programmatore o per altre persone che in seguito collegheranno i loro progetti a questo punto di ancoraggio.

Inoltre sono a conoscenza di Mocking Objects, la cui libreria (ad es. EasyMock) richiede anche qualche interfaccia per creare un Mock.

Dal mio punto di vista, le interfacce per ogni classe non sono necessarie per ogni singola classe in JAVA. In altre lingue, inclusi alcuni Framework, potrebbe essere utile.

Forse potresti mostrarmi alcuni aspetti che non vedo dove possano essere utili le interfacce per ogni classe, o sono sulla strada giusta per negare questo principio di progettazione?

    
posta DmiN 04.05.2013 - 21:32
fonte

5 risposte

3

Un'unica interfaccia per ogni classe? Dalle grandi appendici, che odora di antipattern! Smontiamo alcune cose qui ...

In primo luogo, l'unica ragione un po 'valida per dare a tutto un'interfaccia è se si utilizza molto pesantemente il sistema proxy JRE integrato (che può costruire solo proxy per le interfacce). Tuttavia, se lo fai, puoi anche pensare in termini di utilizzo di sistemi di generazione di classi di runtime come la libreria asm per generare proxy rilevanti. (Se ti stai approfondendo, guarda come funzionano Spring e AspectJ.)

In secondo luogo, dovresti in realtà pensare molto di più al raggruppamento del codice in API chiaramente definite. Queste API dovrebbero essere definite da interfacce (e POJO rilevanti ed eccezioni, se necessario) in modo che si pensi esclusivamente in termini di ciò che l'API in realtà promette e garantisce. Utilizzare la disciplina di un pacchetto OSGi potrebbe essere una buona idea qui. Questo è anche il livello in cui fai davvero i tuoi test; questo è il livello in cui hai il test dell'unità black-box . Entrare nell'implementazione dell'API - test white-box dovrebbe essere ridotto al minimo, perché stai controllando le cose in quel caso che non dovrebbero essere osservabili nel mondo esterno. (Creare molte cose non osservabili è contro il principio YAGNI.)

Ovviamente, se si mantengono le implementazioni sottili in modo che ci sia un minimo di codice in più oltre alle effettive classi di implementazione dell'API diretta, è probabilmente una buona cosa in circostanze normali. Aggiungere quantità eccessive di astrazione non fa altro che renderti più confuso!

    
risposta data 04.05.2013 - 21:59
fonte
1

Oh cielo, non so da dove cominciare ...

Non aggiungi un'interfaccia a una classe. Implementa un'interfaccia codificando una classe.

Diciamo solo che ho imparato ad apprezzare la codifica delle interfacce invece delle classi per una moltitudine di ragioni. Elevata coesione, design di accoppiamento ridotto e testabilità sono i più importanti.

La testabilità è notevolmente migliorata utilizzando le interfacce. Anche la testabilità è notevolmente migliorata dall'inversione di dipendenza. E l'inversione di dipendenza sembra essere molto più semplice quando si usano le interfacce. (Sto parlando del principio qui, non di framework, contenitori o librerie).

Le interfacce e l'inversione delle dipendenze consentono di creare classi di stub test personalizzate per le interfacce da cui dipende l'interfaccia / classe sotto test, senza doversi preoccupare delle parti di una classe "usata" su cui non si fa affidamento nell'interfaccia / classe sotto test. (Si noti che non uso il mocking, nelle parole di Martin Fowler sono un tester classicista, che usa le classi stub per isolare la classe sottoposta a test da dipendenze esterne.)

Quindi anche quando un'interfaccia avrà sempre una sola implementazione "reale", avrà presto un paio di implementazioni di stub di test quando sarà utilizzata da almeno un'altra classe che implementa un'altra interfaccia.

In effetti, oggi collaudo le unità di codice contro le interfacce e collaudo una / ogni classe di implementazione registrando una classe discendente della classe di test e configurandola per utilizzare la classe di implementazione e qualsiasi stub di test di cui potrebbe aver bisogno. Assicurando così che tutte le implementazioni siano testate contro lo stesso "contratto".

Codificare i test contro le interfacce aiuta anche a concentrarsi sul comportamento desiderato ed evita di essere distratto dai dettagli di implementazione della classe sotto test.

    
risposta data 04.05.2013 - 22:29
fonte
1

Sul pavimento del carrello penso che dovresti fare una domanda più astratta, ad esempio, che cosa dovrei esporre nella mia API?.

Dopo aver definito chi vuole davvero conquistare il percorso diventa più facile.

Informazioni su interfacce e classi, non esiste una regola che dica efficacia al 100%. Dipenderà in qualche modo dalle esigenze del tuo progetto.

    
risposta data 05.05.2013 - 00:52
fonte
0

Come accenni alla tua domanda, il grande vantaggio di esporre le classi solo attraverso le interfacce è quando si arriva al test unitario, in particolare ai test automatici.

Se testi una particolare classe e costruisci una particolare interfaccia attraverso la quale si accede alla classe, allora non solo la classe stessa implementerà l'interfaccia, ma qualsiasi componente "mocking" implementerà anche quell'interfaccia.

Dopo aver detto tutto questo, ho pensato anch'io a questo, e non sono sicuro che sia qualcosa che comprerei in entrambi!

    
risposta data 04.05.2013 - 22:41
fonte
0

Penso che la prima domanda da porre sia su cosa sono le interfacce. Le interfacce sono contratti che esponi a chiunque usi il tuo modulo, incluso te stesso (in un altro modulo). Segnano i confini in cui i dettagli dell'implementazione possono non essere così importanti e possono essere scambiati senza interrompere il contratto. Mentre le lezioni sono dettagli concreti, e implementano l'interfaccia del contratto promessa.

Quindi, se segui questa strada, definire un'interfaccia per la classe ogni è decisamente sovraordinata. Ovviamente le interfacce possono anche essere usate come un tipo di tag, come "Serializable". Ma questo tipo di utilizzo è sostituito da annotazioni dopo java 5.

    
risposta data 04.05.2013 - 22:58
fonte

Leggi altre domande sui tag