ORM是不适合DDD的!鲍勃大叔表示同意


鲍勃大叔推荐的Mark Seemann一文:昨天我拜访了一个客户讨论软件架构,包括DDD和ORM。今天我偶然发现了我在2014年写的东西。它仍然反映了我今天的想法。

关于使用ORM进行DDD的合适性?我不同意。ORM可能看起来很强大,但事实上,它们非常有限。似乎解决了一个问题,但创造了更多的问题。

DDD蓝皮书中描述的最重要的战术模式之一是聚合根的概念。我见过的所有ORM都公然违反了这种模式,因为你可以从任何指定的表开始并加载该表的行,然后沿着各种“导航属性”来加载来自关联表的数据。这意味着没有根,因此没有明确的数据所有权。

这样的坏处使得一切都是可变的,你很快就会有很难推理一个系统(banq注:没有逻辑推理的软件系统,无法让人看懂,是没有逻辑思维的人胡乱搪塞!)。

(其实,Spring  Boot的Spring Data JPA适合DDD!因为它有一个聚合根!)
 众说纷纭:
我从来没有理解为什么人们着迷于构建不必要的和不自然的等级。世界不是这样的,所以要学会处理它。许多纵横交错的等级制度是可能的,没有一个是对的或错的。

任何模型都是不现实的。唯一准确的地图就是现实本身。好的模型做出了不切实际的假设,在实践中运作良好。我从未发现ORM在实践中运作良好。

这就是我们称之为模型的原因。但是“对象”和“关系表”也经常隐藏或混淆自然(逻辑)语义,并且在演变中更加不稳定(这些之间的映射必然充满)。基于事实的模型不会增加这些额外的问题。

对于那些努力定义聚合根的人,我发现以下内容很有帮助:从关系找聚合根:如果各种关系定义为一种组合或连接,那么那个不被其他实体组合的就是AR(聚合根)!(banq注:•聚合根= 数据表实体 + 数据表关系!)

我不确定我理解这个定义......我认为Aggregate Root是一棵树。根据模式,您必须只读取和写入根,它将随所有分支和叶子一起提供。你绝不能以任何其他方式读写分支和叶子。

如果我们绘制模型的类图,我们就有组合关系(当父类死亡,子类也死亡)。如果一个实体永远不是子类,那么它就是一个AR。不知道是否有更好的解释。

它只是一个封装聚合的Facade,它只是围绕着许多对象一起工作的边界 - 一个比一个类更大的组织单元:决定了AR将是什么,它是你设计的一个特色。

我最初的想法是通过存储库模式约束ORM。例如,对于Entity Framework,仅允许访问扩展聚合基类型的对象。

当然,这也要求表示实体的类的设计遵循聚合边界。定向约束关联仅限于概念上包含在聚合中的实体。

小心DDD。它经常导致功能分解。

如果你有A,B和C,A后面跟着B,B后跟着C,然后你会创建A,B和C服务。你经常会得到一个膨胀的客户端或上帝对象。DDD可以导致这种情况。

导航属性和延迟加载:使用预先加载/显式加载

您可以删除导航属性并仅映射fk。但是RDBMS是这里的问题,在db级别,每个表都是顶级实体。文档数据库更适合聚合根定义IMO

我曾经和一个客户讨论过这个问题,他们认为他们能够“遍历”整个域模型真是太好了。懒装载无处不在,没有限制.....

这一切都很有趣和游戏,直到生成的所有查询都搞垮了服务器和数据库。

与“SRP单一责任”相反的是“ORM”;)

业务规则/不变量就是一个动机。在根中,您可以强制执行跨越属于AR的多个实体的规则。例如,具有与购物车中的商品相关的规则的购物车,例如折扣。该逻辑适合购物车实体,而非物品实体。