質問

ドメイン駆動設計の一部で、あまり詳しく説明されていないように見えますが、ドメイン モデルをインターフェイスから分離する方法とその理由です。これが良い習慣であることを同僚に説得しようとしていますが、あまり進んでいないように思えます...

彼らは、プレゼンテーション層とインターフェイス層のどこでもドメイン エンティティを使用します。私が彼らに、ドメイン層をインターフェース層から分離するために表示モデルや DTO を使用するべきだと主張すると、彼らは、そのようなことをすることにビジネス価値が見出せないと反論します。なぜなら、今は保守すべき UI オブジェクトがあるからです。元のドメイン オブジェクトも同様です。

そこで、これを裏付ける具体的な理由をいくつか探しています。具体的には:

  1. プレゼンテーション層でドメイン オブジェクトを使用すべきではないのはなぜですか?
    (答えが明らかな「デカップリング」である場合、この文脈においてこれがなぜ重要なのか説明してください)
  2. ドメイン オブジェクトをインターフェイスから分離するには、追加のオブジェクトまたは構造を使用する必要がありますか?
役に立ちましたか?

解決

簡単に言えば、理由は実装とドリフトの1つです。はい。プレゼンテーション層は、ビジネスオブジェクトを適切に表現できるように、ビジネスオブジェクトについて知る必要があります。はい、最初は2種類のオブジェクトの実装に多くの重複があるように見えます。問題は、時間が経つにつれて、両側に物事が追加されることです。プレゼンテーションの変更、およびプレゼンテーション層のニーズは、ビジネス層から完全に独立したもの(たとえば、色)を含むように進化します。一方、ドメインオブジェクトは時間とともに変化し、インターフェイスから適切に分離されていない場合は、ビジネスオブジェクトに見かけ上良性の変更を加えることにより、インターフェイスレイヤーを台無しにするリスクがあります。

個人的に、物事にアプローチする最善の方法は、厳密に強制されたインターフェイスパラダイムを使用することだと思います。つまり、ビジネスオブジェクトレイヤーは、通信できる唯一の方法であるインターフェイスを公開します。インターフェイスに関する実装の詳細(ドメインオブジェクトなど)は公開されません。はい。これは、ドメインオブジェクトを2つの場所に実装する必要があることを意味します。インターフェイスレイヤーとBOレイヤー。しかし、この再実装は、最初は余分な作業のように思えるかもしれませんが、将来のある時点でTONSの作業を節約するデカップリングを実施するのに役立ちます。

他のヒント

私はこれに苦労しました。プレゼンテーションでDTOを使用するのが理にかなっている場合があります。私のシステムに会社のドロップダウンを表示したいとします。値をバインドするためにidが必要です。

まあ、サブスクリプションへの参照を持っている可能性のあるCompanyObjectをロードする代わりに、他に何を知っているのか、名前とIDでDTOを送り返すことができます。これは良い使い方です。

別の例を見てみましょう。私は見積もりを表すオブジェクトを持っています、この見積もりは人件費、機器などで構成されている可能性があり、ユーザーが定義した多くの計算があり、これらのすべてのアイテムを取得して合計します計算の)。このオブジェクトを2回モデリングする必要があるのはなぜですか? UIで計算を単純に列挙して表示できないのはなぜですか?

通常、ドメインレイヤーをUIから分離するためにDTOを使用しません。それらを使用して、ドメインレイヤーを制御できない境界から分離します。誰かがナビゲーション情報をビジネスオブジェクトに入れるという考えはばかげているので、ビジネスオブジェクトを汚染しないでください。

誰かが自分のビジネスオブジェクトに検証を入れるという考えは?これは良いことだと言っています。 UIには、ビジネスオブジェクトを検証する単独の責任を負わせないでください。あなたのビジネス層は MUST 独自の検証を行います。

busienssオブジェクトにUI生成コードを配置する理由は何ですか?私の場合、UIからUIコードseperatleyを生成する個別のオブジェクトがあります。私はビジネスオブジェクトをXmlにレンダリングするオブジェクトを分離していますが、このタイプの汚染を防ぐためにレイヤーを分離する必要があるという考えは、なぜビジネスオブジェクトにHTML生成コードを入れるのですか?

編集 もう少し考えてみると、UI情報がドメイン層に属する場合があります。そして、これはあなたがドメイン層と呼ぶものを曇らせるかもしれませんが、私はUIのルックアンドフィールと機能的なワークフローの両方で非常に異なる振る舞いをするマルチテナントアプリケーションに取り組みました。さまざまな要因に依存します。この場合、テナントとその構成を表すドメインモデルがありました。それらの構成には、たまたまUI情報が含まれています(たとえば、汎用フィールドのラベル)。

オブジェクトを永続可能にするためにオブジェクトを設計しなければならなかった場合、オブジェクトも複製する必要がありますか?新しいフィールドを追加する場合は、追加する場所が2つあることに注意してください。おそらく、DDDを使用している場合、すべての永続エンティティがドメインオブジェクトである場合、これは別の質問を提起しますか?私の例ではそれらがわかっていました。

SQLをASP / JSPページに入れないのと同じ理由で実行します。

プレゼンテーションおよびドメインレイヤーで使用するためにドメインオブジェクトを1つだけ保持すると、その1つのオブジェクトはすぐにモノリシックになります。 UI検証コード、UIナビゲーションコード、およびUI生成コードが含まれるようになりました。次に、すぐにすべてのビジネスレイヤーメソッドを追加します。これで、ビジネスレイヤーとUIがすべて混同され、それらすべてがドメインエンティティレイヤーで混乱しています。

その気の利いたUIウィジェットを別のアプリで再利用したいですか?さて、この名前、これら2つのスキーマ、およびこれらの18のテーブルを使用してデータベースを作成する必要があります。また、HibernateとSpring(または選択したフレームワーク)を構成して、ビジネス検証を行う必要があります。ああ、これらの85のその他の非関連クラスも含める必要があります。これらは、たまたま同じファイルにあるビジネスレイヤーで参照されているためです。

同意しません。

最適な方法は、プレゼンテーションレイヤーのドメインオブジェクトから始めることです。それ以外の場合はセンスが必要になります。

一般的な信念に反して、「ドメインオブジェクト」および「値オブジェクト」喜んでプレゼンテーション層に共存できます。そして、これはそれを行うための最良の方法です-あなたは両方の世界の利益を得、ドメインオブジェクトとの重複(および定型コード)を減らします;リクエスト全体で値オブジェクトを使用するための調整と概念の簡素化。

サーバーとUIで同じモデルを使用しています。そして、それは苦痛です。いつかリファクタリングする必要があります。

問題の主な理由は、データベース全体を参照せずにドメインモデルをシリアル化できるように、ドメインモデルを小さく分割する必要があるためです。これにより、サーバーでの使用が難しくなります。重要なリンクがありません。また、一部のタイプはシリアル化できず、クライアントに送信できません。たとえば、「タイプ」または任意の汎用クラス。非ジェネリックである必要があり、タイプは文字列として転送する必要があります。これにより、シリアル化のための追加のプロパティが生成されます。これらは冗長でわかりにくいものです。

もう1つの問題は、UI上のエンティティが実際には適合しないことです。データバインディングを使用しており、多くのエンティティには、UIの目的でのみ多くの冗長プロパティがあります。さらに、エンティティモデルには多くの「BrowsableAttribute」などがあります。これは本当に悪いです。

最後に、どちらの方が簡単かは問題だと思います。プロジェクトによっては正常に機能し、別のDTOモデルを作成する必要がない場所があります。

応答は、アプリケーションの規模に依存します。


シンプルなCRUD(作成、読み取り、更新、削除)アプリケーション

基本的なcrudアプリケーションの場合、機能はありません。エンティティの上にDTOを追加するのは時間の無駄です。スケーラビリティを増やさずに複雑さが増します。

ここに画像の説明を入力してください


中程度に複雑な非CRUDアプリケーション

このサイズのアプリケーションでは、真のライフサイクルとそれに関連付けられたいくつかのビジネスロジックを持つエンティティはほとんどありません。

このケースにDTOを追加するのは、いくつかの理由で良い考えです:

  • プレゼンテーション層は、エンティティが持つフィールドのサブセットのみを見ることができます。エンティティをカプセル化します
  • バックエンドとフロントエンドの間にカップリングなし
  • エンティティ内にビジネスメソッドがあり、DTOにはない場合、DTOを追加することは、外部コードがエンティティの状態を台無しにできないことを意味します。

ここに画像の説明を入力してください


複雑なエンタープライズアプリケーション

単一のエンティティには、複数の表示方法が必要になる場合があります。それぞれに異なるフィールドのセットが必要です。この場合、前の例と同じ問題が発生し、各クライアントに表示されるフィールドの量を制御する必要があります。 クライアントごとに個別のDTOを用意すると、表示するものを選択するのに役立ちます。

ここに画像の説明を入力してください

大部分の依存関係についてです。組織のコア機能構造には独自の機能要件があり、UIを使用してコアを変更および表示できるようにする必要があります。ただし、UIに対応するためにコア自体は必要ありません。 (発生する必要がある場合、通常はコアがプロパティデザインされていないことを示しています。)

私の会計システムには、会社の運営をモデル化することになっている構造とコンテンツ(およびデータ)があります。この構造は実際のものであり、使用している会計ソフトウェアに関係なく存在します。 (必然的に、特定のソフトウェアパッケージにはそれ自体の構造とコンテンツが含まれますが、課題の一部はこのオーバーヘッドを最小化することです。)

基本的に、人にはやるべき仕事があります。 DDDは、ジョブのフローとコンテンツに一致する必要があります。 DDDは、可能な限り完全に独立して行われる必要があるすべての仕事を明示することです。次に、UIを使用して、可能な限り透過的に、可能な限り生産的にジョブを実行できるようにします。

インターフェイスは、適切にモデル化された不変の機能コアに提供される入力とビューに関するものです。

くそ、私はこれが永続性と言った誓う

とにかく、これは同じことのもう1つの例です。Parnasの法則では、モジュールは秘密を保持する必要があり、秘密は変更可能な要件です。 (Bob Martinには、このバージョンの別のルールがあります。)このようなシステムでは、プレゼンテーションドメインとは無関係に変更できます。たとえば、価格をユーロで維持し、会社のオフィスでフランス語を使用しているが、価格をマンダリンのテキストでドルで表示したい会社などです。 ドメインは同じです。プレゼンテーションは変更される可能性があります。したがって、システムの脆弱性を最小限に抑えるために—つまり、要件の変更を実装するために変更する必要があるものの数—懸念を分離します。

プレゼンテーションではドメインレイヤーを参照できますが、UIからドメインオブジェクトへの直接のバインドはありません。ドメインオブジェクトは、適切に設計されていれば、データ表現ではなく動作に基づいていることが多いため、UIの使用を意図していません。 UIとドメインの間にマッピングレイヤーが必要です。 MVVM(MVP)はこのための良いパターンです。 UIをドメインに直接バインドしようとすると、問題が発生する可能性があります。それらには2つの異なる目的があります。

おそらく、UIレイヤーを十分に広い意味で概念化していないのでしょう。複数の形式の応答(Webページ、音声応答、印刷された文字など)および複数の言語(英語、フランス語など)の観点から考えます。

ここで、電話呼び出しシステムの音声エンジンが、Webサイトを実行するコンピューター(Windowsなど)とはまったく異なるタイプのコンピューター(Macなど)で実行されるとします。

もちろん、trapに陥るのは簡単です"私の会社では英語しか気にせず、LAMP(Linux、Apache、MySQL、PHP)でWebサイトを実行し、誰もが同じバージョンのFirefoxを使用しています ''しかし、5年後または10年後はどうですか?

「レイヤ間のデータ伝播」セクションも参照してください。以下では、説得力のある議論を提示すると思います:

http:// galaxy .andromda.org / docs / andromda-documentation / andromda-getting-started-java / java / index.html

Value Injecter 」のようなツールとプレゼンテーションレイヤーの「マッパー」のコンセプトビューを操作している間、各コードを理解するのがはるかに簡単です。コードが少しあると、すぐに利点が見えなくなりますが、プロジェクトがますます大きくなると、ビューを操作しながらサービスのロジックを入力する必要がないため、非常に満足します。ビューモデルを理解するためのリポジトリ。 View Modelは、腐敗防止レイヤーの広大な世界のもう1つの警備員であり、長期プロジェクトでは金の価値があります。

ビューモデルを使用する利点がないと思う唯一の理由は、プロジェクトが小さく、モデルの各プロパティにビューを直接バインドできるほど単純である場合です。しかし、将来的には、要件の変更とビュー内の一部のコントロールがモデルにバインドされず、ビューモデルの概念がない場合、多くの場所でパッチの追加を開始し、レガシコードを持つことになります。あなたは感謝しません。もちろん、リファクタリングを行ってview-viewmodelでビューモデルを変換し、YAGNIの原則に従いますが、必要でない場合はコードを追加しませんが、私にとっては、追加するために従う必要のあるベストプラクティスです。ビューモデルオブジェクトのみを公開するプレゼンテーション層。

ビューからドメインエンティティを分離することをお勧めする理由の実際の例を次に示します。

数か月前、私は簡単なUIを作成して、一連の3つのゲージを通して土壌サンプル中の窒素、リン、およびカリウムの値を表示しました。各ゲージには赤、緑、赤のセクションがありました。つまり、各コンポーネントが少なすぎるか多すぎる可能性がありましたが、中央に安全な緑のレベルがありました。

あまり考えずに、ビジネスロジックをモデル化して、これら3つの化学成分のデータと、3つのケースのそれぞれで許容されるレベルに関するデータ(モルまたは割合)。次に、UIをモデリングして、非常に異なるモデルを使用しました。このモデルは、ゲージラベル、値、境界値、および色を懸念していました。

これは、後で12個のコンポーネントを表示する必要があったときに、追加のデータを12個の新しいゲージビューモデルにマップしただけで、画面に表示されたことを意味します。また、ゲージコントロールを簡単に再利用して、他のデータセットを表示させることもできました。

これらのゲージをドメインエンティティに直接結合した場合、上記の柔軟性はなくなり、将来の変更は頭痛の種になります。 UIでカレンダーをモデル化するときに、よく似た問題に遭遇しました。 10人以上の出席者がいるときにカレンダーの予定を赤くする必要がある場合、これを処理するビジネスロジックはビジネスレイヤーに残り、UIのすべてのカレンダーを知る必要があります。赤になります。理由を知る必要はありません。

一般化されたセマンティクスとドメイン固有のセマンティクスの間に追加のマッピングを追加する唯一の賢明な理由は、ドメイン セマンティクスとは異なる一般化された (ただしマッピング可能な) セマンティクスに基づく既存のコード本体 (およびツール) にアクセスできることです。

ドメイン駆動設計は、直交する一連の機能ドメイン フレームワーク (ORM、GUI、ワークフローなど) と組み合わせて使用​​すると、最も効果的に機能します。ドメイン セマンティクスを公開する必要があるのは、外層の隣接関係のみであることを常に覚えておいてください。通常、これはフロントエンド (GUI) と永続的なバックエンド (RDBM、ORM) です。効果的に設計された介在層はドメイン不変であることができ、またそうすべきです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top