2009-09-26 7 views
11

Ho esaminato le applicazioni più semplici come Nerddinner e ContactManager e anche quelle più complicate come Kigg. Capisco quelli più semplici e ora vorrei capire quelli più complessi.Portare il mio MVC al livello successivo: DI e Unità di lavoro

In genere le applicazioni più semplici dispongono di classi di repository e interfacce (il più vagamente accoppiabili che possono ottenere) su LINQtoSQL o Entity Framework. I repository vengono chiamati dai controller per eseguire le operazioni necessarie sui dati.

Un modello comune che vedo quando esamino le applicazioni più complesse come Kigg o Oxite è l'introduzione di (io sono solo di graffiare la superficie qui ma devo iniziare da qualche parte):

  • CIO DI (in Kigg di caso l'Unità)
  • manager Web richiesta durata
  • unità di lavoro

Ecco le mie domande:

0.123.

Capisco che per avere un'applicazione accoppiata liberamente devi usare qualcosa come Unity. Ma sembra anche che nel momento in cui presenti Unity al mix, devi anche presentare un Web Lifetime Manager. Perché? Perché le applicazioni di esempio come Nerddinner non hanno un Web Lifetime Manager Richiesta? Cosa fa esattamente? È una cosa specifica di Unity?

Un secondo schema che noto è l'introduzione dell'Unità di lavoro. Ancora una volta, la stessa domanda: perché Nerddinner o ContactManager non usano l'Unità di lavoro? Invece queste applicazioni utilizzano le classi di repository su Linq2Sql o Entity Framework per eseguire la manipolazione dei dati. Nessun segno di alcuna unità di lavoro. Che cosa è esattamente e perché dovrebbe essere usato?

Grazie

seguito è riportato un esempio di DI in Nerddiner a livello DinnersController:

public DinnersController() 
     : this(new DinnerRepository()) { 
    } 

    public DinnersController(IDinnerRepository repository) { 
     dinnerRepository = repository; 
    } 

Così ho ragione di ritenere che a causa del primo costruttore del controllore "possiede" il DinnerRepository e dipenderà quindi dalla durata del controller in quanto viene dichiarato lì?

risposta

3

Con Linq-to-SQL viene utilizzato direttamente, il controllore possiede il riferimento al contesto dati . Di solito è un riferimento privato all'interno del controller e quindi viene creato come parte della sua costruzione. Non c'è bisogno di una gestione a vita, poiché è in un posto.

Tuttavia, quando si utilizza il contenitore IoC, i repository di dati vengono creati all'esterno del controller. Poiché il contenitore IoC che lo crea per te non sa come e per quanto tempo utilizzerai l'oggetto creato, viene introdotta una strategia a vita.

Ad esempio, contesto dati (repository) viene in genere creato all'inizio della richiesta Web e distrutto alla fine. Tuttavia, per i componenti che funzionano con il servizio Web esterno o con un programma di mappatura statico (ad es. Logger) non è necessario crearli ogni volta. Quindi potresti voler dire di crearli una volta (cioè lo stile di vita di singletone).

Tutto ciò accade perché i contenitori IoC (come Unity) sono progettati per gestire molte situazioni e non conoscono le vostre esigenze specifiche. Ad esempio, alcune applicazioni utilizzano transazioni di "conversazione" in cui NHibernate (o Entity Framework) può durare durante diverse pagine/richieste web. I contenitori IoC ti consentono di modificare gli oggetti in base alle tue esigenze. Ma come detto questo ha un prezzo - dal momento che non esiste un'unica strategia predefinita, è necessario selezionarne una da soli.

Perché NerdDinner e altre applicazioni non utilizzano tecniche più avanzate è semplicemente perché hanno lo scopo di dimostrare funzionalità MVC, non utilizzi avanzati di alcune altre librerie. Ricordo un articolo scritto per dimostrare una funzionalità avanzata del contenitore IoC - questo articolo ha rotto alcuni schemi di progettazione approvati come la separazione delle preoccupazioni - ma questo non era così importante perché i modelli di design non erano l'obiettivo dell'articolo. Lo stesso vale per le semplici applicazioni dimostrative MVC: non vogliono che tu, il nuovo arrivato MVC, si perda nei labirinti IoC.

E io non consiglierei di guardare Oxite come un esempio di riferimento disegno: http://codebetter.com/blogs/karlseguin/archive/2008/12/15/oxite-oh-dear-lord-why.aspx http://ayende.com/Blog/archive/2008/12/19/oxite-open-exchangable-informative-troubled-engine.aspx

+0

Grazie! Questo ha aiutato. Ho modificato la mia domanda in fondo. È questo che intendi quando dici che il controller possiede il riferimento al contesto repository/dati? – Thomas

+0

Non esattamente. In NerdDinner usano un costruttore aggiuntivo che accetta IDinnerRepository per rendere più semplici i test unitari. Ma sì, è ancora o controller (costruttore senza parametri) o test che creano e possiedono l'oggetto repository. Entrambi muoiono e non ci sono altri utenti del repository; quindi la vita è semplice. Tra l'altro tale tecnica è cattiva; puoi leggere di più a riguardo qui: http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/07/03/how-not-to-do-dependency-injection-in-nerddinner.aspx (pure come google per "IoC dei poveri"). – queen3

+0

L'argomentazione di Jimmy Bogard su questo esemplare esempio di "IoC del povero uomo" è estremamente buona qui. Anche i commenti sono buoni. Sicuramente vale la pena leggere. –

0

La maggior parte se non tutti i contenitori DI toccano il concetto dei tempi di vita, credo. A seconda dello scenario in questione, è possibile che il contenitore restituisca sempre la stessa istanza di un componente registrato, mentre per un altro componente, si consiglia di restituire sempre una nuova istanza. La maggior parte dei contenitori ti permette anche di specificare che all'interno di un contesto particolare, vuoi che restituisca la stessa istanza, ecc.

Non conosco molto bene l'unità (finora ho usato Windsor e Autofac), ma io sospetto che il gestore della durata della richiesta Web sia un'implementazione delle strategie a vita in cui la stessa istanza viene fornita dal contenitore durante la vita di una singola richiesta web. Troverete strategie simili in contenitori come Windsor.

Infine, suppongo che tu ti stia riferendo all'Unità di lavoro. Un'Unità di lavoro è in sostanza un gruppo di azioni che si desidera avere successo o fallire come una transazione aziendale atomica. Per una descrizione più formale, guarda a Martin Fowler's definition. È un concetto che ha guadagnato più popolarità nel contesto del Domain Driven Design. Un'unità di lavoro tiene traccia delle modifiche applicate in tale transazione e, quando è il momento giusto, impegna queste modifiche in una transazione ACID. In NHibernate, ad es., la sessione supporta la nozione di unità di lavoro e in particolare il rilevamento delle modifiche, mentre in Linq2SQL è il contesto ...

Problemi correlati