Domain driven design 领域驱动设计在建模和编码之间的实现问题

Domain driven design 领域驱动设计在建模和编码之间的实现问题,domain-driven-design,Domain Driven Design,我现在正在努力学习DDD。经过几个月的研究,我发现建模和编码之间存在矛盾。如你所知,DDD的原则是“领域第一,技术第二”。但是,在将实际模型移动到实现中时存在“确定”约束,例如: 原始型号: 在域概念中,帖子与多个评论相关联,而评论是依赖于帖子的普通模型。将此转换为代码 class Post{ Integer postId; String title; String content; String writer; Collection<Commen

我现在正在努力学习DDD。经过几个月的研究,我发现建模和编码之间存在矛盾。如你所知,DDD的原则是“领域第一,技术第二”。但是,在将实际模型移动到实现中时存在“确定”约束,例如:

原始型号:

在域概念中,帖子与多个评论相关联,而评论是依赖于帖子的普通模型。将此转换为代码

class Post{
    Integer postId;
    String title;
    String content;
    String writer;
    Collection<Comment> comments;
}
class Comment{
    String content;
}
这个修改后的模型对我来说效果很好,我对解决方案很满意。但我觉得有些不一致。由于技术限制,该模型似乎正在扭曲。如果我们向领域专家展示第一个和第二个模型,并讨论图表,他或她将更好地理解第一个模型


我是否误解了DDD的概念?如果是的话,给我一些建议。谢谢。

领域驱动设计带来的思维方式变化之一是,随着您对领域理解的变化,您的领域将不断发展。不仅仅是这个领域会进化,你对它的理解和感知也会进化

在我看来,您现在遇到的是,通过从如何持久化的角度来看,试图在将一个或多个实体加载到聚合中的基础上使设计合理化。这种共同的父母和孩子关系感觉很自然,因为这是我们大多数人过去做事的方式。即使从DDD的角度来看,也很容易陷入“评论离不开帖子”的范式


这归结为这样一个事实:您是基于域内的数据而不是用例建模的。这样看吧。。。帖子不仅仅是评论的集合。相反,评论指的是特定的帖子。细微差别听起来很小,但却有着广泛的影响。当以这种方式建模时,它与您修改后的模型相匹配-而且它是完全和完全好的。你唯一需要改变的是你的心态,因为评论可以被视为一个整体,就像帖子一样。它们都将有另一个必须存在的用例,但同时,您需要看到,如果两者都作为同一用例的一部分受到影响(除了删除帖子之外),则不太可能执行某些操作

来说明,考虑这个用例:

作为一名作家,我希望能够编辑我文章的内容

你的新模型实际上有效地支持了这一点。您看到的不是关系,而是域的使用方式。您是否应该加载供作者编辑的注释?如果不知道你的领域,我仍然认为你不想这样做。有一些用例可能同时涉及帖子和评论,这也很好。由于在单个有界上下文中有两个聚合,因此您将能够支持完全基于帖子、完全基于评论或两者的组合的用例

在技术方面,您提到“数亿条评论”。我想你是指整个系统,而不是一个职位?假设您有一篇活跃的帖子,并且它在其生命周期中看到了20k条评论。对于正确设计和优化的数据库,这仍然不是问题。当它成为一个问题时,如果它真的成为一个问题,它可以通过对所使用的技术进行额外的改变来进一步解决,而不是改变领域。您可以查看缓存策略(在域之外,因为这是一个应用程序问题而不是域问题)、外部索引、最终一致性等

强烈建议阅读沃恩·弗农的“有效聚合设计”系列文章,如果您尚未:

此外,在我看来,他的优秀著作《实现领域驱动设计》是一本必读的书。埃文斯材料固然重要,但更像是理论概念;然而,弗农的材料谈到了如何将这些概念付诸实践,以及这些决定的含义是什么


作为附录,正如plalx在下面的评论中指出的那样。所有这些都不是对帖子和评论的概括,而是明确说明它们如何应用于您的领域,正如我们所描述的,以及从您的模型中可以推断出什么。帖子和评论对于其他人可能会有不同的行为,因为其他人会有不同的用例。即使在您自己的域中,如果帖子和/或评论存在于不同的上下文中,它们的行为也可能不同。最重要的是,尝试并确保添加到域模型中的所有内容(通常)都是由于特定的直接用例而添加的。简单地开始数据建模是很有诱惑力的,但是您将开始发现自己试图将用例强制到域模型中。领域建模不应该是一个有限的过程,也不应该是过程中的一个步骤。愿意并能够适应理解上的变化,或业务整体运营战略随时间变化的方式的变化。

领域驱动设计带来的心态变化之一是,您的领域将随着您对领域理解的变化而不断发展。不仅仅是这个领域会进化,你对它的理解和感知也会进化

在我看来,您现在遇到的是,通过从如何持久化的角度来看,试图在将一个或多个实体加载到聚合中的基础上使设计合理化。这种共同的父母和孩子关系感觉很自然,因为这是我们大多数人过去做事的方式。即使从DDD的角度来看,也很容易陷入“评论离不开帖子”的范式

Th
class Post{
    Integer postId;
    String title;
    String content;
    String writer;
}
class Comment{
    Integer postId;
    String content;
}