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

21

Se l'utilizzo di Dependency Injection e un contenitore Inversion of Control rimuovono tutte le occorrenze tutte della parola chiave " new " dal tuo codice?

In altre parole, ogni oggetto / dipendenza, indipendentemente da quanto semplice o di breve durata, deve essere "registrato" all'interno del proprio contenitore IoC e inserito nel metodo / classe che deve essere utilizzato?

Se no, dove disegna la linea in cui le dipendenze / oggetti vengono registrati nel contenitore IoC, rispetto a ciò che viene creato "in-line" come riferimento concreto, tramite la parola chiave new ?

    
posta CraigTP 18.08.2011 - 13:39
fonte

6 risposte

27

Evita il dogma. Fai quello che sembra giusto.

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

Se la classe ha un comportamento, allora osservo l'ambito di tale comportamento. Se è apolide e non ha dipendenze, mi propongo verso "nuovo". Ho solo iniziato a rifattorizzare 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.

    
risposta data 18.08.2011 - 13:49
fonte
11

In mio libro , fornisco la distinzione tra Stabile e Dipendenze variabili . È più importante utilizzare la DI con le dipendenze volatili, ma spesso è possibile ottenere un accoppiamento ancora più sciolto anche mediante l'astrazione e l'iniezione di dipendenze stabili.

Tieni presente che l'applicazione di DI non deve basarsi su un contenitore DI . Nel caso in cui DI Povero sia in uso, non vengono rimosse le parole chiave new - vengono semplicemente spostate nel Composizione root .

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

Il significato di questo è semplicemente che invece di implementare la Composizione radice con un contenitore DI, dovrebbe contenere solo un gruppo di istruzioni% co_de nidificate.

    
risposta data 18.08.2011 - 14:29
fonte
3

"nuovo" non è una parola chiave vietata. 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 essere utilizzata. Pertanto, ogni volta che è necessario utilizzare un servizio esistente, è necessario configurare la classe e il contenitore IOC per fornirlo. Immagina di non sapere come funziona la tua implementazione, potrebbe essere un servizio web, non ti interessa.

Tutti i bean, oi modelli devono essere creati con la parola chiave "new" o con un factory registrato dallo IOC quando ho bisogno che abbiano alcune proprietà predefinite abilitate. C'è anche il caso particolare di classi di utilità contenenti solo metodi statici (ad esempio: un servizio di utilità matematica). Se sono totalmente standalone e non hanno bisogno di alcuna connessione al database o di un altro servizio registrato dallo IOC, li lascio fuori dall'IOOC e devono essere chiamati staticamente. Tuttavia, se una di queste classi ha bisogno di utilizzare un servizio esistente con IOC, lo cambio in una classe singleton e lo registro nel CIO.

    
risposta data 18.08.2011 - 14:12
fonte
2

Vorrei solo aggiungere alle risposte esistenti che sono state introdotte, e new è perfettamente adatto per creare oggetti che sono oggetti di puro valore (cioè hanno solo proprietà / getter / setter). Consulta il Blog di test di Google per ulteriori dettagli.

    
risposta data 18.08.2011 - 18:14
fonte
1

Dipende chiaramente dalla lingua che usi. Se il tuo linguaggio ti obbliga a usare oggetti per rappresentare sia oggetti reali che record (oggetto valore, strutture), allora la risposta è molto probabilmente no.

Parlando esclusivamente di oggetti "reali", non c'è niente di sbagliato nel creare un'istanza esplicitamente. Tuttavia, ciò che devi tenere a mente è che tutte le classi dovrebbero seguire il principio della responsabilità unica. Non dovrebbe essere responsabilità di una classe scegliere l'implementatore di un servizio su cui fa affidamento. Tuttavia ci sono classi che hanno questa stessa responsabilità, cioè fornire implementatori di determinati servizi. Un IoC potrebbe essere tale classe. In realtà qualsiasi tipo di fabbrica è una tale classe.

Quindi riassumendo: solo tali classi dovrebbero creare istantaneamente degli oggetti, la cui responsabilità è scegliere quali classi istanziare.
Potresti trovare questi criteri utili: link

    
risposta data 18.08.2011 - 14:05
fonte
1

Una parola: no.

Altre parole: l'iniezione di dipendenza è esattamente quella. È un mezzo attraverso il quale si introducono risorse da cui dipende un altro oggetto, ma non si dovrebbero conoscere i dettagli intricati di, da un'altra fonte. Usare DI non significa che NULLA 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 parola chiave "nuova" (o le alternative basate sulla riflessione). Tuttavia, DI vuol dire che gli oggetti che NON DEVONO sapere come creare oggetti complessi che richiedono molte dipendenze che accoppieranno strettamente questo oggetto all'altro, non dovrebbero avere tutte queste conoscenze strettamente accoppiate.

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 chiediti: "Questo oggetto dovrebbe essere responsabile della creazione di nuovi oggetti di questo altro tipo? Questa parte della 'descrizione del lavoro' di questo oggetto?" SOLID fa un passo in più: la "S" sta per "Principio di singola responsabilità", che afferma in modo inequivocabile che un oggetto dovrebbe avere un lavoro, e dovrebbe essere l'unico oggetto nel programma che fa quel lavoro specifico.

Quindi, GRASP generalmente ti incoraggia a guardare attraverso le tue classi esistenti per cui creare questi nuovi oggetti, e trovare quello per cui il compito di creare questo oggetto si adatta a quello che l'oggetto già fa, mantenendo il livello desiderato di "coesione" ". SOLID ti dirà che la coesione è la chiave; il compito di creare questi oggetti dovrebbe essere dato ad una fabbrica che dovrebbe essere iniettata nella tua classe. Penso che troverai, mentre la complessità del tuo programma continua a crescere, che l'aderenza a una di queste metodologie, con la volontà di refactoring, si tradurrà in architetture molto simili.

    
risposta data 18.08.2011 - 16:34
fonte

Leggi altre domande sui tag