0

2 か月前に、Scott Millet 著の「Professional ASP.NET Design Patterns」という本を購入しました。これは、デザイン パターンを使用して階層化された Web アプリケーションを構築する方法を学びたかったからです。この本のケーススタディを自分のアプリケーションで使用したので、すべてがセットアップされました。

私が抱えている問題は、集計ルートがわからないことです。

コレクションを作成できるユーザーがいます。ユーザーはコレクションにカテゴリを追加し、カテゴリにキーワードを追加できます。私のデータベースでは次のようになります。

- Users
    - PK: UserId

- Collections
    - PK: CollectionId
    - FK: UserId

- Categories
    - PK: CategoryId
    - FK: CollectionId

- Keywords
    - PK: KeywordId
    - FK: CategoryId

ユーザーをコレクションの集約ルートにするのは論理的ではありませんが、カテゴリとキーワードが一緒になってコレクションを形成します。そのため、ユーザーをまだ子を持たない集約ルートにし、コレクションを集約ルートにしました。1 つのコレクションに複数のカテゴリを含めることができ、カテゴリに複数のキーワードを含めることができます。したがって、カテゴリを追加する場合は、次のようにします。

public void CreateCategory(CreateCategoryRequest request)
    {
        Collection collection = _collectionRepository.FindCollection(request.IdentityToken, request.CollectionName);

        Category category = new Category { Collection = collection, CategoryName = request.CategoryName };

        ThrowExceptionIfCategoryIsInvalid(category);

        collection.AddCategory(category);

        _collectionRepository.Add(collection);
        _uow.Commit();
    }

これは問題なく動作しますが、キーワードを追加する場合は、まずコレクションを取得し、次にキーワードを追加できるカテゴリを取得してからコレクションをコミットする必要があります。

public void CreateKeyword(CreateKeywordRequest request)
    {
        Collection collection = _collectionRepository.FindCollection(request.IdentityToken, request.CollectionName);

        Category category = collection.Categories.Where(c => c.CategoryName == request.CategoryName).FirstOrDefault();

        Keyword keyword = new Keyword { Category = category, KeywordName = request.KeywordName, Description = request.KeywordDescription };

        category.AddKeyword(keyword);

        _collectionRepository.Add(collection);
        _uow.Commit();
    }

そして、これは正しくないと感じます (そうですか?) どうして、カテゴリをキーワードの集約ルートにするべきだと思いましたか。しかし、別の疑問が生じます。最初のコード例で行ったように、カテゴリ集計を作成するコレクション集計があることはまだ有効ですか? 例: collection.Add(category);

4

2 に答える 2

1

集約ルートには確かにネストされた子を含めることができますが、それらの子が集約でもある場合は、集約がやりすぎている可能性があるという警告になる可能性があります。あなたの場合、私Collectionは集約でありCategory、そうではないと思います。それは単なるエンティティまたは集約に属する値オブジェクトでCollectionあり、たまたまKeyword値オブジェクトでもあるインスタンスが含まれています。

CreateCategoryサービスメソッドが次のようになるように実装を変更します。

public void CreateCategory(CreateCategoryRequest request)
{
        var collection = _collectionRepository.Get(request.IdentityToken, request.CollectionName);

        collection.AddCategory(request.CategoryName);

        _uow.Commit();
}

AddCategoryメソッドはCollection、インスタンスの作成Categoryとエラー チェックを担当します。これは集約ルートであり、そこに含まれるエンティティと値オブジェクトのクラスターを管理する責任があるため、理にかなっています。アンビエント作業単位が変更をコミットする必要があるため、リポジトリで Add メソッドを呼び出す必要はありません。

CreateKeyword私がより似ているように変更する方法:

public void CreateKeyword(CreateKeywordRequest request)
{
        var collection = _collectionRepository.Get(request.IdentityToken, request.CollectionName);

        collection.AddKeyword(request.CategoryName, request.KeywordName, request.KeywordDescription);

        _uow.Commit();
}

上のAddKeywordメソッドはCollection、適切なものを取得しCategoryてキーワードを追加し、必要に応じて例外をスローして、一貫性と有効性を強制します。

ご覧のとおり、これら 2 つのメソッドにはパターンがあります。最初にキーによって集計が取得され、次に集計のメソッドが呼び出され、最後にすべてがコミットされます。このようにして、集約は自身の状態をより詳細に制御できるようになり、ドメイン モデルの貧血を回避し、サービスに存在するコードの量を減らすことができます。

集合体設計の詳細については、Vaughn Vernon による「Effective Aggregate Design 」を参照してください。

于 2012-08-21T23:50:14.373 に答える
0

新しいキーワードを追加するには、コレクション参照から始めますが、代わりにカテゴリ参照から完全に始めることができるため、おそらく正しくないと思います。ユーザーがキーワードを追加するとき、彼は確かにカテゴリのコンテキストで追加するので、おそらくその時点でカテゴリがメモリにあります。

また、私はあなたの各メソッド_collectionRepository.Add(collection)の最後にを取得していません。Add[SomeSubEntity]()コレクションはすでにリポジトリに存在しているはずなので、保存するだけですよね?

ネストされたアグリゲートについては、少し複雑で、2つの別々のアグリゲート(カテゴリとコレクション)と比較した場合のメリットはあまりわかりません。

于 2012-08-21T11:51:10.843 に答える