L'uso di DI / IoC dovrebbe rimuovere tutte le occorrenze della "nuova" parola chiave?


21

L'utilizzo di Dependency Injection e un contenitore Inversion of Control dovrebbe rimuovere tutte le occorrenze della newparola chiave " " dal codice?

In altre parole, ogni oggetto / dipendenza, non importa quanto semplice o di breve durata, dovrebbe essere "registrato" all'interno del tuo contenitore IoC e iniettato nel metodo / classe che deve usarli?

Se no, dove traccia la linea tra le quali dipendenze / oggetti vengono registrati nel contenitore IoC, rispetto a ciò che viene creato "in linea" come riferimento concreto, tramite la newparola chiave?


Ho avuto lo stesso pensiero, sulla falsariga di "è 'nuovo' una parola di 4 lettere?"
Michael Easter,

Risposte:


27

Evita il dogma. Fai ciò che ti sembra giusto.

Preferisco usare "nuovo" per strutture di dati che non hanno alcun comportamento.

Se la classe ha un comportamento, allora guardo l'ambito di quel comportamento. Se è apolide e non ha dipendenze, mi sposto verso il "nuovo". Inizio il refactoring verso DI quando ho bisogno di aggiungere una dipendenza a risorse stateful (come un database o un file) o ad altre classi con tali risorse.


15
+1 per "evitare il dogma". Troppo facile cadere nella trappola del solo seguire i movimenti senza capire cosa sta succedendo o dove dovrebbe essere usato correttamente.
Wayne Molina,

@Alex Mi piace questo. Un approccio molto pragmatico. Stranamente, stavo per aggiungere un po 'di codice alla mia domanda che mostrava una newdipendenza nel mio codice che ha portato alla mia domanda. Era una classe semplice senza funzionalità o "comportamento" di per sé, solo proprietà semplici.
CraigTP,

11

Nel mio libro , fornisco la distinzione tra dipendenze stabili e volatili . È molto importante utilizzare DI con Dipendenze volatili, ma spesso è possibile ottenere un accoppiamento ancora più libero astrattando e iniettando Dipendenze stabili.

Tieni presente che l'applicazione di DI non deve fare affidamento su un contenitore DI . Nel caso in cui il DI di Poor Man sia in uso, non newvengono rimosse parole chiave: vengono semplicemente spostate nella Root di composizione .

Alcune persone in realtà preferiscono DI Poor Man su DI Containers. Il costo di manutenzione potrebbe essere più elevato, ma in cambio si ottiene la sicurezza in fase di compilazione. Come ho sentito di recente Dan North dire: " newè il nuovo new" :)

Ciò che si intende con questo è semplicemente che invece di implementare la Composizione Root con un contenitore DI, conterrebbe solo un intero gruppo di newistruzioni nidificate .


Mark, per ampliare un po 'il mio commento su Twitter , i programmatori sono il posto giusto per domande concettuali e da lavagna che non hanno a che fare con un errore specifico in un'implementazione.
Adam Lear

3
Stack Overflow ha oltre 2000 domande nel tag di iniezione delle dipendenze, e molte di queste sono come questa. I programmatori hanno 23 domande nello stesso tag. Sulla base di questi numeri, dove dovrebbe andare uno sviluppatore per avere le maggiori possibilità di ottenere una risposta a una domanda come questa?
Mark Seemann,

1
Molte di queste domande sono completamente precedenti ai programmatori. Questo sito è stato creato per togliere domande concettuali da SO e dare loro una casa dedicata. E stiamo ancora crescendo. È un work in progress, ma idealmente le domande che non comportano specifici problemi di implementazione verrebbero migrate qui. Nel frattempo facciamo ciò che possiamo.
Adam Lear

3

"nuovo" non è una parola chiave proibita. Le mie regole personali:

Tutti i "servizi" (chiamo un servizio una classe progettata per fornire uno o più metodi relativi a una sola cosa, ad esempio: accedere al database, recuperare / aggiornare i dati relativi a un determinato dominio) sono registrati nel contenitore IOC. Nessuna classe dovrebbe prendere la decisione su come ottenere l'implementazione di un determinato servizio che deve usare. Pertanto, ogni volta che è necessario utilizzare un servizio esistente, è necessario configurare la classe e il contenitore IOC per fornirlo. Immagina di non essere consapevole di come funziona la tua implementazione, potrebbe essere un servizio web, non ti interessa.

Tutti i bean o i modelli devono essere creati con la "nuova" parola chiave o con una fabbrica registrata IOC quando ne ho bisogno per abilitare alcune proprietà predefinite. Esiste anche il caso particolare di classi di utilità che contengono solo metodi statici (ad esempio: un servizio di utilità matematica). Se sono totalmente autonomi e non necessitano di alcuna connessione al database o di un altro servizio registrato dal CIO, li lascio fuori dal CIO e devono essere chiamati staticamente. Tuttavia, se una di queste classi deve utilizzare un servizio IOC registrato esistente, lo cambio in una classe singleton e lo registro nel CIO.


2

Vorrei solo aggiungere alle risposte esistenti che sono state sollevate in precedenza, newva benissimo creare oggetti che sono oggetti di puro valore (cioè hanno solo proprietà / getter / setter). Vedi il Blog dei test di Google per maggiori dettagli.


+1 per il collegamento. Il punto 9 di quel post sul blog risponde alla domanda e fornisce una distinzione pragmatica tra ciò che dovrebbe e non dovrebbe essere new'ed
CraigTP

1

Dipende chiaramente dalla lingua che usi. Se il tuo linguaggio ti costringe a utilizzare gli oggetti per rappresentare sia l'oggetto reale sia i record (oggetto valore, strutture), la risposta è molto probabilmente no.

Parlando solo di oggetti "reali", non c'è nulla di sbagliato nel creare esplicitamente un'istanza. Ciò che devi tenere a mente, tuttavia, è che tutte le classi dovrebbero seguire il principio della singola responsabilità. Non dovrebbe essere responsabilità di una classe scegliere l'implementatore di un servizio su cui si basa. Tuttavia ci sono classi che hanno quella stessa responsabilità, cioè fornire attuatori di determinati servizi. Un IoC potrebbe essere tale classe. In effetti ogni tipo di fabbrica è una tale classe.

Riassumendo: solo tali classi dovrebbero istanziare direttamente gli oggetti, chi ha la responsabilità di scegliere quali classi istanziare.
Potresti trovare utili questi criteri: http://en.wikipedia.org/wiki/GRASP_(object-oriented_design)#Creator


1

Una sola parola: no

Più parole: l'iniezione di dipendenza è esattamente questo. È un mezzo con cui si introducono risorse da cui dipende un altro oggetto, ma che non è necessario conoscere i dettagli intricati di un'altra fonte. L'uso di DI non significa che NIENTE nel tuo programma dovrebbe sapere come creare qualsiasi altro oggetto; in effetti, ritengo che sia altamente impossibile per un programma non banale evitare completamente la "nuova" parola chiave (o alternative basate sulla riflessione). Tuttavia, DI significa che gli oggetti che non devono DOVERE sapere come creare oggetti complessi che richiedono molte dipendenze che accoppieranno strettamente questo oggetto all'altro, non dovrebbero avere tutte queste conoscenze strettamente legate.

Vorrei studiare le due principali teorie sulla progettazione di software O / O, GRASP e SOLID. GRASP ti dirà di studiare lo scopo dell'oggetto e chiederti: "Questo oggetto dovrebbe essere responsabile della creazione di nuovi oggetti di questo altro tipo? Fa parte della" descrizione del lavoro "di questo oggetto?" SOLID fa un ulteriore passo avanti: la "S" sta per "Principio di singola responsabilità", che afferma inequivocabilmente che un oggetto dovrebbe avere un lavoro e dovrebbe essere l'unico oggetto nel programma che fa quel lavoro specifico.

Pertanto, GRASP in genere ti incoraggerebbe a esaminare le classi esistenti per le quali creare questi nuovi oggetti e trovarne uno per cui il compito di creare questo oggetto si adatta a ciò che l'oggetto fa già, mantenendo il livello desiderato di "coesione". SOLID ti dirà che la coesione è la chiave; il compito di creare questi oggetti dovrebbe essere affidato a qualche factory che dovrebbe essere iniettato nella tua classe. Penso che scoprirai, mentre la complessità del tuo programma continua a crescere, che l'adesione a una di queste metodologie, con la volontà di refactoring, porterà a architetture molto simili.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.