はじめに
本記事は以下の書籍を読んで学んだことをまとめることを目的としています。
前回の続きです。
ドメイン駆動設計入門 ボトムアップでわかる! ドメイン駆動設計の基本 | 成瀬 允宣 |本 | 通販 | Amazon
依存関係のコントロール
多くのオブジェクトに依存され、依存しているようなオブジェクトがあるとすると、少しの変更が多くのオブジェクトに影響してしまいます。
依存することは避けられないので、コントロールすることが必要です。
具体的なクラスや、具体的な技術要素への依存は、変化しやすかったり、ソフトウェアの柔軟性が落ちるたりするため、避けるべきです。(前回記事も参照してください。)
抽象的で変化しにくいインターフェースに依存することによって、ソフトウェアの柔軟性を保ち、また、インターフェースを実装するクラスを変更しても影響が出ないようにできます。
実装上の工夫
ServiceLocatorパターン
事前にServiceLocatorオブジェクトに依存関係の解決先を登録しておき、必要になったらその場所でインスタンスを取得するパターンです。
オブジェクトのインスタンス化を行う実装が点在するのを防げるため、実装クラスを変更することになっても、変更箇所はServiceLocatorオブジェクトに依存関係の解決先を登録する箇所のみで済みます。
※一般的にServiceLocatorパターンではクラスを定義しただけでは、どのクラスと依存があるのかがわかりにくいため、アンチパターンと言われています。依存関係が見えないため、増えた際も気が付きにくく、テストもしづらいです。
IoC Containerパターン
コンストラクタでDIできるようにし、依存するオブジェクトのインスタンス化をIoC Containerで行うパターンです。
ServiceLocatorパターンとは異なり、依存関係をコンストラクタ引数で受け取るため、依存関係が見えやすいです。また、依存関係が増えるときはコンストラクタ引数に増えるので、もしテストのリファクタをし忘れた際でも、コンパイルエラーとなり気が付きやすいです。
ファクトリ
オブジェクトの生成を責務とするオブジェクトのことをファクトリと呼びます。
ファクトリを使う理由
複雑なオブジェクトの生成をドメインオブジェクト内で行うと、その複雑な実装がドメインオブジェクトのコードに表れて、ドメインの意図が読み取りづらくなってしまうためです。
その生成処理自体をオブジェクトして定義することで、ドメイン層内に知識を収めつつ(複雑でドメインの意図がぼやけるからと言ってクライアント側に生成の責務を押し付けない)、ほかのドメインオブジェクトからは簡単に複雑なオブジェクトを生成できるようにします。
ファクトリはいつ使うべきか
ひとつの指標として、コンストラクタでほかのオブジェクトを生成するようなコンストラクタが単純でなくなる場合が挙げられていました。
このオブジェクトのコンストラクタが変更された際に、すべての生成箇所の修正が必要になってします。他のオブジェクトをただインスタンス化するだけであっても、複雑さが増してしまいます。
なんでもファクトリで生成されるべきではないと思います。シンプルに生成できるのであればそれが一番良いと思います。ただ、ファクトリで生成することを一度考慮してみることが重要だと思いました。
さいごに
ここまでお読みいただき、ありがとうございました。
長くなるので、#5に続きます。