2013-06-04 7 views
5

Wir versuchen, Domain-Driven Design in unserem Projekt zum ersten Mal zu übernehmen. Das Problem, das ich habe, ist mit Verbindungen zwischen Entitäten. Wie machst du das richtig?Der richtige Weg, um Assoziationen in DDD zu implementieren?

Say, ich habe die Entitäten und Contract, eine einfache Eins-zu-viele-Assoziation. Wie modelliere ich es?

Option 1: Aggregat.

Problem: Das Problem hier ist, dass, wenn ich es richtig verstehe, alle Entitäten in einem Aggregat geladen werden müssen, wenn ein Aggregatobjekt erstellt wird. Ich kann keine Lazy-Loads laden, wenn sie benötigt werden, weil es ein Repository von einer Entity referenzieren müsste, was offensichtlich schlecht ist. Es wäre jedoch ein großes Leistungsproblem, alle Verträge eines Mitarbeiters aus der Datenbank zu holen.

Option 2: Holen eines Vertrag des Mitarbeiters durch einen Repository (z.B. ContractRepository.GetContractsForEmployee()) und das Hinzufügen von EmployeeId Eigenschaft Contract Klasse.

Problem: es macht schwer, irgendeine Geschäftslogik in Einheiten zu setzen. Ich hätte gerne eine Methode, sagen wir Employee.Dismiss(), aber es müsste auch den Vertrag des Mitarbeiters aktualisieren. Dies bedeutet, dass ich diese Logik in einen Dienst stellen müsste. Das Problem ist, ich kann nicht viel Logik denken, die nur auf einem Employee arbeitet, und so würde das Modell etwas anämisch werden, mit den meisten Logik innerhalb der Dienste.

Wie gehen Sie mit diesen Problemen in DDD um?

+1

Sobald Sie "eine einfache Eins-zu-viele-Verknüpfung" denken, tun Sie nicht DDD, Sie tun Datenbank-Schema-Design. Die Assoziationen zwischen Entitäten sollten Verhalten sein. Ein Mitarbeiter kann sich nicht selbst entlassen, er muss entlassen werden (von einer anderen Stelle, die dazu befugt ist). Option 2 ist die richtige. Sie müssen nicht viel Verhalten für eine Entität entwickeln. Wenn ein Domänenobjekt im realen Geschäft sehr einfach ist, modelliere es so. Es ist wichtig, wie die Domäne das Konzept (die Semantik) definiert und nicht wie viele Methoden das Objekt hat. – MikeSW

+0

MikeSW ist richtig. Ein sehr wichtiger Aspekt von DDD ist Ubiquitous Language. Die Art und Weise, wie Sie über die Domain sprechen, MUSS die Art und Weise sein, wie der Domänenexperte über die Domain spricht, andernfalls wird der Code umständlich und unintuitiv. Es klingt trivial, aber wenn du das richtig machst, beginnen Entitäten, Verhalten vorzuschlagen. z.B. Employee.Resign(); Vertrag.Klicken(); – Asher

Antwort

2

Das ist nur meine Meinung ... ohne Ihre Domain zu kennen.

Zunächst ist here eine gute Ressource zu lesen (Teil über Aggregates und Roots).

In DDD Terminologie Employee und Contract sind beide Einheiten (weil sie beide haben eine Identität).

„Aggregates zieht eine Grenze um eine oder mehr Entitäten und auch:. jedes Aggregat hat eine Wurzel Entity, welches das einzige Mitglied des Aggregats ist, dass jedes Objekt außerhalb des Aggregats erlaubt einen Verweis auf halten."

Die Frage ist: do Employee und Contract Form ein Aggregat, mit Employee die Root-Entität ist offensichtlich nicht, weil andere Domäne Entitäten auch einen Verweis auf ein contract haben könnten, und die Verdingungs ids sind global eindeutig, nicht wahr? . nur innerhalb eines Customer

also unter Berücksichtigung dieser Regeln, Employee und Contract sind beide Aggregat Wurzeln

Dann:. „nur Aggregat Wurzeln kann direkt mit Abfragen erhalten werden; so bedeutet dies, dass wir ein Repository pro Aggregat Wurzel haben sollten.“

So in diesem Fall haben wir ein EmployeeRepository und ein ContractRepository.

all dies in Berücksichtigung, würde ich nicht eine Beziehung zwischen hinzufügen Mitarbeiter und Verträge in der Domain-Modell, aber behandeln sie separat.Nach allem, wenn Sie eine Employee benötigen, müssen Sie nicht unbedingt seine contracts auch, sie sind beide verschiedene Aspekte.

Option 2 ist, was ich wählen würde: Verwenden Sie die ContractRepository, um die Verträge zu erhalten, die Sie interessieren. Und bei Bedarf Sie co Fügen Sie einen Domain-Service hinzu, der für die Aggregation von Mitarbeitern und Verträgen zuständig ist, falls erforderlich.

Wenn Sie auch eine Company Entität definieren, kann die Kündigung eines Mitarbeiters die Aufgabe dieser Entität sein.

0

Sie müssen Ihre wahren Invarianten finden.

Hier könnten Sie eine Invariante wie: Sie können eine Employee nicht entlassen, die bereits entlassen wurde.

Wenn dies die einzige echte Invariante ist, dann könnten Sie eine Employee aggregieren, die nur die IDs der zugehörigen Verträge hätte.

Contract wäre ein weiteres Aggregat (falls erforderlich).

Wenn die Methode ablehnt() erfolgreich ist, können Sie die erforderlichen Verträge laden und die erforderlichen Änderungen vornehmen.

1

Wir sind vor kurzem auch in den DDD-Ansatz gekommen. Wenn ich es täte, würde ich die folgenden (Attribute werden der Kürze halber vereinfacht):

public class Employee() { 

    String name; 
    Set<ContractNumber> contracts; 

    public void addContract(ContractNumber contractNumber) { 
     this.contracts.add(contractNumber); 
    } 

} 

public class Contract() { 
    ContractNumber contractNumber; 
    Date effectiveDate; 
} 

public class ContractNumber() { 
    String contractNumber; 
} 

ContractNumber ist ein Wertobjekt, das auf von innen Mitarbeiter bezeichnet wird. In diesem Beispiel befindet sich Employee in einem BoundedContext, der sich mit Mitarbeitern und ihren jeweiligen Verträgen befasst. Es kann andere Darstellungen von Employee in anderen begrenzten Kontexten geben.

Wie in anderen Antworten besprochen, wird es Repositories für Mitarbeiter und Vertrag geben.

Verwandte Themen