2

ASP.NET MVC を使用して Web ベースのアプリケーションを開発しています。私は、薄い/貧血モデルではなく、豊富なドメイン モデルを使用しようとしています。

Onion アーキテクチャに沿ってソリューションをモデル化しました。さまざまなプロジェクトは次のとおりです。 ここに画像の説明を入力

  • {}.Domain.Core - インフラストラクチャ レイヤーに実装される IDbContext などのドメイン オブジェクトとインターフェースが含まれます
  • {}.Database - データベース プロジェクトです。
  • {].Infrastructure - ロギング、データ アクセスなどの実装が含まれています。
  • {}.Web - ビューとコントローラ

**** データ アクセスは dapper を使用して行われ、IDbContext は 2 つの単純なコマンド、クエリ インターフェイスのラッパーです。各クエリを個別のクラスとして分離しました。

議論のために、私はアプリケーションのごく一部を取り上げています。

タグ、権限などの他のメタデータとともにドキュメントを含む、バージョン管理されたドキュメント ライブラリがあります。

私の文書オブジェクトの単純化されたモデルは以下のとおりです

ここに画像の説明を入力

これらの各操作にはビジネス ロジックが含まれているため、ドメイン オブジェクト内で操作を定義する必要があります。「削除」を操作としましょう。操作を実行する必要があります

  • ユーザーが削除する権限を持っているかどうかを検証する
  • この削除によって影響を受ける関連付けがないかどうかを確認します
  • 進行中のワークフローがないかどうかを確認する
  • トランザクションでデータベースから実際のアイテムを削除する

上記の例に示すように、この操作を完了するにはデータベース コンテキストが必要です。モデリングがドメインオブジェクトにIDbContextを持たせ、公開されたクエリを実行できるようにすることである場合、私が現在考えている方法。

ここに画像の説明を入力

コントローラー クラスでは、ドメイン オブジェクトを呼び出して操作を実行します。

ドメイン オブジェクトで IDbContext を渡しても問題ないかどうかわかりません。そうでない場合、これをモデル化するためのより良い方法は何ですか?

1) ほとんどの場合、コントローラーはサービス層の最初の層として機能する 2) サービス層はドメインから別のクラスに同じメソッドを複製しているだけなので、別のサービス層を持つことに確信が持てない

このデザインを改善する方法を教えてください。

4

1 に答える 1

3

IDbContextドメインエンティティの取得と保存中にビジネスロジックのみを担当する必要があるドメインモデルの主な原則にブレーキをかけるようなものを注入することは、インフラストラクチャ層の責任です。はい、インターフェースで注入し、実際の実装を隠しますが、ドメインモデルにいくつかのストレージを認識させます。

また、上記の削除に必要な手順は、Document完全に Document オブジェクトに属しているわけではありません。ユーザー権限の最初のステップと次のケースを考えてみましょう。

  • 管理者ロールを持つユーザーは、すべてのドキュメントを削除できる必要があります
  • ドキュメントの所有者にドキュメントの削除を許可する必要があります

最初のケースでは、ユーザーと削除するドキュメントの間に接続がない可能性があります。管理者ユーザーは何でもできます。これは、2 つの銀行口座があり、両方の口座に関係するが責任を負わない送金操作を行う古典的な例のようなものです。これが、ドメイン サービスの出番です。それらをサービス層サービスと混同しないでください。ドメイン サービスはドメイン モデルの一部であり、ビジネス ロジックのみを担当します。

私があなたなら、DeleteDocumentメソッドを使用して新しいドメイン サービスを作成します。これにより、上記の最初の 3 つのステップがパラメーターとして受け入れUserられDocumentます。4 番目のステップは、リポジトリで実行する必要があります。言ってる意味がわからない

リポジトリを追加する価値はあまりありませんでした

しかし、ドメイン モデルの観点からは、既にIDbContext. エンティティごとにリポジトリまたは個別のリポジトリを実装するためのパターンを意味していたと思います。長期的には、コントローラー内の疑似コードは次のようになります。

var user = bdContext<User>.SelectById(userId);
var document = bdContext<Document>.SelectById(docId);
var docService = new DocumentService();
docService.DeleteDocument(document, user);  //  Throw exception here if deletion is not allowed
bdContext<Document>.Delete(document);

アプリケーションの多くの場所でこのロジックが必要になると予想される場合は、サービス レイヤー サービスにラップするだけで済みます。

ドメイン モデリングについて詳しく知りたい場合は、DDD に関するEric Evansの本を読むことをお勧めします。これは、エンティティ、値オブジェクト、ドメイン サービスなどの意味について詳しく説明しています。

コメントへの回答: そうではありませんが、ドメイン サービスはドメインの一部であるため、実装とインターフェイスの両方もドメインの一部です。ドメイン サービスを作成するには、2 つ以上のオブジェクトが相互に対話しなければならないという事実だけでは不十分です。例としてフライト予約システムを考えてみましょう。、などのさまざまなプロパティを持つFlightエンティティがあります。エンティティには、座席のリストへの参照も必要です。(ビジネス、エコノミーなど)、(アイル、ロウ、ミドル)などのプロパティを持つ別のエンティティにすることもできます。ドメインサービスはこちら 本来のようにDepartureCityArrivalCityFlightSeatClassTypeFlightSeatSeatプロパティは、 の子オブジェクトと見なされなければ意味がありませんFlight。コンテキストSeat外からエンティティをクエリするケースが発生する可能性はほとんどありません。Flightしたがって、ここで a を予約するのはエンティティSeatの責任であり、予約ロジックをクラスに配置しても問題ありません。これは、ドメイン サービスを作成する必要がある場合に試して説明するための単なる例であり、実際のシステムはまったく別の方法でモデル化できることに注意してください。したがって、次の 3 つの基本的な手順に従って、ドメイン サービスが必要かどうかを判断してみてください。FlightFlight

  1. サービスによって実行される操作は、エンティティまたは値オブジェクトに本来属していないドメインの概念を参照します。
  2. 実行された操作は、ドメイン内の他のオブジェクトを参照しています。
  3. 操作はステートレスです。

ドメイン/ビジネス層ではなく、アプリケーション/サービス層であるコントローラーから dbcontext にアクセスしています。ドメイン モデルはビジネス ロジックのみを扱います。永続化ロジックを認識する必要はありません。上記の例から、DocumentService には dbcontext の参照がないことがわかります。

于 2014-10-18T23:26:30.680 に答える