Frage

Nach Evans und Nilsson Büchern zu lesen Ich bin immer noch nicht sicher, wie Datenzugriff in einer Domäne getrieben Projekt zu verwalten. Sollten die CRUD Methoden Teil der Repositorys sein, das heißt OrderRepository.GetOrdersByCustomer (Kunde) oder sollten sie einen Teil der Einheiten sein: Customer.GetOrders (). Der letztere Ansatz scheint mehr OO, aber es wird für einen einzelnen Entitätstyp von mehreren Objekten Data Access verteilen, das heißt Customer.GetOrders (), Invoice.GetOrders (), ShipmentBatch.GetOrders () usw. Was zum Einfügen und Aktualisieren?

War es hilfreich?

Lösung

CRUD-ish Methoden sollten Teil des Repository ... ish sein. Aber ich denke, Sie sollten sich fragen, warum Sie eine Reihe von CRUD Methoden. Was sie wirklich tun? Was sind sie wirklich für? Wenn Sie tatsächlich die Datenzugriffsmuster rufen Ihre Anwendung finde ich es das Repository macht viel nützlicher und hält Sie davon ab, Schrotflinte Operation zu tun, wenn bestimmte Arten von Änderungen an Ihrer Domain passieren.

CustomerRepo.GetThoseWhoHaventPaidTheirBill()

// or

GetCustomer(new HaventPaidBillSpecification())

// is better than

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

„Speicher“ Typ Methoden auch einen Teil des Repository sein sollten.

Wenn Sie Aggregat Wurzeln haben, das hält man von einer Repository Explosion mit oder Logik ausgebreitet haben aus dem ganzen: Sie haben nicht 4 x Anzahl der Einheiten Datenzugriffsmuster, nur die, die Sie tatsächlich auf den aggregierten Wurzeln verwenden .

Das ist mein $ .02.

Andere Tipps

DDD zieht in der Regel das Repository-Muster über das Active Record Sie mit Customer.Save andeuten.

Ein Nachteil im Active Record-Modell ist, dass es ziemlich viel ein einziges Persistenz-Modell geht davon aus, abgesehen von einigen besonders aufdringlich Code (in den meisten Sprachen).

Die Repository-Schnittstelle ist in der Domänenschicht definiert, aber nicht weiß, ob Ihre Daten in einer Datenbank gespeichert sind oder nicht. Mit dem Repository-Muster, kann ich eine InMemoryRepository erstellen, so dass ich Domain-Logik in Isolation testen kann, und Dependency Injection in der Anwendung verwenden, um die Service-Layer-instanziiert eine SqlRepository zu haben, zum Beispiel.

Für viele Menschen nur ein spezielles Repository mit zum Testen klingt doof, aber wenn Sie das Repository-Modell verwenden, können Sie feststellen, dass Sie wirklich nicht, eine Datenbank für Ihre Anwendung benötigen; manchmal ein einfacher FileRepository den Trick. Hochzeit, um sich auf eine Datenbank, bevor Sie wissen, was Sie brauchen es möglicherweise zu begrenzen. Selbst wenn eine Datenbank notwendig ist, es ist viel schneller Tests gegen einen InMemoryRepository auszuführen.

Wenn Sie in der Art von Domain-Logik nicht viel haben, müssen Sie wahrscheinlich DDD nicht. Active ist durchaus für viele Probleme geeignet, vor allem, wenn Sie meist Daten haben und nur ein wenig der Logik.

Lassen Sie uns wieder für einen zweiten Schritt. Evans empfiehlt, dass die Verwahrungs Rückkehr Aggregat Wurzeln und nicht nur Einheiten. Also vorausgesetzt, dass Ihr Kunde ist ein Aggregat Wurzel, die Aufträge enthält, dann, wenn Sie die Kunden aus seinem Repository geholt, kamen die Aufträge zusammen mit ihm. Sie würden die Befehle zugreifen, indem die Beziehung von Kunden zu Bestellungen navigiert wird.

customer.Orders;

So Ihre Frage zu beantworten, sind CRUD-Operationen, die auf aggregierten root-Repositories.

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

Ich habe es in beiden Richtungen getan Sie sprechen, ist mein bevorzugter Ansatz jetzt der persistent unwissend (oder PONO - Plain Ole‘Net Object) -Methode, wo Ihre Domain Klassen über Klassen sein Domain nur besorgt sind. Sie wissen nichts darüber, wie sie beibehalten werden oder auch wenn sie beibehalten werden. Natürlich müssen Sie dies manchmal pragmatisch sein und für Dinge wie eine Id lassen (aber auch dann Super Typ benutze ich nur eine Schicht, die die Id hat, so kann ich einen Punkt haben, wo Dinge wie Standardwert leben)

Der Hauptgrund dafür ist, dass ich danach streben, das Prinzip der einzigen Verantwortung zu folgen. Folgt man diesem Prinzip habe ich meinen Code viel mehr prüfbar und wartbar gefunden. Es ist auch viel einfacher, Änderungen vorzunehmen, wenn sie gebraucht werden, da ich nur eine Sache hat, um darüber nachzudenken.

Eine Sache von wachsam zu sein ist die Methode aufblasen, die Repositories leiden können. GetOrderbyCustomer .. GetAllOrders .. GetOrders30DaysOld .. etc etc. Eine gute Lösung für dieses Problem bei dem Abfrage-Objekt-Muster zu suchen. Und dann können Sie Ihre Repositories nehmen Sie nur in einem Query-Objekt auszuführen.

Ich würde auch empfehlen dringend etwas wie NHibernate Blick in. Es enthält viele der Konzepte, die Repositorys so nützlich machen (Identity Map, Cache, Query-Objekte ..)

Auch in einem DDD, ich würde Data Access Klassen hält und Routinen getrennt von Entities.

Die Gründe dafür sind,

  1. Testbarkeit verbessert
  2. Die Trennung von Bedenken und Modularer Aufbau
  3. Mehr wartbar auf lange Sicht, wie Sie hinzufügen Entitäten, Routinen

Ich bin kein Experte, nur meine Meinung.

Die ärgerliche Sache mit Nilssons Anwendung DDD & P ist, dass er immer mit beginnt: „Ich würde das nicht in einer realen Welt-Anwendung, aber ...“ und dann seinem Beispiel folgt. Zurück zum Thema: Ich denke, OrderRepository.GetOrdersByCustomer (Kunde) ist der Weg zu gehen, aber es gibt auch eine Diskussion über die ALT.Net Mailing-Liste ( http://tech.groups.yahoo.com/group/altdotnet/ ) über DDD.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top