Ich lerne derzeit DDD und habe einige Fragen zum Verwalten von Repositorys mit DDD.
Eigentlich habe ich zwei Möglichkeiten getroffen:
Erster
Die erste Möglichkeit zum Verwalten von Diensten, die ich gelesen habe, besteht darin, einem Anwendungsdienst ein Repository und ein Domänenmodell hinzuzufügen.
Auf diese Weise rufen wir in einer der Anwendungsdienstmethoden eine Domänendienstmethode (Überprüfung von Geschäftsregeln) auf. Wenn die Bedingung gut ist, wird das Repository mit einer speziellen Methode aufgerufen, um die Entität aus der Datenbank zu erhalten / abzurufen.
Ein einfacher Weg, dies zu tun, könnte sein:
class ApplicationService{
constructor(domainService, repository){
this.domainService = domainService
this.repository = repository
}
postAction(data){
if(this.domainService.validateRules(data)){
this.repository.persist(new Entity(data.name, data.surname))
}
// ...
}
}
Der zweite
Die zweite Möglichkeit besteht darin, das Repository stattdessen in den domainService einzuschleusen und das Repository nur über den domainService zu verwenden:
class ApplicationService{
constructor(domainService){
this.domainService = domainService
}
postAction(data){
if(this.domainService.persist(data)){
console.log('all is good')
}
// ...
}
}
class DomainService{
constructor(repository){
this.repository = repository
}
persist(data){
if(this.validateRules(data)){
this.repository.save(new Entity(data.name))
}
}
validateRules(data){
// returns a rule matching
}
}
Von nun an kann ich nicht mehr unterscheiden, welches das beste ist (wenn es eines am besten gibt) oder was beide in ihrem Kontext implizieren.
Können Sie mir ein Beispiel geben, wo eines besser sein könnte als das andere und warum?
quelle
Antworten:
Die kurze Antwort lautet: Sie können Repositorys von einem Anwendungsdienst oder einem Domänendienst verwenden. Es ist jedoch wichtig zu überlegen, warum und wie Sie dies tun.
Zweck eines Domain Service
Domänendienste sollten Domänenkonzepte / -logik kapseln - als solche die Domänendienstmethode:
gehört nicht zu einem Domänendienst, da er
persist
nicht Teil der allgegenwärtigen Sprache ist und die Funktionsweise der Persistenz nicht Teil der Geschäftslogik der Domäne ist.Im Allgemeinen sind Domänendienste nützlich, wenn Sie über Geschäftsregeln / -logiken verfügen, die eine Koordinierung oder die Arbeit mit mehr als einem Aggregat erfordern. Wenn die Logik nur ein Aggregat umfasst, sollte sie sich in einer Methode für die Entitäten dieses Aggregats befinden.
Repositorys in Application Services
In diesem Sinne bevorzuge ich in Ihrem Beispiel Ihre erste Option - aber auch da gibt es Raum für Verbesserungen, da Ihr Domain - Service Rohdaten von der API akzeptiert - warum sollte der Domain - Service über die Struktur von Bescheid wissen
data
? Darüber hinaus scheinen die Daten nur auf ein einzelnes Aggregat bezogen zu sein, sodass die Verwendung eines Domänendienstes dafür nur einen begrenzten Wert bietet. Im Allgemeinen würde ich die Validierung im Entitätskonstruktor ablegen. z.Bund eine Ausnahme auslösen, wenn es ungültig ist. Abhängig von Ihrem Anwendungsframework kann es einfach sein, einen konsistenten Mechanismus zum Abfangen der Ausnahme und zum Zuordnen zu der entsprechenden Antwort für den API-Typ zu haben - z. B. für eine REST-API einen 400-Statuscode zurückgeben.
Repositorys in Domänendiensten
Ungeachtet des oben Gesagten ist es manchmal nützlich, ein Repository in einen Domänendienst einzuschleusen und diesen zu verwenden, aber nur, wenn Ihre Repositorys so implementiert sind, dass sie nur Aggregatwurzeln akzeptieren und zurückgeben, und wenn Sie Logik abstrahieren, die mehrere Aggregate umfasst. z.B
Die Implementierung des Domänendienstes würde folgendermaßen aussehen:
Fazit
Der Schlüssel hierbei ist, dass der Domänendienst einen Prozess kapselt , der Teil der allgegenwärtigen Sprache ist. Um seine Rolle zu erfüllen, muss es Repositorys verwenden - und das ist völlig in Ordnung.
Das Hinzufügen eines Domänendienstes, der ein Repository mit einer Methode namens
persist
umschließt , bietet jedoch nur einen geringen Mehrwert.Auf dieser Basis ist es kein Problem, das Repository direkt vom Anwendungsservice aus zu verwenden, wenn Ihr Anwendungsservice einen Anwendungsfall ausdrückt, bei dem nur mit einem einzelnen Aggregat gearbeitet werden muss.
quelle
Es gibt ein Problem mit der akzeptierten Antwort:
Das Domain-Modell darf nicht vom Repository abhängen und der Domain-Service ist Teil des Domain-Modells -> Der Domain-Service sollte nicht vom Repository abhängen.
Sie sollten stattdessen alle Entitäten zusammenstellen, die für die Ausführung der Geschäftslogik bereits im Anwendungsservice erforderlich sind, und dann Ihre Modelle nur mit instanziierten Objekten versehen.
Nach Ihrem Beispiel könnte es so aussehen:
Faustregel: Das Domain-Modell hängt nicht von den äußeren Schichten ab
Application vs Domain Service Aus diesem Artikel :
Domänendienste sind sehr detailliert, da Anwendungsdienste eine Fassade für die Bereitstellung einer API darstellen.
Domänendienste enthalten Domänenlogik, die natürlich nicht in eine Entität oder ein Wertobjekt eingefügt werden kann, wohingegen Anwendungsdienste die Ausführung der Domänenlogik koordinieren und selbst keine Domänenlogik implementieren.
Domänendienstmethoden können andere Domänenelemente als Operanden und Rückgabewerte haben, wohingegen Anwendungsdienste triviale Operanden wie Identitätswerte und primitive Datenstrukturen verarbeiten.
Anwendungsdienste deklarieren Abhängigkeiten von Infrastrukturdiensten, die zum Ausführen der Domänenlogik erforderlich sind.
quelle
Keines Ihrer Muster ist gut, es sei denn, Ihre Dienste und Objekte kapseln eine zusammenhängende Reihe von Verantwortlichkeiten.
Sagen Sie zunächst, was Ihr Domain-Objekt ist, und besprechen Sie, was es in der Domain-Sprache tun kann. Wenn es gültig oder ungültig sein kann, warum sollte es nicht eine Eigenschaft des Domänenobjekts selbst sein?
Wenn zum Beispiel die Gültigkeit eines Objekts nur in Bezug auf ein anderes Objekt Sinn macht, haben Sie möglicherweise eine Verantwortlichkeits-Validierungsregel X für Domänenobjekte, die in eine Reihe von Diensten eingekapselt werden kann.
Muss ein Objekt zur Validierung in Ihren Geschäftsregeln gespeichert werden? Wahrscheinlich nicht. Die Verantwortung für das Speichern von Objekten liegt normalerweise in einem separaten Repository-Objekt.
Nun möchten Sie eine Operation ausführen, die eine Reihe von Verantwortlichkeiten abdeckt, ein Objekt erstellt, validiert und, falls gültig, speichert.
Gehört dieser Vorgang zum Domänenobjekt? Machen Sie es dann zu einem Teil dieses Objekts, z
ExamQuestion.Answer(string answer)
Passt es zu einem anderen Teil Ihrer Domain? Leg es dort hin
Basket.Purchase(Order order)
Möchten Sie lieber ADM REST-Services ausführen? OK dann.
quelle