Le classi IOC inquinano il mio progetto

4

Dire che ho un'app C #, che è a strati. Voglio testare il livello del dominio indipendentemente dagli altri livelli. Pertanto ho creato un progetto Domain Layer con tre classi, ad es. Person, Order and OrderItem (ipotetico).

Ho usato Inversion of Control (Castle Windosr) quindi ho anche un intero carico di altre classi:

PersonFactory
OrderFactory
OrderItemFactory
IPersonFactory
IOrderFactory
IOrderItemFactory
etc

Il mio progetto Visual Studio sembra "inquinato" con queste classi. Cosa posso fare con queste lezioni? Ho pensato di creare una cartella chiamata: Fabbriche. Cosa fai con queste classi che "inquinano" il progetto?

    
posta w0051977 17.06.2017 - 15:06
fonte

2 risposte

6

IoC è una cosa molto buona. Ma le fabbriche che hanno un rapporto strettamente 1 a 1 con quello che fanno non ti stanno facendo molto bene.

Una fabbrica dovrebbe fare qualcosa per qualcosa. Non dovrebbero essere un'alternativa cerebrale alternativa a un costruttore. Dovrebbero consentire buoni valori predefiniti senza mai forzare nulla a SEMPRE avere quel valore predefinito.

Dovresti mantenere il tuo comportamento separato dalla costruzione. Ciò non significa che devi mantenere tutta la costruzione in un documento xml.

Non tutti i tuoi edifici devono essere comunque nelle fabbriche. I modelli creativi sono disponibili in molti gusti. E a volte è meglio semplicemente creare quello che ti serve in main.

Non lasciare che nessun contenitore IoC ti incolli in un angolo. Se il tuo pensiero è stato: ho bisogno di un oggetto Person quindi ho bisogno di un PersonFactory che stai vivendo in un inferno di tua creazione.

    
risposta data 17.06.2017 - 15:32
fonte
3

Prenderò un tack piuttosto diverso rispetto a CandiedOrange. Prima però, voglio andare oltre alcuni potenziali altri problemi. Non so se alcuni si applicano alla tua situazione, ma voglio coprire tutte le basi.

In primo luogo, non tutto deve essere iniettato. Le cose (concettualmente) senza dipendenze, in particolare oggetti valore e oggetti di trasferimento dati (DTO) non devono essere iniettati proprio come non si userebbe l'iniezione di dipendenza per iniettare un StringFactory . In secondo luogo, non è necessario un factory se il costruttore di una classe non è parametrizzato ad eccezione delle dipendenze. Terzo, potrebbe darsi che troppe cose abbiano dipendenze e dovresti forse ristrutturare il tuo codice. Ad esempio, se i DTO devono assumere dipendenze per salvarsi, è possibile che tale comportamento venga spostato all'esterno del DTO in modo che non richieda alcuna dipendenza. In quarto luogo, come altri hanno menzionato, si può cadere in una trappola in cui si sta tentando di adattare le cose allo stampo del framework DI quando ciò non è né necessario né utile. A volte è semplicemente più semplice avere il codice che hai scritto per gestire parte del processo di risoluzione delle dipendenze nella "radice della composizione" principale.

Tuttavia, anche se nessuna delle situazioni precedenti si applica, puoi facilmente trovarti nella tua situazione. Considera un'analogia che non è un'analogia, ma esattamente ciò che sta sta accadendo. Diciamo che hai la seguente espressione usando le operazioni che sono state aggiunte con LINQ (che ho ottenuto da qui dopo aver cercato su google "esempio di linq", selezionando uno dei link in alto e selezionando a caso gli esempi su questo sito):

customers.SelectMany((cust, custIndex) =>
    orders.Where(o => cust.Field("CustomerID") == o.Field("CustomerID"))
          .Select(o => new { CustomerIndex = custIndex + 1, OrderID = o.Field("OrderID") }));

Ciò che fa non è importante. Ciò che è importante sono le tre funzioni lambda. Immagina, come sarebbe stato il caso in C # 1.0, che dovevi usare il Pattern della strategia e creare una classe per ognuno di quei lambda. Sarebbe osceno, non lo faresti, e nella misura in cui sei stato costretto a farlo, sicuramente "inquinerà" il tuo progetto. Il modello di fabbrica è solo il modello di strategia applicato alla creazione dell'oggetto. Infatti, se pensi, ad esempio, al costruttore Person come Func<Dependencies, Parameters, Person> , un PersonFactory di base è proprio ciò che ottieni dal curriculum, ovvero un Func<Dependencies, Func<Parameters, Person>> . Quello che vuoi veramente in una classe che ha bisogno di creare Person s è la parte Func<Parameters, Person> , e vuoi un'integrazione delle dipendenze per gestire le dipendenze.

Se non si utilizza affatto un framework di dipendenza delle dipendenze e si sono semplicemente cablate manualmente le dipendenze nella root principale / della composizione, si può semplicemente dipendere da Func<Parameters, Person> (o meglio Func<Parameters, IPerson> ) e semplicemente passare un appropriato funzione lambda durante il cablaggio. Tuttavia, molti framework DI rendono questo difficile o impossibile. Il risultato è che, per questo scopo, sei di nuovo nella situazione di C # 1.0. (Questo è uno dei motivi per cui, personalmente, non sono così appassionato di framework DI [da non confondere con DI in sé], specialmente quelli con file di configurazione.)

È possibile eliminare molte delle classi factory usando l'intuizione di cui sopra, ma molto probabilmente questo sarà contorto per adattarsi al framework DI e quindi non ne vale la pena. Non eri chiaro di quale "inquinamento" ti preoccupi veramente: inquinamento delle directory, inquinamento da namespace, inquinamento Intellisense? Per gli ultimi due, il meccanismo di namespace di C # può gestirlo in modo adeguato. Per il primo, una directory è una soluzione ragionevole. Quale approccio ha più senso dipende dalla struttura della directory che stai utilizzando. Ad esempio, se ogni "entità" / "servizio" ha una propria directory, allora non c'è davvero un problema. Se si dispone di una cartella "Entità", quindi di una sottocartella per le interfacce di fabbrica e, forse, alcune o tutte le implementazioni di fabbrica sembrano ragionevoli.

    
risposta data 18.06.2017 - 01:43
fonte

Leggi altre domande sui tag