エンタープライズ アプリケーション アーキテクチャのパターンで、Martin Fowler は、ドメイン ロジックを編成するための 2 つのパターン、ドメイン モデルとサービス層について説明しています。ドメイン モデル パターンは「純粋な OOP」アプローチであり、モデル (おそらく ORM を使用してデータベースから検索されるオブジェクト) にビジネス ロジックが含まれます (ただし、おそらく別のクラスのロジックに委譲するだけです)。
サービス層パターンはドメイン モデル パターンに似ていますが、その前に実行可能なビジネス オペレーションを含む薄い層があります。MVC では、コントローラーは主にサービス層と対話します。適切に設計された MVC Web アプリケーションのほとんどは、このパターンを使用していると思います。
さて、私の質問に。Martin は、ドメイン モデル アプローチはよりオブジェクト指向のアプローチであり、したがってより優れていると示唆しています。私の経験では、実際に実装するのは非常に困難です (不可能を参照)。
上の最初の図の例を見てください。2 つの「エンティティ」Contract
とがありProduct
ます。これらは、マッパーを使用してデータベースに永続化されます。例では、 がありRecognitionStrategy
ます。Martin は、実際のビジネス ロジックを含むこの戦略に委任するためのメソッドをエンティティ自体に配置します。contract.calculateRecognitions
クライアントは、またはを使用してこの計算を実行しますcontract.recognizedRevenue(someDate)
。同様の設計を実装する場合、通常、クライアント インターフェイスをstrategy.calculateRecognitions(contract)
およびとして記述しますstrategy.recognizedRevenue(contract, someDate)
。これにより、戦略と契約を調整するためにサービス層が必要になります。使用される具体的な戦略がサービスに注入されます。
マーティンのアプローチは、デザインの観点からは間違いなく魅力的ですが、セットアップを回避する作業ははるかに困難です。
- a をインスタンス化するときに戦略を渡すのは
Product
面倒です。使用する具体的なサービスでカリー化されたファクトリを介してを作成する必要がありますProduct
。これにより、作成時にエンティティに渡されます。 - データベース アクセスに対するきめ細かい制御ができません。ORM の設定によっては、 への
Contract
委任がProduct
ごとにクエリを実行する場合がありますProduct
。Product
マッパー (または ORM) に s を貪欲にロードすることは、 をロードするContract
が を呼び出すつもりがない場合、熱心すぎるかもしれませんcontract.calculateRecognitions()
。私のアプローチでは、サービスがデータベース抽象化レイヤーの知識を持っているため、よりきめ細かい制御が可能になりますが、エンティティはそうすべきではありません。
ここに列挙していない問題点が実際にはもっとあると確信しています。
Martin のアプローチには、純粋なデータ モデル パターンを使用するよう説得する具体的な利点は何ですか?