2

一般にアクセス可能な Web サイトを作成する際に、ドメイン駆動設計を使用しようとしています。私が抱えている問題の 1 つは、モデルの集約ルートがどうあるべきかを理解しようとすることです。私は、どのオブジェクトがエンティティ オブジェクトで、どのオブジェクトが値オブジェクトであるかについてかなり良い考えを持っています。

私のサイトは、ほとんどの公開サイトと同様に、すべてのユーザーがサイトに保存されているすべての情報を閲覧できるわけではありません。代わりに、自分が所有する情報しか見ることができません。私のサイトの場合、ユーザーは他のユーザーと共有できる「プロジェクト」を作成します。それでも、ユーザーは自分が作成したプロジェクトまたは参加を招待されたプロジェクトの情報しか見ることができません。私のモデルの他のすべてのオブジェクトはプロジェクト内に存在し、プロジェクトが削除された場合、それに含まれるすべてのオブジェクトも削除する必要があります。

これは、1 つのメインの「Project」集約ルート タイプと 1 つの「ProjectRepository」リポジトリを用意する必要があるということですか? サイトのページがリクエストされるたびにプロジェクト全体をロードするのは効率が悪いように思えます。実際には、要求されたプロジェクト内のアイテムのみを遅延ロードする NHibernate を使用しているため、これはそれほど問題ではありません。それでも、サイトの効率が遅延読み込みを伴う ORM の使用に大きく依存するようにするのは、悪い設計のように思えます。


これが、私の質問をより明確にすることを願っている更新です。

まず、プロジェクト タイプがモデルの集約ルートであるべきかどうかを理解しようとしています。プロジェクトは単独で存在できますが、レポートはプロジェクト内に存在する必要があります。プロジェクトが削除された場合、対応するレポートを削除する必要があります。これは、Project が集約ルートになる可能性がある、または集約ルートになる必要があることを意味しますか? これはよくわかりません。

プロジェクトが集約ルートの場合、レポートは正しくないはずですか? 私が理解しているように、ルートは DDD にネストされるべきではありません。さらに、リポジトリから取得できるのは集約ルートのみです。したがって、Report が集約ルートでない場合は、ReportsRepository を持つべきではなく、ProjectsRepository から取得したプロジェクトを介してのみ Report にアクセスする必要があります。そのため、ページが 1 つのレポートからのデータのみを必要とする場合でも、レポートを取得するには ProjectRepository からプロジェクト全体を読み込む必要があります。

さらに、プロジェクトがレポートを含む集約ルートである場合、ProjectRepository からプロジェクトを削除すると、含まれるレポートを削除するように設定することもできます。それでも、プロジェクトとレポートの両方が集約ルートである場合、プロジェクトが削除されたときに ProjectRepository がレポートを削除できないようにすると、集約間の境界が壊れますか? 集約ルートとそれに対応するリポジトリは、互いに独立して動作するはずではありませんか?

4

1 に答える 1

1

あなたは懸念を混乱させていると思います。セキュリティ (誰が何を表示できるか) はドメインの問題ではありません。ドメインを汚染させないでください。ユーザーがプロジェクト内でレポートを表示できない場合は、ドメイン モデル以外の場所でそれを強制します。

さらに、ViewModel (読み取りに使用される) をドメイン モデル (主に書き込みに使用される) から分離することでメリットが得られると思います。どちらもデータ モデルを共有していますが (同じ DB スキーマから読み取っているため)、実際には異なる目的を持っています。

実際には (.NET で)、ViewModel を分離すると、次の特性のほとんどまたはすべてが得られます。

  • ASP.NET MVC ビューは、画面上のすべてのデータを表す単一のクラスにバインドされます。たとえば、要素で現在選択されている値だけでなく、要素で可能なすべての値を<select>表すプロパティです。<option><select>

これらは MyProject.ViewModel 名前空間にあります。

public class ProjectLead // Note that this class is specifically designed for display.  This is not the domain object.
{
    public Guid Id;
    public string Name;
}

public class ProjectViewModel
{
    public Guid ProjectLeadId;
    public IEnumerable<ProjectLead> ProjectLeads;
}

コントローラーEdit()アクションは次のように呼び出します。

new ProjectViewModelRepository.Load(id);

ProjectViewModelRepositoryデータ モデル (nHibernate クラスまたは ADO.NET データ行など) をProjectViewModelインスタンスにマップします。

次に、UI でフォームを送信することによって呼び出されるコントローラー アクションは次のようになります。

    public ActionResult Edit(ProjectViewModel viewModel)
    {
        var repo = new ProjectRepository();
        var project = repo.Load(viewModel.Id);
        // Map the properties of the viewmodel to properties/methods of the Project domain class
        repo.Save(project);
    }

ここでの大きなアイデアは、単一責任の原則です。 ProjectViewModelプロジェクトが画面にどのように表示されるかを表します。ドメイン クラスは、ビジネス ロジックと、そのProjectデータが画面にどのように表示されるかに関係なく、プロジェクトに関連付けられているものを表します。

これらを分離することで、ドメイン クラスを複数の目的 (永続性、ドメイン ロジック、表示) に使用していたため、多くの問題が解決されました。しかし...これがすべて完全にやり過ぎのように聞こえる場合は、ドメインが本当にDDDを保証するのに十分複雑であるかどうかを確認します.

于 2011-06-20T19:49:04.973 に答える