Is Dependency Injection vale la pena al di fuori del test unitario

17

Dato un costruttore che non dovrà mai e poi mai usare diverse implementazioni di diversi oggetti che inizializza, è ancora pratico usare DI? Dopotutto, potremmo ancora voler testare le unità.

La classe in questione inizializza alcune altre classi nel suo costruttore e le classi che usa sono piuttosto specifiche. Non userà mai un'altra implementazione. Siamo giustificati nell'evitare di provare a programmare su un'interfaccia?

    
posta Seph 23.09.2013 - 13:00
fonte

8 risposte

13

Dipende da quanto sei sicuro che "mai, mai" sia corretto (durante il periodo di utilizzo della tua app).

In generale:

  • Non modificare la progettazione solo per la testabilità. I test unitari sono lì per servirti, non viceversa.
  • Non ripeterti. Creare un'interfaccia che avrà sempre un solo erede è inutile.
  • Se una classe non è testabile, probabilmente non è flessibile / estensibile nemmeno per casi reali. A volte va bene - è improbabile che tu abbia bisogno di quella flessibilità, ma semplicità / affidabilità / manutenibilità / prestazioni / qualsiasi cosa è più importante.
  • Se non lo sai, codifica sull'interfaccia. Modifica dei requisiti.
risposta data 23.09.2013 - 13:49
fonte
12

Are we justified in avoiding trying to program to an interface?

Sebbene il vantaggio di codificare su un'interfaccia sia piuttosto evidente, dovresti chiederti che cosa si ottiene esattamente non facendolo.

La prossima domanda è: fa parte della responsabilità della classe in questione scegliere o meno le implementazioni? Potrebbe essere o non essere il caso e dovresti agire di conseguenza.

In fin dei conti, c'è sempre il potenziale per alcuni stupidi vincoli a venire fuori dal nulla. Si consiglia di eseguire contemporaneamente la stessa parte di codice e la possibilità di iniettare l'implementazione potrebbe aiutare con la sincronizzazione. Oppure, dopo aver profilato la tua app, potresti scoprire che desideri una strategia di allocazione diversa dalla semplice istanza. Oppure sorgono preoccupazioni trasversali e non hai il supporto AOP a portata di mano. Chi lo sa?

YAGNI suggerisce che durante la scrittura del codice, è importante non aggiungere nulla di superfluo. Una delle cose che i programmatori tendono ad aggiungere al loro codice senza nemmeno esserne a conoscenza, sono supposizioni superflue. Come "questo metodo potrebbe tornare utile" o "questo non cambierà mai". Entrambi aggiungono confusione al tuo design.

    
risposta data 23.09.2013 - 13:36
fonte
7

Dipende da vari parametri, ma qui ci sono alcuni motivi per cui potresti ancora voler usare DI:

  • test è una buona ragione di per sé, credo
  • le classi richieste dall'oggetto potrebbero essere utilizzate in altri luoghi - se le si inietta, consente di raggruppare le risorse (ad esempio se le classi in questione sono thread o connessioni al database) non si desidera che ciascuna delle classi per creare nuove connessioni)
  • se l'inizializzazione di quegli altri oggetti può fallire, il codice più in alto nello stack sarà probabilmente meglio affrontare i problemi rispetto alla tua classe, che quindi probabilmente semplicemente inoltrerà gli errori

In conclusione: probabilmente puoi vivere senza DI in quel caso, ma ci sono possibilità che l'utilizzo di DI finirà con un codice più pulito.

    
risposta data 23.09.2013 - 13:31
fonte
3

Quando progetti un programma o una funzione, parte del processo di pensiero dovrebbe essere come lo testerai. La dipendenza dall'iniezione è uno degli strumenti di test e dovrebbe essere considerata parte del mix.

Gli ulteriori vantaggi di Dipendenza dell'iniezione e l'uso di interfacce invece di classi sono utili anche quando un'applicazione viene estesa, ma possono anche essere adattati al codice sorgente in un secondo momento in modo abbastanza semplice e sicuro utilizzando la ricerca e la sostituzione. - anche su progetti molto grandi.

    
risposta data 23.09.2013 - 14:07
fonte
2
 > Dependency Injection worth it **outside** of UnitTesting?
 > Are we justified in avoiding trying to program to an interface?

Molte risposte a questa domanda possono essere discusse come "potresti averne bisogno perché .." come YAGNI se non vuoi fare l'unittest.

Se ti stai chiedendo quali sono i motivi per cui le unittests richiedono di programmare su un'interfaccia

, Dipendenza dalla iniezione vale la pena fuori di UnitTesting se hai bisogno di inversione di controllo . Ad esempio, se un'implementazione di un modulo richiede un altro modulo che non è accessibile nel suo livello.

Esempio: se hai i moduli gui = > businesslayer = > driver = > common .

In questo scenario businesslayer può utilizzare driver ma driver non può utilizzare businesslayer .

Se driver ha bisogno di alcune funzionalità di livello superiore, puoi implementare questa funzionalità in businesslayer che implementa un'interfaccia in common layer. driver deve solo conoscere l'interfaccia in common layer.

    
risposta data 23.09.2013 - 17:15
fonte
1

Sì. In primo luogo, dimenticando il test delle unità come motivo per progettare il codice attorno agli strumenti di test delle unità, non è mai una buona idea piegare la progettazione del codice per adattarla a un vincolo artificiale. Se i tuoi strumenti ti costringono a farlo, ottieni strumenti migliori (ad esempio Microsoft Fakes / Moles che ti consentono molte più opzioni per la creazione di oggetti mock).

Ad esempio, divideresti i tuoi corsi in metodi solo pubblici solo perché gli strumenti di test non funzionano con metodi privati? (So che la saggezza prevalente è fingere che non sia necessario testare metodi privati, ma ritengo che questa sia una reazione alla difficoltà nel farlo con gli strumenti attuali, non una reazione genuina a non dover testare i privati).,

Tutto sommato si tratta di che tipo di TDDer sei - il "mockist" come Fowler descrive s loro , è necessario cambiare il codice per adattarsi agli strumenti che usano, mentre i tester "classici" creano test che sono più di integrazione (cioè test la classe come unità, non ogni metodo), quindi c'è meno bisogno di interfacce, specialmente se usi gli strumenti che possono prendere in giro lezioni concrete.

    
risposta data 23.09.2013 - 15:28
fonte
1

Iniezione delle dipendenze rende anche più chiaro che le tue dipendenze HA .

Quando qualcun altro va a usare il tuo oggetto in modo ingenuo (senza guardare il costruttore), scoprirà che dovrà impostare servizi, connessioni, ecc. Non erano ovvi perché non dovevano passarli al costruttore. Passare nelle dipendenze rende più chiaro ciò che è necessario.

Inoltre stai potenzialmente nascondendo il fatto che la tua classe potrebbe violare SRP. Se stai passando molte dipendenze (più di 3), la tua classe potrebbe fare troppo e dovrebbe essere sottoposta a refactoring. Ma se li stai creando nel costruttore, questo odore di codice sarà nascosto.

    
risposta data 23.09.2013 - 17:33
fonte
0

Sono d'accordo con entrambi i campi qui e la questione è ancora aperta per il dibattito a mio parere. YAGNI richiede che non affronti il cambiamento del mio codice per adattarlo alle supposizioni. Il test unitario non è un problema qui perché credo fermamente che la dipendenza non cambierà mai, mai. Ma se fossi stato un test unitario come previsto, non avrei comunque raggiunto questo punto. Come mi sarei finalmente trasformato in DI.

Consentitemi di offrire un'altra alternativa per il mio scenario in particolare

Con un modello factory posso localizzare le dipendenze in un posto. Durante i test posso cambiare l'implementazione in base al contesto, e questo è abbastanza buono. Questo non va contro YAGNI a causa dei vantaggi dell'astrazione di diverse costruzioni di classe.

    
risposta data 24.09.2013 - 20:43
fonte

Leggi altre domande sui tag