10 Stimmen

Datenzugriff in DDD?

Nach der Lektüre von Evans und Nilssons Büchern bin ich mir immer noch nicht sicher, wie der Datenzugriff in einem domänengesteuerten Projekt zu handhaben ist. Sollten die CRUD-Methoden Teil der Repositories sein, d.h. OrderRepository.GetOrdersByCustomer(customer) oder sollten sie Teil der Entitäten sein: Customer.GetOrders(). Der letztere Ansatz scheint OO-freundlicher zu sein, aber er verteilt den Datenzugriff für einen einzigen Entitätstyp auf mehrere Objekte, d. h. Customer.GetOrders(), Invoice.GetOrders(), ShipmentBatch.GetOrders() usw. Was ist mit Einfügen und Aktualisieren?

15voto

Chris Bilson Punkte 1844

CRUD-ähnliche Methoden sollten Teil des Repositorys sein...ish. Aber ich denke, Sie sollten sich fragen, warum Sie eine Reihe von CRUD-Methoden haben. Was tun sie realmente tun? Was sind sie realmente für? Wenn Sie die Datenzugriffsmuster, die Ihre Anwendung verwendet, tatsächlich nennen, wird das Repository meiner Meinung nach sehr viel nützlicher, und Sie müssen nicht mit der Schrotflinte operieren, wenn bestimmte Arten von Änderungen an Ihrer Domäne vorgenommen werden.

CustomerRepo.GetThoseWhoHaventPaidTheirBill()

// or

GetCustomer(new HaventPaidBillSpecification())

// is better than

foreach (var customer in GetCustomer()) {
    /* logic leaking all over the floor */
}

Methoden vom Typ "Speichern" sollten ebenfalls Teil des Repositorys sein.

Wenn Sie Aggregatwurzeln haben, verhindert dies eine Explosion des Repositorys oder die Ausbreitung der Logik über die gesamte Fläche: Sie haben nicht 4 x # von Entitäten Datenzugriffsmuster, nur die, die Sie tatsächlich auf die aggregierten Wurzeln verwenden.

Das sind meine $.02.

5voto

JasonTrue Punkte 18756

DDD bevorzugt in der Regel das Repository-Muster gegenüber dem aktiven Datensatzmuster, das Sie mit Customer.Save andeuten.

Ein Nachteil des Active-Record-Modells besteht darin, dass es so gut wie ein einziges Persistenzmodell voraussetzt, es sei denn, es handelt sich um besonders aufdringlichen Code (in den meisten Sprachen).

Die Repository-Schnittstelle wird in der Domänenschicht definiert, weiß aber nicht, ob Ihre Daten in einer Datenbank gespeichert sind oder nicht. Mit dem Repository-Muster kann ich ein InMemoryRepository erstellen, so dass ich die Domänenlogik isoliert testen kann, und in der Anwendung mit Hilfe von Dependency Injection beispielsweise ein SqlRepository von der Dienstschicht instanziieren lassen.

Ein spezielles Repository nur zum Testen zu haben, klingt für viele Leute albern, aber wenn Sie das Repository-Modell verwenden, werden Sie vielleicht feststellen, dass Sie für Ihre spezielle Anwendung nicht wirklich eine Datenbank brauchen; manchmal reicht ein einfaches FileRepository aus. Sich mit einer Datenbank zu verheiraten, bevor man weiß, dass man sie braucht, ist potentiell einschränkend. Selbst wenn eine Datenbank notwendig ist, ist es viel schneller, Tests gegen ein InMemoryRepository laufen zu lassen.

Wenn Sie nicht viel an Domänenlogik haben, brauchen Sie wahrscheinlich kein DDD. ActiveRecord ist für viele Probleme sehr gut geeignet, vor allem, wenn Sie hauptsächlich Daten und nur ein wenig Logik haben.

4voto

Stefan Moser Punkte 6323

Treten wir für einen Moment zurück. Evans empfiehlt, dass Repositories aggregierte Wurzeln zurückgeben und nicht nur Entitäten. Nehmen wir also an, dass Ihr Kunde eine aggregierte Wurzel ist, die Aufträge enthält, dann wurden beim Abrufen des Kunden aus dem Repository auch die Aufträge mitgenommen. Sie würden auf die Bestellungen zugreifen, indem Sie durch die Beziehung von Customer zu Orders navigieren.

customer.Orders;

Um Ihre Frage zu beantworten: CRUD-Operationen sind in aggregierten Root-Repositories vorhanden.

CustomerRepository.Add(customer);
CustomerRepository.Get(customerID);
CustomerRepository.Save(customer);
CustomerRepository.Delete(customer);

3voto

Shane Courtrille Punkte 13622

Ich habe es getan, beide Möglichkeiten, die Sie sprechen, meine bevorzugte Ansatz ist jetzt die persistente unwissend (oder PONO - Plain Ole' .Net Object) Methode, wo Ihre Domain-Klassen sind nur besorgt über die Domain-Klassen zu sein. Sie wissen nichts darüber, wie sie persistent sind oder ob sie überhaupt persistent sind. Natürlich muss man dabei manchmal pragmatisch sein und Dinge wie eine Id berücksichtigen (aber selbst dann verwende ich nur einen Layer-Supertyp, der die Id hat, damit ich einen einzigen Punkt habe, an dem Dinge wie Standardwerte leben).

Der Hauptgrund dafür ist, dass ich mich bemühe, dem Prinzip der Einzelverantwortung zu folgen. Durch die Befolgung dieses Prinzips habe ich festgestellt, dass mein Code viel besser testbar und wartbar ist. Es ist auch viel einfacher, Änderungen vorzunehmen, wenn sie notwendig sind, da ich nur an eine Sache denken muss.

Eine Sache, auf die man aufpassen sollte, ist die Aufblähung der Methoden, unter der Repositories leiden können. GetOrderbyCustomer.. GetAllOrders.. GetOrders30DaysOld.. usw. usw. Eine gute Lösung für dieses Problem ist die Verwendung des Query Object Patterns. Und dann können Ihre Repositories einfach ein Query-Objekt zur Ausführung annehmen.

Ich würde auch dringend empfehlen, sich mit etwas wie NHibernate zu beschäftigen. Es enthält viele der Konzepte, die Repositories so nützlich machen (Identity Map, Cache, Query-Objekte )

0 Stimmen

Ich dachte, dass in den Business-Klassen, injizieren Sie nicht das Repository, so dass die Domain-Klassen dones't care, wenn die Daten persist oder nicht, nur die Business-Logik zu tun ist. Aber wo ist dann der Code, der die Daten aus der Datenbank abruft und sie speichert? In einem Dienst der Geschäftslogik oder in einem Dienst in der Anwendungsschicht?

2voto

Vin Punkte 6035

Selbst in einer DDD würde ich Datenzugriffsklassen und -routinen von Entitäten getrennt halten.

Die Gründe dafür sind,

  1. Testbarkeit verbessert
  2. Trennung der Bereiche und modularer Aufbau
  3. Langfristig besser wartbar, da Sie Entitäten und Routinen hinzufügen

Ich bin kein Experte, nur meine Meinung.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X