Devo scrivere un'interfaccia API prima di un'implementazione?

14

Recentemente ho approfondito una programmazione più "organizzata" e ho imparato che dovrei programmare un'interfaccia, non un'implementazione. Con questo in mente, sarebbe meglio "abbozzare" un progetto nelle interfacce prima di scrivere l'implementazione per quanto possibile?

E se questo è il caso, nel caso di usare librerie di terze parti (es. Lidgren), dovrei includere anche quelle nelle interfacce e risolverle attraverso i contenitori IOC, oppure è giusto esporle alle interfacce?

    
posta Dan Pantry 06.12.2013 - 10:47
fonte

5 risposte

8

Purtroppo, questo si riduce spesso alle preferenze personali.

Ciò che hai descritto finora, però, sembra buono. Infatti, se lo volessi (e lo raccomando) potresti utilizzare il seguente approccio:

  1. Scrivi lo scheletro dell'applicazione come interfacce, classi astratte (stubbed) e classi (anche stub)
  2. Scrivi i tuoi test su quelle interfacce e stub (non funzioneranno per ora)
  3. Scrivi le tue implementazioni (i test inizieranno a passare al termine della tua implementazione)

Ti stai concentrando sul tentativo di scrivere più codice "organizzato". Seguendo TDD ti aiuterò con questo.

Alcuni punti extra:

  • I contenitori IoC sono convenienti. Usali e DI il più possibile.
  • Fai racchiudi le librerie di terze parti. Questo allenterà l'accoppiamento tra il tuo codice (codice che controlli) e il codice di terze parti (codice che non controlli)
risposta data 06.12.2013 - 10:55
fonte
13

Sì, dovresti codificare le interfacce anziché le implementazioni conosciute, e sì, dovresti prima costruire interfacce piuttosto che farle emergere dal tuo codice.

Le ragioni di entrambe le raccomandazioni sono in gran parte le stesse: la programmazione per computer riguarda in gran parte i fattori umani. Molti trovano questo sorprendente, ma considerano: ci sono un numero quasi infinito di modi diversi per risolvere lo stesso problema informatico che funziona ugualmente bene. Quasi tutti sono assolutamente impossibili da dare un senso a chiunque non li abbia scritti (o di fatto all'autore poco tempo dopo).

Ne consegue che una buona ingegneria del software è in gran parte su come ottenere l'effetto desiderato (calcolo corretto con efficienza ragionevole) in un modo che consenta di utilizzare il codice sorgente in seguito. Le interfacce e le API sono una parte cruciale di tale disciplina: consentono di pensare a un problema a un livello di descrizione alla volta. Questo è molto più facile che pensare alle regole di coerenza aziendale e sulle implementazioni delle liste collegate contemporaneamente, e quindi imporre forzatamente tale separazione delle preoccupazioni è migliore che consentire al programmatore del client usare il tuo codice come preferisce.

Questo è difficile da credere per molti programmatori di cowboy, che sono convinti di comprendere tutto ciò che scrivono, sono molto migliori dei pensatori medi e possono gestire tutta la complessità che dà problemi ai programmatori "minori". Non essere consapevoli dei propri limiti cognitivi è un fenomeno estremamente comune - ecco perché le migliori pratiche nell'organizzazione del codice sono così estremamente importanti (e così spesso ignorate).

Per ripetere, le interfacce e le barriere API sono in gran parte buone , anche quando collabori solo con te stesso. Per quanto riguarda le librerie esterne, se portano con sé un'API ben ponderata, non vedo alcun problema nell'usarlo poiché è fin quando non si prevede di dover sostituire quella libreria con un'altra. Altrimenti, un wrapper o un layer anti-corruzione può essere un'ottima idea.

    
risposta data 06.12.2013 - 10:58
fonte
4

Piuttosto che servirsi semplicemente di programmazione per interfacce, perché non guardare in Test Driven Development / Design (TDD)?

Molte persone pensano che TDD sia una pratica di prova, ma in realtà è un approccio di progettazione in cui si lascia testare come verrà utilizzato il codice tramite test (inizialmente tramite test unitari, ma anche tramite test di integrazione).

La programmazione delle interfacce è un'arma importante nel tuo set di strumenti, ma come la maggior parte delle cose, non sempre è la soluzione / tecnica / pratica appropriata, poiché non è sempre necessaria. È necessario programmare le interfacce dove è necessario.

L'utilizzo di TDD ti costringerà ad esplorare dove tali interfacce sono importanti e dove, francamente, non ha importanza. E alla fine dovresti avere un bel set di test unitari sulla tua base di codice.

Per quanto riguarda l'utilizzo di librerie di terze parti, ti consiglio vivamente di includerle nelle tue astrazioni, se necessario; e non lasciare che i clienti della tua API "sappiano" di loro.

Buona fortuna!

[modifica: segna la risposta di megaflight - completamente d'accordo]

    
risposta data 06.12.2013 - 11:32
fonte
2

Penso che sia eccessivo. Se l'utente della tua API non ha bisogno di essere forzato ad implementare / utilizzare qualcosa in un certo modo, lo lascerei fuori. Le interfacce sono contratti, se non ne ho bisogno, allora perché darmene uno?

Penso che le persone usino troppo le interfacce. Stai aggiungendo un livello di complessità che non è necessario nella maggior parte dei casi.

    
risposta data 06.12.2013 - 17:47
fonte
1

Programmare contro un contratto è quasi sempre una buona idea. Questo contratto non deve essere un'interfaccia, ma può essere soddisfatto da una classe. A mio parere, le interfacce sono diventate alquanto abusate insieme a DI a causa di problemi di testing unitario e strutture di derisione.

Personalmente preferisco portare solo interfacce quando molto probabilmente potrei avere o avere più di 1 implementazione di un contratto. Le interfacce sono ottime per i repository in cui desidero astrarre l'accesso ai dati, ma probabilmente meno per la mia logica aziendale standard, che è probabilmente relativamente poco flessibile.

Ora non avere un'interfaccia può causare problemi con i test delle unità, specialmente per i puristi. Ma mi interessa prendere in giro le dipendenze esterne dei miei programmi, non le sue dipendenze interne. Voglio che i miei test eseguano la convalida del codice, non fanno eco alla struttura del codice.

    
risposta data 07.12.2013 - 00:26
fonte