貧血ドメインモデルとドメインサービスインジェクション


19

貧血のドメインモデルは、 Martin Fowler氏によってドメイン駆動設計におけるアンチパターンとして記載されています。ドメインモデルでビジネスロジックを使用するには、多くの場合、ドメインサービスが使用されます。ただし、ドメインモデルへのドメインサービスの注入は、Vaughn Vernonにとって有害で​​あると考えられています(「ドメイン駆動設計の実装」を参照)。

私の意見では、これらの意見は矛盾している、これは本当ですか?両方のポイントをどのように考慮することができますか?

それは実際にされたドメインサービスと豊富なドメインモデルは、注入された貧血のドメインモデルと通常のドメインサービス


4
私は決してこれに関する専門家ではありませんが、ドメインサービスとドメインエンティティに入るロジックのタイプは根本的に異なると思いました。エンティティーに入るロジックは、オブジェクトを正しい状態に保つために必要なロジックです。これには、検証および変換ロジックが含まれます。一方、ドメインサービスは、より高いレベルのロジック用です。したがって、たとえば、ドメインサービスは、複数の異なる種類のエンティティを含むビジネスプロセスをモデル化するのは複雑な方法です。
MetaFight

2
@MetaFight:ビジネスプロセスが複数のエンティティに複雑な方法で影響を与える場合でも、適切な集約ルートドメインモデル、つまり、影響を受けるすべてのエンティティに自身のプロパティまたはフィールドとしてアクセスできるドメインモデルを指定すると、サービスなしでこれを実現できます。
グレッグブルクハート

それは理にかなっています:)
MetaFight

回答:


16

貧血モデルは単なるデータコンテナーです。動作は含まれていません。(これは実際には機能的パラダイムでは良いことと考えられるかもしれません。)貧血モデルの反対は、ドメインサービスで満たされたモデルではありません。あなたは2つの極端を説明しています-両方とも悪いです。

貧弱なモデルを持っている場合、OOPが提供するものを完全に受け入れているわけではありません。これらのモデルにサービスを注入し始めると、そこに属さない懸念を注入する可能性があります。それまたはあなたのモデルはあなたが思っているよりも貧血です。なぜ必要なのに欠けているものを提供する以外のサービスが必要なのでしょうか?(欠落は貧血を意味する場合があります。)

両方の「テル」を回避すると、デザインが強化されます。モデルに必要なサービスに何かありますか?モデルに移動する必要があるかもしれません。そうでない場合は、懸念を再考する必要があります。モデルの動作はモデル内で機能するはずです。それは主に(それだけではないにしても)メンバー自身に関係するはずです。しかし、まだ、物事という仕事があるだろう、覚えているモデル。たとえば、モデルが何らかの形で関与している場合でも、モデルがTCP接続を開いたり、UIイベントをリッスンしたりしてはなりません。それは他の誰かの責任であり、誰かがモデルの内部に決して所属しないことです。


7
覚えておきたい優れた特徴は、ドメインモデルビジネスロジックを実装し、ドメインサービスがドメインモデルでビジネスロジックを実行することです。違いは誰が誰を呼んでいるかです。サービスはドメインモデルメソッドを呼び出すことができます。ドメインモデルがサービスメソッドを呼び出している場合は、頭の上でパターンを反転しています。
グレッグブルクハート

7

矛盾していません。両方の支持者は、実際のコードをドメインオブジェクト自体に配置することを望んでいます。

すなわち。

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;
    }
}

対注入サービス

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";
    }
}

率直に言って、各アプローチにはプラスとマイナスがあります。あなたが選択するものは主に個人的な好みの問題です

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.