web-dev-qa-db-ja.com

エンティティ/ビジネスオブジェクトの依存関係を解決するためにIoCコンテナーを使用しないのはなぜですか?

DIの背後にある概念は理解していますが、私はさまざまなIoCコンテナーで何ができるかを学習しています。ほとんどの人がIoCコンテナーを使用してステートレスサービスを接続することを推奨しているようですが、エンティティーなどのステートフルオブジェクトにそれらを使用することはどうでしょうか。

それが正しいか間違っているかに関係なく、私は通常、その振る舞いに外部クラスが必要な場合でも、振る舞いをエンティティに詰め込みます。例:

public class Order : IOrder
{

    private string _ShipAddress;
    private IShipQuoter _ShipQuoter;

    public Order(IOrderData OrderData, IShipQuoter ShipQuoter)
    {
        // OrderData comes from a repository and has the data needed 
        // to construct order
        _ShipAddress = OrderData.ShipAddress;  // etc.
        _ShipQuoter = ShipQuoter;

    }

    private decimal GetShippingRate()
    {
        return _ShipQuoter.GetRate(this);
    }
}

ご覧のとおり、依存関係はコンストラクター注入です。さて、いくつか質問があります。

  1. エンティティをShipQuoterなどの外部クラスに依存させることは悪い習慣と見なされていますか?これらの依存関係を排除すると、定義を正しく理解していれば、貧血の領域に向かうように思えます。

  2. IoCコンテナを使用してこれらの依存関係を解決し、必要に応じてエンティティを構築することは悪い習慣ですか?これは可能ですか?

洞察をありがとう。

80
Casey Wilkins

最初の質問は答えるのが最も難しいです。エンティティを外部のクラスに依存させるのは悪い習慣ですか?それは確かに最も一般的なことではありません。

たとえば、リポジトリをエンティティに挿入すると、実質的に アクティブレコードパターン の実装ができます。このパターンが便利なためにこのパターンを好む人もいれば、(私のような)他の人が 単一の責任の原則 (SRP)に違反しているため、コードの臭いやアンチパターンと見なしている人もいます。

エンティティに他の依存関係を注入すると、同じ方向(SRPから離れる方向)に引っ張られると主張できます。一方、これを行わない場合、プルは Anemic Domain Model に向かうことは間違いなく正しいです。

グレッグヤングの(放棄された)に出会うまで、私はこれすべてに長い間苦労していました DDDDに関する論文 ここで、彼はなぜステレオタイプのn層/ nレイヤーアーキテクチャが常にCRUDy です(したがって、貧弱です)。

焦点を名詞の代わりに Commands and Events としてドメインオブジェクトのモデリングに移すと、適切なオブジェクト指向ドメインモデルを構築できるようになります。

2番目の質問の方が答えやすいです。いつでも Abstract Factoryを使用して、実行時にインスタンスを作成する を使用できます。 Castle Windsorを使用すると、Typed Factory機能を使用することもでき、工場を手動で実装する負担が軽減されます。

88
Mark Seemann

これは古い投稿ですが、追加したかったのです。 ctorで抽象化されたリポジトリを渡したとしても、ドメインエンティティは永続化しないはずです。これは、これがSRPに違反しているだけでなく、DDDの集計に反していることを示唆しています。説明すると、DDDは本質的に深いグラフを持つ複雑なアプリに適しています。したがって、根本的な「子」への変更を永続化するために集約ルートまたは複合ルートを使用するため、個々の子に永続性を注入すると、子とライフサイクルまたは集約を「担当」する必要がある複合ルートまたは集約ルート。もちろん、複合ルートまたは集約は、それ自体のグラフも永続化しません。もう1つは、DDDオブジェクトの依存関係を注入することです。注入されたドメインオブジェクトには、他のイベントが発生してその状態をハイドレートするまで、事実上状態がありません。コードの利用者は、カプセル化に違反するビジネス動作を呼び出す前に、ドメインオブジェクトを最初に初期化またはセットアップする必要があります。

1
user1538467