3

我正在练习领域驱动设计,那么为什么不构建一个演示产品目录项目呢?显然Product这里是核心域,但由于我想让项目更有趣,我很想支持嵌套Category层次结构。换句话说, aCategory可以有多个 child Category

此外,我想与域分离CategoryProduct使其成为自己的支持域。

问题:标记Category为 AggregateRoot 对我来说听起来不对。ACategory可以有很多孩子Category,这也是 AggregateRoots?!!我该如何进行建模?嵌套产品类别在电子商务现实生活中非常普遍。


命名空间DL.Demo.Domain.Shared

public abstract class ValueObjectBase<T> : IEquatable<T> 
    where T : ValueObjectBase<T>
{
    public abstract bool Equals(T other);
    public abstract override bool Equals(object obj);
    public abstract override int GetHashCode();
}

public abstract class EntityBase : IEquatable<EntityBase>
{
    public Guid Id { get; private set; }

    protected EntityBase()
    {
        this.Id = Guid.NewGuid();
    }

    // Some Object overrides
}

而且我实际上有AggregateRoot内在的东西,Entity因为我猜只有一个Entity可能是一个AggregateRoot

public abstract class AggregateRoot : EntityBase
{
}

命名空间DL.Demo.Domain.Catalog

public class Category : AggregateRoot
{
    public string Name { get; private set; }
    public Guid? ParentCategoryId { get; private set; }
    public CategoryStatus CategoryStatus { get; private set; }
}

拥有 AggregateRoot 的嵌套列表对我来说听起来不合适。如果您不将 标记Category为 AggregateRoot,您将如何对其进行建模?

我是 DDD 和所有其他相关的很酷的东西,如领域事件、事件溯源等的新手。如果有经验的人能告诉我我是否走对了路,我将不胜感激。

4

3 回答 3

1

定义聚合的关键是首先定义事务边界。聚合边界之外的一致性是最终的——通过对聚合发出的域事件做出反应来实现。

聚合可以持有另一个聚合 ID(值对象)作为参考,但是不负责与另一个聚合在事务上保持一致。

所以,主要问题 - 你的树在事务上是一致的吗?如果是,则链表将无法很好地扩展。您必须以不同的方式对其进行建模。

建模是特定于上下文的,不是千篇一律的练习。也许您的类别只是一个可以建模为路径的值对象。没有更广泛的背景很难说。

于 2017-03-02T08:29:47.093 回答
1

我是 DDD 和所有其他相关的很酷的东西,如领域事件、事件溯源等的新手。如果有经验的人能告诉我我是否走对了路,我将不胜感激。

你走对了。

Category应该是一个Aggregate root,通过它的 ID 引用父类别,这非常好。

嵌套类别是事件溯源的良好候选者,即使没有特殊的不变量需要保护,因为此层次结构可以在Read models. Aggregate尽管这是直截了当的,但您在该表示上不受任何限制。在每次使用中Read model,您都可以以不同的方式实现它们:

  1. 具有父引用的模型树结构
  2. 具有子引用的模型树结构
  3. 具有祖先数组的模型树结构
  4. 具有物化路径的模型树结构
  5. 具有嵌套集的模型树结构

在此处查看有关实现树结构的更多信息(此链接指向 MongoDB,但不相关)。

只是发出简单的Category Aggregate事件ACategoryWasCreatedACategoryHasMovedToOtherParent等等,并且Read models只是适应以反映这些事件。

我已经实现了这样的树结构,并且读取端(查询端)的查询非常快。您可以选择一个类别中的产品以及没有连接的所有子类别。或者,您可以再次构建一个没有连接的类别路径。

于 2017-03-02T07:17:23.657 回答
0

如果您想要一个类别树,那么树本身可能应该是您的聚合根(我看到您已经在评论中自己得出了这个结论)。这将具有添加或删除子代等功能。

是的,对于非常大的树,您可能会获得很多性能,例如以 json 格式(存储在 MongoDb、缓存、文件或其他格式)中的树的只读投影。特别是考虑到这样的类别树通常只更新它的读取频率的一小部分,您也可以轻松地始终只维护该 json 并完全放弃规范化的数据库表树。

于 2017-03-03T22:15:29.800 回答