1

私たちは、階層化されたアプリケーションのアーキテクチャの開発に取り組んできました。モバイルブラウザーと「通常の」ブラウザーの両方にサービスを提供するASP.NETMVCプレゼンテーション層を計画しています。つまり、ユーザーがモバイルデバイスでサイトに移動した場合に、モバイルブラウザ用に最適化されたビューを提供すると同時に、次のように最適化された「通常の」ビューを提供するには、同じASP.NETMVCプレゼンテーションレイヤーが必要です。ユーザーがデスクトップ/ラップトップコンピューターを使用している場合は、デスクトップ/ラップトップブラウザー。現時点では、ネイティブモバイルアプリのサポートを計画していませんが、将来的にその機能を追加する可能性があります。さらに、アーキテクチャには、ドメインモデル(ドメインエンティティ、ドメインサービスなど、アプリケーションサービス、

ただし、開発中のシステムに適用されるドメインサービス、アプリケーションサービス、およびドメインエンティティの動作(メソッド)の違いを理解しようとしています。以下は、調査のためのシステムの高レベルのユースケースです。

レポートとレポートグループがあります。これら2つのエンティティの間には多対多の関係があります。DBテーブルは次のとおりです。Reports<->Jct_Reports_ReportGroups<-> ReportGroups、ドメインエンティティは次のようになります。

Report class :
    public string ReportName { get; set; }
    ...
    public virtual ICollection<ReportGroup> ReportGroups { get; set; }

ReportGroup class :
    public string GroupName { get; set; }
    ...
    public virtual ICollection<Report> Reports { get; set; }

もちろん、ユーザーは(レポートグループを作成せずに)レポートを作成することも、1つまたは複数のレポートを含むレポートグループを作成することもできます。また、ユーザーはレポートを削除できます。これが発生すると、いくつかのことが発生します。まず、レポートがレポートグループに含まれているかどうかを確認します(1つのレポートが多くの異なるレポートグループに含まれる場合があります)。レポートがいずれかのレポートグループで見つかった場合は、各レポートグループを調べて、レポートをレポートグループから削除します(Jct_Reports_ReportGroupsテーブルから行を削除します)。次に、削除するレポートが含まれているレポートグループごとに、レポートグループに他のレポートが残っているかどうかを確認します。レポートグループに他のレポートがない場合は、レポートグループも削除します(ReportGroupsテーブルから行を削除します)。レポートグループに他のレポートが残っている場合、レポートグループは削除されません。これらの操作がすべて成功すると、ユーザーが選択したとおりに削除するレポートが削除されます([レポート]テーブルの行を削除します)。最後に、レポートの削除が成功したかどうかを示すメッセージがユーザーに表示されます。

これが、アプリケーション全体のほんの一部を理解するのに役立つ適切なユースケースであることを願っています。

ドメインサービスは、ドメインオブジェクト内に自然に収まらず、一般的なCRUD操作ではないビジネスロジックをカプセル化することをどこかで読みましたが、アプリケーションサービスは、外部の消費者がシステムと通信するために使用します-消費者がCRUD操作にアクセスする必要がある場合、ここで公開されます。しかし、POCOドメインエンティティでどのメソッド(ビジネスロジック)が使用されるのか、どのビジネスロジックがドメインサービスと見なされてビジネスレイヤーに含まれるのか、どのビジネスロジックがアプリケーションサービスと見なされるのかがわかりません。アプリケーションサービス層。したがって、私の主な質問は次のとおりです。上記のユースケースを考えると、ドメインサービス、アプリケーションサービス、ドメインエンティティの動作(メソッド)をどのように分類するかについての推奨事項は何でしょうか。

4

1 に答える 1

4

それはかなりの質問です。

私は自分自身のために次の非厳密なガイドラインを好みます:

アプリケーションサービス:システムとのユーザーインタラクションを説明する一連のユースケースがあると想像してください。特定の入力と出力を持つケースがあるLoginとしましょう。Cash transferまた、成功と失敗のシナリオについても説明します。それがあれば、一般的にアプリケーションサービスの仕様があります。私は両方LoginResul Login(name, pass)TransferResult CashTrasnfer(from, to, amount)メソッドを公開し、インとアウト、および成功/失敗の動作はほぼ同じです。

ユースケースを実現するために、アプリケーションサービスがBLを呼び出すことは非常に明白です(ただし、セキュリティやその他のアプリ固有のチェックが追加されます)。

ドメインサービス:あなたが説明するように:'ドメインオブジェクト内に自然に適合しません'。

CashTrasnferのユースケースがある場合、次のことを行う必要があります。

  • アカウントを読み込む'from'
  • アカウントをロードする'から'
  • 「バランス」から「チェック」//エラーが返される可能性があります
  • アカウントへのアクセスを確認する(ロックされているなど)//エラーが返される可能性があります
  • 'から'から'金額'を撤回
  • 金額を「〜」に入れます
  • (理想的には、それは単一の「ビジネス」トランザクションである必要があります)。

この関数がアカウントエンティティに適合しないことは明らかです。そのため、特別なものがあると便利ですTransferService


特にレポート/レポートグループの機能について-非論理的な参照がないため、エンティティスコープである可能性があります(すべてのアイテムはレポートから到達可能です)。

Report.Remove() {
    foreach(group in Groups) {
        group.RemoveReport(this);
    }
    repository.Remove(this);
} 
Group.RemoveReport(report) {
    reports.Remove(report);
    if(reports.Count == 0)
        repository.Remove(this);
}

または、レポートサービスとエンティティの間で分割します(リポジトリの参照には問題がある可能性があります)。

Report.RemoveFromAllGroups() {
   foreach(group in Groups) {
        group.RemoveReport(this);
        if(group.IsEmpty)
            //add to collection to return
    }
}
Service.Remove(report) 
{
    var emptyGroups = report.RemoveFromAllGroups();
    reportRepo.Remove(report);
    groupRepo.Remove(emptyGroups);
}
于 2012-05-31T10:14:00.050 に答える