【问题标题】:Aggregate & Aggregate Roots聚合和聚合根
【发布时间】:2014-10-26 20:29:46
【问题描述】:

我目前正在尝试定义某些基类和接口以在 DDD 和 CQRS 项目中使用它们,但是我正在努力定义 聚合聚合根.

蓝皮书告诉我们...

  • 聚合对象的集群
  • 每个聚合都有一个聚合根
  • 聚合根是一个特定的实体,是应用程序其他部分可以引用的唯一对象。

为此,我制作了以下类/接口:

实体

public interface IEntity<TKey> {

    TKey Key { get; set; }

}

public abstract class EntityBase<TKey> : IEntity<TKey> {

    // key stuff, equality comparer..

}

聚合根

public interface IAggregateRoot<TKey> : IEntity<TKey>
{
}

存储库

public interface IRepository<TAggregate, TRoot, TKey>
    where TAggregate : IAggregate<TRoot>
    where TRoot : IAggregateRoot<TKey>
{

    TRoot Root { get; set; }

    void Add(TAggregate aggregate);

}

现在,我理解正确了吗?那么聚合界面会是什么样子呢?

public interface IAggregate<TRoot, TKey>
    where TRoot : IAggregateRoot<TKey>
{

}

我试图找到一些参考资料,并在 CQRS 框架中找到了以下实现:(CQRS 与 DDD 有很大不同吗?我认为在不应用事件溯源时几乎相同)

public abstract class Entity<TAggregateRoot> where TAggregateRoot
    : AggregateRoot
{

}

【问题讨论】:

  • 'CQRS 与 DDD 有很大不同吗?'。恕我直言,它们完全不同。

标签: c# design-patterns repository domain-driven-design cqrs


【解决方案1】:

聚合根只是一个实体,您无需显式定义整个聚合。聚合是对象(实体和值)的层次结构,可以通过聚合根来寻址。

因此,根据您对IEntityEntityBaseIAggregateRoot 的定义,我认为:

存储库

public interface IRepository<TAggregateRoot, TKey>
    where TAggregateRoot : IAggregateRoot<TKey>
{

    TAggregateRoot Get(TKey id);

    void Delete(TAggregateRoot aggregateRoot);

    void Add(TAggregateRoot aggregateRoot);

}

聚合根实体

public abstract class AggregateRootEntityBase<TKey>
: EntityBase<TKey>, IAggregateRoot<TKey>
{

}

IAggregate&lt;TRoot, TKey&gt;explicit TRootEntity&lt;TAggregateRoot&gt; 等构造不需要实现。

另外,请不要过度概括并保持简单。在大多数应用程序中,您只需为IAggregateRoot 实现一个非通用接口,为Entity 实现一个基类或接口

【讨论】:

  • 那么谁是聚合体? :D 让我们举个例子:您的域中有一个 User 实体和一个 Phone 实体。每个用户都有几个电话号码,因此它是 Phone 的集合。 User 实体现在是否包含带有 Phone 号码的普通列表?如果我使用存储库删除用户怎么办?假设我使用 NHibernate 作为我的 ORM。我在域中的哪个位置指定当用户被删除时,他的所有电话号码也会被删除?我可以在映射配置或数据库中声明它,但是它不再是域的一部分。
  • 在您的示例中,聚合是一组用户及其电话(实例)。聚合根是用户,电话是包含在聚合中的实体,因此除了用户实例之外不能在任何地方引用。是的,当然,删除用户实例,你必须删除它的电话。如何做到这一点是另一个问题。首先,您应该了解 ORM 定义的是数据模型,而不是域模型(但两个模型必须相同以避免模型分层)。数据模型中的所有操作都隐藏在 Db Repository 中。
  • 哇,我好像被 ORM 搞糊涂了,一直想知道 DDD 甚至可以如何使用,比如说 EF,因为 EF 要求对象具有公共 getter/setter,这对于某个域来说可能不正确。但现在一切都说得通了!
  • 是的,今天有点混乱,因为 PoEAA 的初始 DataMapper 模式必须进行从域到 SQL 的转换。但是今天的实现(ORM)通常不适合,因此我们不应该编写从类到 sql 的转换,而是从域模型到数据模型。如果你有兴趣,你可以看看 DataObjects.net,它希望看起来像业务层逻辑框架,它允许对数据和域使用单一模型(包括定义字段私有等的能力)。
  • @ValentinP。 “您应该了解 ORM 定义的是数据模型,而不是域模型(但两个模型必须相同以避免模型分层)” 这有点笼统的说法。 ORM 只是在对象模型(用 OO 代码表示)和关系模型(用 SQL 表示)之间进行映射。您是否应该在对象端创建一个额外的“数据模型”是有争议的。您能否详细说明为什么您认为这是必要的,因为正如您所说,域模型和数据模型必须相同?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多