Costruisci entità tramite il quadro dell'iniezione delle dipendenze

1

Ho bisogno di aiuto per risolvere un disaccordo, un collega e io ho. Stiamo lavorando a un progetto Angular piuttosto vasto e stiamo cercando di incorporare alcuni principi di Domain Driven Design nel nostro progetto.

Mentre guardavamo questa immagine, abbiamo discusso di come il nostro quadro dell'iniezione delle dipendenze avrebbe contribuito a questo.

Lamiaposizione:iFrameworkdell'iniezionedelledipendenzedevonoessereutilizzatisoloperserviziapplicativi,servizididominio,archiviefabbriche.Alcontrario,glioggettidominisonofondamentalmentenuovi(anchesenontipicamentenuovi,tranneall'internodiunafactory)enonhannoalcunadipendenzadelcostruttore.
Lasuaposizione:èimpossibile,perchéabbiamounDI-Frameworkedovremmousarlo.Lasuapaurasonoenormiclassidimonoliti.Sostienechequandoleclassihannotroppimetodièperfettamentenormaledividerliinclassipiùpiccole(acausadell'SRP)eraggrupparliinunasortadiclassestrumentale.Questosarebbeunlavorodiroutinesenzainiezionedidipendenza.SostienecheiDI-Frameworksononormalidausareinogniprogettopiùgrande,enonusarequantoèpossibileèsciocco.
Perchéècosìdifficilepermeconvincerlo:Lavoriamoconletabellemoltoec'èunaclasse,chepiùomenorappresentail'modello'diunatabella(ignoraperunsecondo,chenellamaggiorpartedeiprogettiuna'tabella'nonfarealmentepartedeldominiodelproblema,eaccettalapremessa,chepotrebbeesserenelnostro).Oraprimaditutto-ancheseinostridatielenostretabellefosserosemplici-unaclassecherappresentaunatabellaavrebbedozzinedimetodi.Tral'aggiuntaelarimozionedirighe,ilridimensionamentodicolonne,ilrecuperoel'impostazionedistaticomelaselezionedirighe,evidenziandolecolonnechecosahai.
Inoltre,anchelecosechesonoconvenzionalmentesemplici,comeaggiungereunariga,hannospesso5effetticollateralidiversisualtrepartidellatabella(questisonoirequisitieffettivi).Quindipensochetuttivoisiated'accordo,cheavereunaclassedatavolodi4000righesiainaccettabile.Diconseguenza,dobbiamospostarealcunedellesuefunzionalitàinclassipiùpiccole,chefannosolounacosa,oanchesolounapartediunacosa.Eorasiamoinunvicolocieco.Pensochequestodebbaancoraessereunalezionesenzaun'iniezionedidipendenza,manonsocomefarloedèirremovibile,chestosoloimmaginandoquestocomeunproblemaevogliofocalizzareiservizinellaclasse,chefannoilavori,chedovrebbeconvenzionalmentefarlodasé.

Quindisonopazzo?Èpazzo?Inoltre,senonseid'accordoconlui,ottienipuntibonusperilcollegamentodifontiaffidabili,perché"chiunque può scrivere qualsiasi cosa su StackOverflow"

    
posta KeTr 27.09.2018 - 18:19
fonte

2 risposte

1

Se dovessi essere guidato da YAGNI , non penso che ti raggiungerebbe mai il punto in cui introdurre l'iniezione di dipendenza negli oggetti del dominio.

L'iniezione di dipendenza è una manifestazione del modello strategico; il valore di avere dipendenze iniettabili è che è possibile sostituire un comportamento con un altro. Ovviamente, il modo più semplice per sostituire un comportamento con un altro è semplicemente riscrivere il metodo in questione, quindi ciò che realmente significa è che vogliamo supportare due (o più) comportamenti candidati e essere in grado di per fare quella scelta dall'esterno.

L'esempio classico sarebbe un'interfaccia con effetti collaterali - ad esempio, per inviare un'email. In produzione, ci connettiamo davvero a un server SMTP; in prova, facciamo solo finta. Quindi vorremmo essere in grado di controllare il comportamento dall'esterno.

Gli oggetti di dominio sono in rappresentazioni di memoria delle aziende che stanno modellando. Non hanno effetti collaterali (diretti). Il richiamo di un metodo su un oggetto dominio di solito legge o scrive nella memoria privata del processo.

Quando vogliamo includere gli effetti collaterali come parte del lavoro svolto dal modello di dominio, passiamo la capacità come argomento al metodo che stiamo chiamando. Questo è uno dei ruoli dei servizi di dominio: agire come proxy per il mondo esterno.

Poiché il modello di dominio stesso non ha effetti collaterali, i benefici che normalmente si ottengono dall'isolare un soggetto del test dal suo ambiente di solito non si applicano. A meno che la logica del tuo dominio sia estremamente complicata, non otterrai molto dalla semplificazione del grafico delle chiamate.

Vedi il discorso di Ian Cooper TDD: dove tutto è andato storto per ulteriori discussioni sulla variazione del test.

L'altro aroma di variazione che può essere interessante è la variazione della struttura dei dati - questo valore nel tuo modello di dominio può essere un elenco collegato o un elenco di matrici, o forse un ammasso .... In una certa misura, l'intero punto di "oggetti valore" è quello di astrarre dalla logica del dominio le preoccupazioni su come i dati sono disposti in memoria.

Nelle lingue che richiedono di essere specifici sui tipi (Java, ad esempio), le interfacce che è necessario scrivere per supportare la sostituzione di grafici di oggetti valore sono complicate - le varianti di tipo non vengono incapsulate. Quindi davvero devi volerlo.

Le probabilità di investimento sono pessime per introdurre l'iniezione di dipendenza nel tuo modello di dominio prima che tu ne abbia una dimostrata necessità. Il problema è che la probabilità di un pagamento è piccola, e fare presto il lavoro non migliora in modo significativo il rapporto payoff / costo.

This... is wrong tool. -- Zathras

Link

risposta data 28.09.2018 - 14:28
fonte
0

Penso che sia d'aiuto in situazioni come queste fare un passo indietro e porre una domanda, quella domanda è "perché usiamo questo pattern / framework / strumento?". Trovo che molta della confusione intorno ai pattern in generale e alla DI in particolare derivi davvero da molta pressione per usare un pattern senza uno specifico rapporto costo / beneficio.

Il vantaggio principale dell'integrazione delle dipendenze è quello di separare una classe dalle sue dipendenze, rendendo possibile l'uso della classe in nuovi contesti in cui è possibile utilizzare una diversa implementazione della capacità fornita dalla dipendenza. (Wikipedia lo descrive più in dettaglio nel link ) L'esempio canonico è il livello di persistenza. Oggi, il mio servizio può ricevere dati da un database SQL ma forse domani voglio che lo estragga da un servizio web.

La maggior parte dei vantaggi che ascolterai sono casi speciali di questa capacità di sostituire le implementazioni di dipendenza. In pratica trovo che la maggior parte delle basi di codice che usano la DI lo fanno per il test delle unità. Se un componente del servizio si basa su un componente del repository che viene iniettato, è più facile sostituire il repository con un mock o uno stub per il test dell'unità.

Per essere chiari, DI ha anche degli svantaggi, il più grande è l'aumento della complessità che spesso si traduce in una minuscola quantità di sovraccarico nel sistema in esecuzione e una maggiore complessità durante la lettura del codice a causa degli ulteriori livelli di riferimento indiretto.

Ora che vediamo i problemi che DI cerca di risolvere, possiamo essere chiari su quello che non risolve, ovvero la costruzione di oggetti. Non c'è niente di sbagliato in new . Non è rotto Fa quello che dice sullo stagno: crea nuove istanze di una classe. Quindi la semplice creazione di un oggetto non è un motivo adeguato per usare DI. Dobbiamo risolvere per la capacità di sostituire le implementazioni di capacità.

È questo il caso degli oggetti modello / dati? Tipicamente no. Rappresentano in genere dati e hanno relativamente poca capacità di alcun tipo. Se non c'è niente da iniettare, non c'è motivo di usare l'iniezione di dipendenza. (A titolo di chiarimento, dovrei notare che solo la composizione di oggetti non è la stessa cosa che rappresenta una dipendenza di componente: un Person può avere un Address , ma potrebbe essere solo un attributo di Person - non è necessario che un Person dipenda da un Address ).

Su una nota meno astratta, meno teorica, è anche importante rendersi conto che molte librerie / framework per le dipendenze dipendono pesantemente dai singleton (questo comportamento dipende dal framework DI in uso e da come è configurato - per esempio, Spring è singleton-by-default, ma può essere configurato anche con altri comportamenti: è sufficiente conoscere lo stack). In effetti, la riduzione delle istanze attive viene talvolta citata come un vantaggio. Ciò significa che potresti involontariamente terminare con più parti di codice che mutano lo stesso modello / oggetto dati. In questo caso, possono verificarsi tutti i tipi di problemi casuali e condizioni di gara. In caso contrario, stai semplicemente utilizzando il framework DI per implementare una factory e potrebbe essere più chiaro ai manutentori della base di codice se la factory è separata dal codice di configurazione.

Il che mi porta al mio ultimo punto principale. L'iniezione di dipendenza è strongmente legata all'idea di configurazione e la configurazione del sistema produrrà grafici di oggetti diversi. Di solito non c'è molto in termini di configurazione nelle classi modello / dati.

Riepilogo: troverei strano vedere gli oggetti modello o dati costruiti tramite l'integrazione delle dipendenze, poiché in genere non rappresentano componenti con dipendenze, né generalmente hanno un aspetto sensibile alla configurazione. Infine, mi aspetto di creare e scartare regolarmente le istanze, cosa che non funziona bene con la mentalità singleton-first della maggior parte dei framework DI.

Consiglio vivamente di leggere la descrizione del pattern di Martin Fowler ( link ) e alcune discussioni su StackOverflow (< a href="https://stackoverflow.com/questions/871405/why-do-i-need-an-ioc-container-as-opposed-to-straightforward-di-code"> link essendo uno dei più interessanti per me) per alcune buone prospettive su cosa sia DI e perché possa o meno applicarsi a un determinato caso d'uso.

    
risposta data 27.09.2018 - 21:59
fonte

Leggi altre domande sui tag