2009-12-29 25 views
12

Pro:Pro e contro di DDD Repository

  • Repositories nascondere query complesse.
  • I metodi di deposito possono essere utilizzati come limiti di transazione.
  • ORM può essere facilmente deriso

Contro:

  • framework ORM offrono già una collezione come l'interfaccia per gli oggetti persistenti, qual è l'intenzione di repository. Quindi gli archivi aggiungono complessità extra al sistema.
  • esplosione combinatoria quando si utilizzano i metodi findBy. Questi metodi possono essere evitati con oggetti Criteria, query o oggetti di esempio. Ma per farlo non è necessario alcun repository perché un ORM già supporta questi modi per trovare oggetti.
  • Poiché i repository sono una raccolta di radici aggregate (nel senso di DDD), è necessario creare e passare le radici aggregate anche se viene modificato solo un oggetto figlio.

Domande:

  • Quali pro e contro lo sai?
  • Consiglieresti di utilizzare i repository? (Perché o perché no?)
+2

Gli ORM a contrasto con repository non hanno senso - si utilizzano gli ORM per implementare i repository, no? –

+1

Nessuna risposta definitiva. Wiki della comunità? –

+1

Il tuo terzo cono non ha senso. Se hai bisogno di manipolare un "oggetto figlio" da solo, dovrebbe essere una radice aggregata. –

risposta

8

Il punto principale di un repository (come nel Principio di Responsabilità Unica) è di astrarre il concetto di ottenere oggetti che hanno identità. Dato che mi sento più a mio agio con DDD, non ho trovato utile pensare agli archivi come focalizzati principalmente sulla persistenza dei dati, ma piuttosto come fabbriche che istanziano gli oggetti e mantengono la loro identità.

Quando si utilizza un ORM si dovrebbe usare la propria API nel modo più limitato possibile, offrendo una facciata forse specifica per il dominio. Quindi, indipendentemente dal tuo dominio, vedresti comunque un repository. Il fatto che abbia un ORM dall'altra parte è un "dettaglio di implementazione".

7

Un repository è in realtà solo uno strato di astrazione, come un'interfaccia. Lo si utilizza quando si desidera disaccoppiare l'implementazione della persistenza dei dati (ad es. Il proprio database).

Suppongo che se non si desidera disaccoppiare il DAL, non è necessario un repository. Ma ci sono molti vantaggi nel farlo, come la testabilità.

Riguardo all'esplosione combinatoria dei metodi "Trova": in .NET è possibile restituire un IQueryable anziché un IEnumerable e consentire al client chiamante di eseguire una query Linq su di esso, anziché utilizzare un metodo Find. Ciò fornisce flessibilità per il cliente, ma sacrifica la capacità di fornire un'interfaccia testabile ben definita. In sostanza, si scambia una serie di vantaggi per un altro.

+1

+1 alla restituzione di un IQueryable dall'IRepository. Ciò consente di scrivere la logica di "trova" nel livello di servizio/root e di testare tale logica simulando un IRepository. Per quanto riguarda i test, il livello "Repository" è il punto in cui tracciare la linea tra Test unitario e Test di integrazione - Scrivo test di integrazione per i miei Repos e restituiscono i record FetchAll() appropriati per un IQueryable, e Unit test per altri che ha una vera e propria logica di business. – eduncan911

+0

Almeno con NHibernate devi essere consapevole del fatto che ci sono grandi differenze (caching, modo interrogativo è eseguito) tra chiamare linq. Dove (a => a.id == id) e chiamare ISession.Load (id). Può essere utile avere un modo IQueryable per accedere ai dati, ma non provare a fare tutto con esso, tenere presente che gli ORM di solito offrono alcuni modi per eseguire query e operazioni avanzate. –

8

Il repository mette a fuoco il modello di dominio nascondendo i dettagli di accesso ai dati dietro un'interfaccia basata su un linguaggio ubiquo. Quando si progetta il repository, ci si concentra sui concetti di dominio, non sull'accesso ai dati. Dal punto di vista DDD, l'utilizzo dell'API ORM direttamente equivale all'utilizzo diretto di SQL.

Questo è il modo in repository può apparire come l'applicazione di elaborazione degli ordini:

List<Order> myOrders = Orders.FindPending() 

Nota che non ci sono termini di accesso ai dati come 'Criteri' o 'Query'. Il metodo 'FindPending' internamente può essere implementato usando i criteri Hibernate o HQL ma questo non ha nulla a che fare con DDD.

L'esplosione del metodo è una preoccupazione valida. Ad esempio potresti finire con più metodi come:

Orders.FindPending() 
    Orders.FindPendingByDate(DateTime from, DateTime to) 
    Orders.FindPendingByAmount(Money amount) 
    Orders.FindShipped() 
    Orders.FindShippedOn(DateTime shippedDate) 
    etc 

Questo può essere migliorato utilizzando il modello di specifica. Ad esempio si può avere una classe

class PendingOrderSpecification{ 
    PendingOrderSpecification WithAmount(Money amount); 
    PendingOrderSpecification WithDate(DateTime from, DateTime to) 
    ... 
} 

Così quel repository sarà simile a questa:

Orders.FindSatisfying(PendingOrderSpecification pendingSpec) 
Orders.FindSatisfying(ShippedOrderSpecification shippedSpec) 

Un'altra opzione è quella di avere repository separato per attesa e gli ordini spediti.