模块
模块(Module)是指提供特定功能的相对独立的单元。提到模块,你肯定就会想到模块化设计思想,也就是功能的分解和组合。
在DDD中,模块的用途也是如此,通过分解领域模型为不同的模块,以降低领域模型的复杂性,提高领域模型的可读性。
模块设计的原则
模块的设计是基于领域模型的,要符合通用语言的表述。其次,模块的设计要符合高内聚低耦合的设计思想。
1. 根据领域来组织模块
模块应该由领域的概念来组织,而不是根据通用的组件类型和模式来创建模块。如果将所有的聚合、服务、工厂分别放在独立的模块中,就会有悖于DDD的设计原则,同时还会限制我们创建富有行为的领域模型。这样设计的模块的关注点是在当前的组件和模式上,而不是在领域上。每个模块都应该有适当的类来建模领域的特定方面的概念和功能。
2. 基于通用语言
项目中的通用语言除了用来指导实体,值对象、领域服务和领域事件的的命名外,也适用于模块的命名。使用通用语言来为模块命名,可以清晰的反映领域中的概念,且能够明确模块职责。例如,领域中身份认证的概念,我们就可以以Identity
来命名这个模块。
推荐的模块命名规范是:公司名称.项目名称.限界上下文.架构分层.组件类型。 比如:
com.xtoon.boot.sys.domain.service
com.xtoon.boot.sys.domain.specification
com.xtoon.boot.sys.application.impl
com.xtoon.boot.sys.infrastructure.persistence.repository
说到这里,你可能会想到mvc的项目结构也是基于模块的思想,比如Models、Views、Controllers、css、js都是放在独立的文件夹中,这其实也是关注点分离的思想,通过模块的分割来达到关注点分离。
3. 高内聚低耦合
高内聚低耦合是模块设计的重要思想,模块内高内聚,模块间低耦合。 一个完整的系统,模块与模块之间,尽可能的使其独立存在。也就是说,让每个模块,尽可能的独立完成某个特定的子功能。模块与模块之间的接口,尽量的少而简单。如果某两个模块间的关系比较复杂的话,最好首先考虑进一步的模块划分,这样有利于修改和组合。
模块与子域和限界上下文的关系
不要将模块与子域和限界上下文混淆。在复杂的领域模型中,为了对领域模型中进行准确建模,需要将领域模型拆分成多个子域,每个子域对应一个或多个限界上下文。在限界上下文中,可以将限界上下文中具体的领域概念分解成不同的模块。所以,从子域到限界上下文再到模块,应该是依次包含关系。