2

エンタープライズ アプリケーションでの EF の使用に関する Julie Lerman のビデオを見たことがあります。今、私は「Bounded Contexts」と彼女がそのシリーズで教えた他のものを使用して Web サイトを開発しています。

問題は、「ビジネス層」内から境界付けられたコンテキスト (BC) を使用する方法がわからないことです。より明確にするために: BL は、どの特定の BC を使用する必要があるかをどのように知る必要がありますか。

UI がビジネス層から製品のリストを要求するとします。BL には、製品のリストを返すメソッドがあります: GetAll(). このメソッドは、UI のどの部分 (サイト管理者、モデレーター、またはパブリック ユーザー) が製品のリストを要求したかを知りません。各ユーザー/シナリオには独自の境界付けられたコンテキストがあるため、その関連するコンテキストを使用してリストを取得する必要があります。BL は適切な BC をどのように選択する必要がありますか?

さらに、UI レイヤーがデータ レイヤーと対話することは望ましくありません。

これはどのように行うことができますか?

4

1 に答える 1

6

ビジネス レイヤーとは、すべてのビジネス ルールが定義されている場所を意味する場合、それは境界付けられたコンテキストです。

境界付けられたコンテキストは、ビジネス ルールを区分化された方法で実装できるように、特定の角度からシステムを調べます (小さなチャンクに分割することで全体的な問題を処理しやすくすることを目的としています)。

http://martinfowler.com/bliki/BoundedContext.html

fowler - 境界付けられたコンテキスト

フロントエンド

したがって、ASP MVC フロント エンドがあると仮定すると、このコントローラーは、標準の既知のインターフェイスを介して呼び出されるドメインから提示されるユース ケース/ユーザー ストーリーを呼び出すものです。

public class UserController : Controller
{
    ICommandHandler<ChangeNameCommand> handler;

    public UserController(ICommandHandler<ChangeNameCommand> handler)
    {
        this.handler = handler;
    }

    public ActionResult ChangeUserName(string id, string name)
    {
        try
        {
            var command = new ChangeNameCommand(id,name);
            var data = handler.handle(command);
        }
        catch(Exception e)
        {
            // add error logging and display info
            ViewBag.Error = e.Message;
        }

        // everything went OK, let the user know
        return View("Index");
    }
}

ドメイン申請(ユースケース)

次に、ユース ケースを実装するドメイン アプリケーション エントリ ポイントがあります (これは、コマンドまたはクエリ ハンドラーになります)。

これを直接呼び出して、フロント エンド アプリケーションでコードをインプロセスで実行することも、ドメイン アプリケーション サービスを提示する前に WebAPI または WCF サービスを配置することもできます。システムがどのように信頼されていないかは、システム要件によって異なります (インフラストラクチャの観点からは、必要がない場合は配布しない方が簡単な場合がよくあります)。

次に、ドメイン アプリケーション レイヤーがユーザー ストーリーを調整します。つまり、リポジトリを新しく作成し、エンティティを取得し、それらに対して操作を実行してから、リポジトリに書き戻します。ここでのコードは、複雑なものやロジックを含むものであってはなりません。

public class NewUserHandler : ICommandHandler<ChangeNameCommand>
{
    private readonly IRepository repository;

    public NewUserHandler(IRepository repository)
    {
        this.repository = repository;
    }

    public void Handle(ChangeUserName command)
    {
        var userId = new UserId(command.UserId);
        var user = this.repository.GetById<User>(userId);
        user.ChangeName(command.NewName);
        this.repository.Save(newUser);
    }
}

ドメイン モデル

エンティティ自体は、ドメイン モデルに独自のビジネス ロジックを実装します。また、個々のエンティティ内に自然に収まらないロジック用のドメイン サービスがある場合もあります。

public class User
{
    protected string Name;
    protected DateTime NameLastChangedOn;

    public ChangeName(string newName)
    {
        // not the best of business rules, just an example...
        if((DateTime.UtcNow - NameLastChangedOn).Days < 30)
        {
            throw new DomainException("Cannot change name more than once every 30 days");
        }

        this.Name = newName;
        this.NameLastChangedOn = DateTime.UtcNow;
    }
}

インフラストラクチャー

バッキング ストアからエンティティをフェッチおよび取得するためのコードを実装するインフラストラクチャが必要です。あなたにとって、これは Entity Framework と DbContext です (上記のコード例は EF を使用していませんが、代わりに使用できます)。

あなたの質問への回答 - フロント エンド アプリケーションはどの境界付きコンテキストを呼び出す必要がありますか?

答えを複雑にしたり長くしたりすることはありませんが、背景を設定するために上記のコードを含めました。使用している用語が少し混乱していると思うので、理解しやすくすることを願っています。

上記のコードでは、より多くのコマンドおよびクエリ ハンドラーの実装を開始したため、フロント エンド アプリケーションからどの境界付きコンテキストが呼び出されるかは、ユーザーが実行したい特定のユーザー ストーリーによって異なります。

ユーザー ストーリーは通常、さまざまな境界付けられたコンテキストにわたってクラスター化されるため、必要な機能を実装する境界付けられたコンテキストのコマンドまたはクエリを選択するだけで済みます。それ以上に複雑にする必要はありません。

解決しようとしている問題によってマッピングが決まります。解決しようとしている問題への洞察が向上するにつれて、このマッピングが変わる可能性があることを恐れないでください。

サイドノート

私が便利だと思ったことを言及する補足として (私は EF で DDD の旅を始めました)... エンティティ フレームワークには、エンティティ間のマッピング関係やナビゲーション プロパティの定義、カスケード削除で何が起こるかなど、しばしば必要とされる ORM の概念があります。更新します。私にとって、これは、エンティティの設計方法を決定する問題ではなく、エンティティの設計方法に影響を与え始めました。これは興味深いかもしれません: http://mehdi.me/ambient-dbcontext-in-ef6/

また、http: //geteventstore.comと、ORM マッピングの頭痛の種を取り除くイベント ソーシングを確認することもできます(ただし、複雑さが増し、許容できるパフォーマンスを得るために必要な回避策が必要になります)。どちらを使用するのが最適かは状況によって異なりますが、すべてのオプションを知っておくことは常に良いことです。

また、SimpleInjector を使用してクラスを接続し、MVC コントローラーに (ビルド済みのコマンドまたはクエリ ハンドラーとして) 挿入します。詳細については、https ://cuttingedge.it/blogs/steven/pivot/entry.php?id= 91 .

IoC コンテナーの使用は個人的な好みであり、決まったものではありません。

この本も素晴らしいです: https://vaughnvernon.co/?page_id=168

私は EF で DDD の旅を始めたので、上記のことを言及し、あなたが持っていたのとまったく同じ質問をしました。

于 2015-02-19T00:31:34.263 に答える