Domain driven design 聚合根数据重复和Demeter定律

Domain driven design 聚合根数据重复和Demeter定律,domain-driven-design,cqrs,aggregateroot,law-of-demeter,Domain Driven Design,Cqrs,Aggregateroot,Law Of Demeter,得墨忒尔定律是一条规则,规定一个物体只应意识到“密切相关”的其他物体(我的解释)。看 以下示例不遵循LoD: // This class has to be aware of too many other classes, increasing complexity. class Thing { void foo(Customer c, Employee e, System s, Company c, SupportTicket st) { // Th } }

得墨忒尔定律是一条规则,规定一个物体只应意识到“密切相关”的其他物体(我的解释)。看

以下示例不遵循LoD:

// This class has to be aware of too many other classes, increasing complexity.
class Thing {
    void foo(Customer c, Employee e, System s, Company c, SupportTicket st) {
        // Th
    }
}

// This function likewise has to be aware of too many other classes.
void foo(SupportTicket st) {
    st.employee().division().incrementResolutionCount();
}
我正在研究一个数据之间有很多复杂关系的系统。在SQL数据库中,使用四种不同的联接执行查询以获取所需的数据是很容易的。然而,在这样的场景中,您正在加载一个基于它实际上不包含的属性的聚合。如果存储库是内存集合的抽象(即,在最简单的用例中是数组的包装器),那么纯内存集合就不可能执行这样的查询,因为没有聚合可以匹配它

我想到的解决方案是在聚合之间复制数据,而不仅仅是在有界上下文()之间。这增加了对Demeter定律的遵从性,同时允许您根据自然“属于”相关聚合的属性查询聚合

是否建议采用这种方法

是否建议采用这种方法

不是我见过的任何权威

我想到的解决方案是在聚合之间复制数据

这对你的记录本意味着什么

域模型的动机是维护记录簿的完整性,确保它始终满足您的业务需求。聚合边界描述域内相互独立更新的不相交区域,也就是说,每个聚合对其自己的状态具有主权

因此,当您提出在两个聚合之间复制数据的设计时,您真正主张的是,记录簿中的一个事实实际上是两个不同的事实,它们可能相互独立地发展

这可能是愚蠢的,也可能是对业务的重要洞察。一般来说,争论是不可能的;你必须和你的领域专家坐下来好好讨论一下

然而,我认为,违反德米特定律但实际正确描述业务的领域模型远远优于满足德米特定律但对业务产生误导性描述的替代设计

这就是说,观察您的解决方案违反LoD是合理的,并在此基础上推回您的需求:与您的领域专家坐下来,探索普遍存在的语言,让每个人都了解业务是否真的那么复杂,以及是否应该如此复杂

我正在研究一个数据之间有很多复杂关系的系统。在SQL数据库中,使用四种不同的联接执行查询以获取所需的数据是很容易的。然而,在这样的场景中,您正在加载一个基于它实际上不包含的属性的聚合

为什么要加载聚合而不是它的标识符

等等,你是说

您正在加载基于实际不包含的属性的聚合

您试图使用违反Demeter法则的查询来加载聚合?是的,有人被打破了

CQRS模式在这里可能很有用,可以作为一种工具来帮助解开真正发生的事情。一些即时猜测

1) 如果不尝试修改状态,则不需要聚合。聚合用于对写入强制执行业务约束。如果您的用例正在读取,那么您需要状态的只读表示——也就是投影

2) 如果您试图修改状态,那么您正在处理一个命令,并且命令消息将寻址一个特定的处理程序。很难想象有这样一个用例,您将向聚合发送命令,而不能够识别该聚合

另一种可能性是,您正在考虑的命令实际上是一个事件,具有订阅服务器。通常,订阅服务器不是域模型中的聚合,而是通过向聚合发送命令来对事件作出反应的流程管理器

3) 仍然有可能您在错误的位置绘制了聚合边界