在本系列的上一篇:Spring Boot项目模板文章中,其实我已经讲到了基于业务的分包,结合DDD的场
景,这里再简要讨论一下。所谓基于业务分包即通过软件所实现的业务功能进行模块化划分,而不是从
技术的角度划分(比如首先划分出 service 和 infrastruture 等包)。在DDD的战略设计中,我们关注于
从一个宏观的视角俯视整个软件系统,然后通过一定的原则对系统进行子域和限界上下文的划分。在战
术实践中,我们也通过类似的提纲挈领的方法进行整体的代码结构的规划,所采用的原则依然逃离不了
“内聚性”和“职责分离”等基本原则。此时,首先映入眼帘的便是软件的分包。
在DDD中,聚合根(下文会讲到)是主要业务逻辑的承载体,也是“内聚性”原则的典型代表,因此通常的做
法便是基于聚合根进行顶层包的划分。在示例电商项目中,有两个聚合根对象 Order 和 Product ,分别
创建 order 包和 product 包,然后在各自的顶层包下再根据代码结构的复杂程度划分子包,比如对于
product 包:
可以看到, ProductRepository 和 ProductController 等多数类都直接放在了 product 包下,而没
有单独分包;但是展现类 ProductSummaryRepresentation 却做了单独分包。这里的原则是:在所有
类已经被内聚在了 product 包下的情况下,如果代码结构足够的简单,那么没有必要再次进行子包的划
分, ProductRepository 和 ProductController 便是这种情况;而如果多个类需要做再次的内聚,那
么需要另行分包,比如通过REST API接口返回Product数据时,代码中涉及到了两个对象
ProductRepresentationService 和 ProductSummaryRepresentation ,这两个对象是紧密关联的,
因此将他们放在 representation 子包下。而对于更加复杂的Order,分包如下:
└── product
├── CreateProductCommand.java
├── Product.java
├── ProductApplicationService.java
├── ProductController.java
├── ProductId.java
├── ProductNotFoundException.java
├── ProductRepository.java
└── representation
├── ProductRepresentationService.java
└── ProductSummaryRepresentation.java
├── order
│ ├── OrderApplicationService.java
│ ├── OrderController.java
│ ├── OrderPaymentProxy.java
│ ├── OrderPaymentService.java
│ ├── OrderRepository.java
│ ├── command
│ │ ├── ChangeAddressDetailCommand.java
│ │ ├── CreateOrderCommand.java
│ │ ├── OrderItemCommand.java
│ │ ├── PayOrderCommand.java
│ │ └── UpdateProductCountCommand.java
│ ├── exception
│ │ ├── OrderCannotBeModifiedException.java
│ │ ├── OrderNotFoundException.java
│ │ ├── PaidPriceNotSameWithOrderPriceException.java
│ │ └── ProductNotInOrderException.java
│ ├── model
│ │ ├── Order.java