DDD Entitätsvalidierung

8

Ich habe eine Frage bezüglich der Validierung von Entitäten. Als Beispiel gibt es eine User , die in einem System mit email und password registriert werden kann. Die Geschäftsregel besagt Folgendes:

  1. email muss gültig sein (muss dem E-Mail-Format entsprechen) und einmalig;
  2. password sollte zwischen 6 und 20 Zeichen lang sein.

Mein erster Gedanke ist, die Validierung in User.Register(email, password) zu platzieren. Der Hauptvorteil dieses Ansatzes ist, dass User steuert, wie es registriert wird, indem es sich selbst die Korrektheit der Registrierungsdaten überprüft. Der Nachteil besteht darin, dass die Überprüfung der E-Mail-Eindeutigkeit Aufrufe von UserRepository erfordert, sodass die User möglicherweise von ihrer Repository abhängig ist. Um dieses Problem zu lösen, könnte die E-Mail- und Passwort-Validierung für irgendeine Art von BusinessRule -Objekten ausgeschlossen werden. So könnte die Validierung in User.Register() -Methode wie folgt aussehen:

%Vor%

Dabei könnten _emailRule und _passwordRule als Konstruktorargumente übergeben werden: User(EmailRule emailRule, PasswordRule passwordRule).

In diesem Fall ist User nicht direkt an UserRepository gekoppelt. Auf diese Weise werden die Regeln explizit in der Domäne angezeigt, wodurch sie expressiver werden.

Die Frage ist also: Was denken Sie über diesen Ansatz? Gibt es andere Lösungen?

    
Markus 10.03.2012, 12:37
quelle

4 Antworten

4

Sie könnten einen Domain Service implementieren, der dies kapselt. In DDD würden Sie normalerweise einen Domänen-Service verwenden, wenn die Geschäftslogik außerhalb des Bereichs eines einzelnen Aggregats liegt. In diesem Fall ist es die Eindeutigkeitsprüfung. Also, was ich tun würde ist:

%Vor%

Wenn Sie sich Sorgen darüber machen, dass User.Create außerhalb des Registrierungsdienstes aufgerufen wird und Sie daher die Eindeutigkeitsprüfung umgehen, können Sie möglicherweise die User.Create-Methode auf intern setzen, was bedeutet, dass die einzige Möglichkeit zum Erstellen eines Benutzers über die Registrierungsdienst.

    
David Masters 12.03.2012 10:20
quelle
3

Es gibt drei Validierungen, die Sie in diesem Beispiel versuchen möchten:

  1. Die E-Mail-Adresse muss ein gültiges Format sein;
  2. Die E-Mail-Adresse muss eindeutig sein (d. h. es existiert kein Benutzer mit dieser E-Mail-Adresse);
  3. Das Passwort muss bestimmten Längenbeschränkungen entsprechen.

1 und 3 oben sind einfache Validierungen, die deklarativ für die Entitätseigenschaften durchgeführt werden können (unter Verwendung von benutzerdefinierten Attributen und einer geeigneten Validierungsbibliothek in .NET zum Beispiel).

2 oben ist das knifflige Bit, und hier besteht meines Erachtens die innere Abhängigkeit vom User Repository.

Die Frage ist: "Ist die Verantwortung, die Erstellung eines User mit der gleichen E-Mail-Adresse zu verhindern wie ein vorhandenes User , mit der User Entität zu verhindern?". Ich glaube, die Antwort auf diese Frage lautet "Nein" ... es fühlt sich an, als ob diese Verantwortung bei einem Dienst oder einer Organisation auf höherer Ebene liegen sollte, für die es selbstverständlich ist, Kenntnis über die Gesamtheit der Benutzer zu haben.

Also, meine Meinung ist:

  1. Platzieren Sie die Validierungen, die mit dem Benutzer verknüpft sind, in der Entität User (starke Kohäsion);
  2. Platzieren Sie die Eindeutigkeitsbeschränkung in einem DDD-Dienst, der speziell für die Pflege der Invarianten der Gruppe von Benutzern verantwortlich ist. Dazu wird die Eindeutigkeitsprüfung und die Persistenz der neuen% co_de umschlossen % in einer Transaktion.
Eric Smith 11.12.2012 07:00
quelle
2

Sie können denken, dass es zwei Arten der Validierung gibt: Validierung des internen Zustands und Kontextvalidierung. Sie können innerhalb dieser Entität eine interne Validierung durchführen und anschließend mithilfe eines Services eine Kontextvalidierung durchführen.

    
driushkin 10.03.2012 14:30
quelle
1

Markus,

Sein Ansatz war nicht schlecht, aber ich mache es einfach anders.

Meiner Meinung nach respektieren Sie die OCP, indem Sie Validierungsregeln aus der Entität herausnehmen, was mit Bedacht entschieden wurde. Mit diesen Validierungsregeln im Klassenkonstruktor suggerieren Sie, dass die Regeln unveränderlich sind, oder?

Ich würde das nicht tun, sondern einfach ein Methoden-Dyad erstellen, das die Regeln als Konstruktor setzt. Für mich war nicht klar, was passieren würde, wenn die Validierungsregeln verletzt würden. Ich mag es, Ausnahmen auf die Benutzeroberfläche zu werfen, die als allgegenwärtige Warnungen behandelt.

Eine andere Sache, die mir nicht klar war, ist das Ereignis, das diese Validierung auslöst. wäre es, wenn die Entität Benutzer dem Repository hinzugefügt wurde oder eine Methode der Entität, die dies tun würde? Ich nehme die zweite Option, die die Methode isValidAuthentication () aufruft, die diese Ausnahmen auslöst.

Was die Abhängigkeit der Entität vom Repository betrifft, wage ich zu sagen, dass das falsch ist. Sie könnten sogar die Entität von ihm abhängig machen, weil das Repository eine Sammlung von Objekten ist, was ist daran falsch? An dieser Stelle scheint jedoch klar zu sein, dass Validierung ein Service ist. Wenn wir also diese Validierungen in einen Service legen, würde diese Kopplung entfallen und das OCP erneut anwenden. Stimmen Sie zu?

Eine große Umarmung und Erfolg!

    
lcardosobr 10.03.2012 13:34
quelle