Anämische Domänenmodelle und Injektion von Domänendiensten

19

Das anämische Domänenmodell wird von Martin Fowler als Antimuster im domänengetriebenen Design beschrieben. Um Geschäftslogik auf den Domänenmodellen zu haben, werden häufig Domänendienste verwendet. Das Injizieren von Domänendiensten in Domänenmodelle wird von Vaughn Vernon jedoch als schädlich eingestuft (siehe "Implementieren von domänengesteuertem Design", Seite 409).

Meiner Meinung nach sind diese Meinungen widersprüchlich, stimmt das? Wie können beide Punkte berücksichtigt werden?

Ist es wirklich reich Domain - Modell mit Domain - Services injiziert vs. anämischen Domänenmodell und normalen Domain - Services ?

Sjoerd222888
quelle
4
Ich bin auf keinen Fall ein Experte in diesem Bereich, aber ich dachte, die Art der Logik, die in Domänendiensten und in Domänenentitäten verwendet wurde, war grundlegend anders. Die Logik, die zu Entities gehört, ist die Logik, die benötigt wird, um das Objekt in einem korrekten Zustand zu halten. Dies beinhaltet Validierungs- und Transformationslogik. Domänendienste hingegen sind für die Logik höherer Ebenen gedacht. So würde beispielsweise ein Domänendienst einen Geschäftsprozess modellieren, an dem mehrere verschiedene Entitätstypen beteiligt sind. Dies ist auf komplexe Weise möglich.
MetaFight
2
@MetaFight: Auch wenn ein Geschäftsprozess mehrere Entitäten auf komplexe Weise beeinflusst, können Sie dies ohne Dienste erreichen, wenn Sie ein gutes aggregiertes Stammdomänenmodell voraussetzen, dh ein Domänenmodell, das Zugriff auf alle betroffenen Entitäten als Eigenschaften oder Felder für sich selbst hat.
Greg Burghardt
Das macht Sinn :)
MetaFight

Antworten:

16

Ein anämisches Modell ist einfach ein Datencontainer. Es enthält kein Verhalten. (Dies könnte tatsächlich als eine gute Sache im Funktionsparadigma angesehen werden.) Das Gegenteil eines anämischen Modells ist kein Modell, das voll von Domänendiensten ist. Sie beschreiben zwei Extreme - beide sind schlecht.

Wenn Sie ein anämisches Modell haben, werden Sie das, was OOP bietet, nicht voll und ganz zu schätzen wissen. Wenn Sie anfangen, Services in diese Modelle einzufügen, werden Sie wahrscheinlich Bedenken einfließen lassen, die nicht dazugehören. Entweder das oder dein Modell ist anämischer als du denkst. Warum sollten Sie den Service anders benötigen als etwas, das benötigt wird, aber fehlt? (Fehlen könnte Anämie bedeuten.)

Das Vermeiden beider "Tells" führt zu einem stärkeren Design. Haben Sie etwas in einem Service, das ein Model benötigt? Vielleicht sollte es zum Modell verschoben werden. Wenn nicht, sollten Sie Ihre Bedenken vielleicht noch einmal überdenken. Das Verhalten eines Modells sollte innerhalb des Modells funktionieren . Sie sollte sich hauptsächlich (wenn nicht nur) mit Mitgliedern befassen. Aber denken Sie daran, es wird immer noch Dinge geben, die am oder mit dem Modell funktionieren . Zum Beispiel sollten Modelle keine TCP-Verbindungen öffnen oder auf UI-Ereignisse warten, auch wenn sie irgendwie involviert sind. Das liegt in der Verantwortung eines anderen und dass niemals jemand in das Modell gehört.

Scant Roger
quelle
7
Ein guter Unterschied, an den ich mich gerne erinnere, ist, dass Ihr Domänenmodell Geschäftslogik implementiert und Ihre Domänendienste die Geschäftslogik auf den Domänenmodellen ausführen . Der Unterschied ist, wer wen anruft. Dienste können Domänenmodellmethoden aufrufen. Wenn Domänenmodelle Dienstmethoden aufrufen, haben Sie das Muster über den Kopf gekippt.
Greg Burghardt
7

Das ist kein Widerspruch. Beide Befürworter möchten, dass Sie Ihren tatsächlichen Code in das Domänenobjekt selbst einfügen.

dh

public class Order
{
    private string status = "not bought";
    public void Buy()
    {
        this.status = "bought";
    }
}

vs ADM

public class Order
{
    public string Status = "not bought";
}

public class BuyingService
{
    public Order Buy(Order order)
    {
         Order o = new Order();
         o.status = "bought";
         return o;
    }
}

vs injizierten Dienstleistungen

public class Order
{
    public Order(IBuyingService bs)
    {
        _bs = bs;
    }
    private IbuyingService _bs;
    private string status = "not bought";
    public void Buy()
    {
        this.status = _bs.Buy();
    }
}

public class BuyingService : IBuyingService
{
    public string Buy()
    {
         return = "bought";
    }
}

Ehrlich gesagt, hat jeder Ansatz Vor- und Nachteile. Die Entscheidung, die Sie treffen, hängt größtenteils von Ihren persönlichen Vorlieben ab

Ewan
quelle