Ich passe das domänengetriebene Design seit ungefähr 8 Jahren an und selbst nach all den Jahren gibt es immer noch eine Sache, die mich nervt. Das heißt, es wird nach einem eindeutigen Datensatz im Datenspeicher für ein Domänenobjekt gesucht.
Im September 2013 erwähnte Martin Fowler das TellDon'tAsk-Prinzip , das nach Möglichkeit auf alle Domänenobjekte angewendet werden sollte, die dann eine Nachricht über den Ablauf der Operation zurückgeben sollten (im objektorientierten Design erfolgt dies meistens durch Ausnahmen, wenn die Operation war nicht erfolgreich).
Meine Projekte sind normalerweise in viele Teile unterteilt, von denen zwei Domain (mit Geschäftsregeln und nichts anderem, die Domain ist völlig persistenzunabhängig) und Services sind. Dienste, die sich mit der Repository-Schicht auskennen, die für CRUD-Daten verwendet wird.
Da die Eindeutigkeit eines zu einem Objekt gehörenden Attributs eine Domänen- / Geschäftsregel ist, sollte das Domänenmodul lang sein, damit die Regel genau dort ist, wo sie sein soll.
Um die Eindeutigkeit eines Datensatzes überprüfen zu können, müssen Sie den aktuellen Datensatz, normalerweise eine Datenbank, abfragen, um herauszufinden, ob bereits ein anderer Datensatz mit einem Beispiel Name
vorhanden ist.
Wenn man bedenkt, dass die Domänenschicht die Persistenz nicht kennt und keine Ahnung hat, wie die Daten abgerufen werden sollen, sondern nur, wie sie verarbeitet werden sollen, kann sie die Repositorys selbst nicht wirklich berühren.
Das Design, das ich damals angepasst habe, sieht folgendermaßen aus:
class ProductRepository
{
// throws Repository.RecordNotFoundException
public Product GetBySKU(string sku);
}
class ProductCrudService
{
private ProductRepository pr;
public ProductCrudService(ProductRepository repository)
{
pr = repository;
}
public void SaveProduct(Domain.Product product)
{
try {
pr.GetBySKU(product.SKU);
throw Service.ProductWithSKUAlreadyExistsException("msg");
} catch (Repository.RecordNotFoundException e) {
// suppress/log exception
}
pr.MarkFresh(product);
pr.ProcessChanges();
}
}
Dies führt dazu, dass Dienste Domänenregeln definieren und nicht die Domänenschicht selbst, und dass die Regeln auf mehrere Abschnitte Ihres Codes verteilt sind.
Ich habe das TellDon'tAsk-Prinzip erwähnt, da der Dienst, wie Sie deutlich sehen können, eine Aktion anbietet (er speichert entweder die Product
Ausnahme oder löst eine Ausnahme aus), aber innerhalb der Methode arbeiten Sie Objekte mithilfe eines prozeduralen Ansatzes.
Die naheliegende Lösung besteht darin, eine Domain.ProductCollection
Klasse mit einer Add(Domain.Product)
Methode zu erstellen , die ProductWithSKUAlreadyExistsException
das auslöst. Die Leistung ist jedoch sehr gering, da Sie alle Produkte aus dem Datenspeicher abrufen müssten, um im Code herauszufinden, ob ein Produkt bereits dieselbe SKU hat als das Produkt, das Sie hinzufügen möchten.
Wie löst ihr dieses spezielle Problem? Dies ist an sich kein wirkliches Problem. Ich habe die Service-Schicht jahrelang bestimmte Domain-Regeln darstellen lassen. Die Service-Schicht dient normalerweise auch komplexeren Domain-Operationen. Ich frage mich nur, ob Sie während Ihrer Karriere auf eine bessere, zentralere Lösung gestoßen sind.