领域驱动设计的思考

零散记录,随想随记,在适当的时候再做整合:

问题一:对于数据或输入参数的校验应该放到应用层还是领域层?

在编写程序时,少不了对输入参数的校验。

第一可以减少异常场景,另外也可以节省不必要的执行逻辑,从这个角度讲参数的校验应该尽量靠前,如果参数是异常的话,应该尽早返回给调用方,所以放在应用层的最前端比较合适。

但如果把参数合法性理解成为领域对象的行为,也就是说领域对象是最了解输入参数校验规则的,那么就应该把参数校验逻辑放在领域层。并且,对于调用领域对象的调用方来说,这样是安全可靠的,同时也减少了重复校验的可能性。

结论:不是原则性问题,可以通过定于规范来统一行为,但是一定要有地方定义参数的校验逻辑,无论是在接口文档,还是在领域对象的注释中,并且保证这是唯一定义参数校验逻辑的地方。

问题二:对于事务的控制应该放在哪里?

比较重要,核心的问题。事务的定义:是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。

有几条原则:1. 聚合根首先是原子的,即聚合根内部的操作是原子的;

结论:目前看,事务应该放在应用层来做,由应用层来统一规划事务的范围,毕竟事务的范围是由业务最终决定的。

问题三:领域边界如何界定?

之前一直在纠结一个问题:两个系统交互时,可能会用到同样的对象,例如A系统调用B系统获取User信息,A和B系统都需要定义User的数据结构,那么这个User的数据结构是分别由A和B分别维护,还是在一个Common包中维护?

如果由A和B分别维护,则当User发生变化时,A和B要协调同步修改,这里可能存在没有同步的问题;如果在Common包中维护,而A和B对User的定义有可能不完全一样,所以还需要在A和B中分别再创建UserA和UserB,以区分两者的不同,产生了冗余。

结论:需要结合具体场景来使用。如果把User单纯定义为传输结构的定义而不具备领域含义(即将其定义为应用层概念),那么在Common包中定义比较合适。但如果为了精简结构,User不仅作为传输结构,同时也包含领域意义(那么A和B对User的定义需要在各自的领域范围内赋能,其结构有相似但含义完全不同,比如A中是User,B中可能是Customer),那么就一定要由A和B分别定义了。




猜你喜欢

转载自blog.csdn.net/asb_snail/article/details/80421618