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:
email
muss gültig sein (muss dem E-Mail-Format entsprechen) und einmalig; 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:
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?
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.
Es gibt drei Validierungen, die Sie in diesem Beispiel versuchen möchten:
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:
User
(starke Kohäsion); 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.
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!
Tags und Links validation domain-driven-design