您现在的位置是:首页 >技术杂谈 >设计模式:DDD领域驱动设计网站首页技术杂谈
设计模式:DDD领域驱动设计
领域
Domain-driven design
DDD 强调是说得先把 “领域” 中涉及到的数据、流程、规则等都弄明白了,然后以面向对象的观点为其建立一个模型(即领域模型),而这个模型,决定了你将用什么技术、什么架构、什么平台来实现这个系统。所以技术在这个过程中是 “被动的”,是被 “选来” 实现 “领域模型” 的。对于项目的成败,技术不是决定性因素,领域模型是否符合事物的本质才是关键。
可以看出,领域驱动设计的出发点是业务导向,技术服务于业务。
实体
比如商品是商品上下文的一个实体,通过唯一的商品 ID 来标识,不管这个商品的数据如何变化,商品的 ID 一直保持不变,它始终是同一个商品。
值对象
实体是看得到、摸得着的实实在在的业务对象,实体具有业务属性、业务行为和业务逻辑。而值对象只是若干个属性的集合,只有数据初始化操作和有限的不涉及修改数据的行为,基本不包含业务逻辑。值对象的属性集虽然在物理上独立出来了,但在逻辑上它仍然是实体属性的一部分,用于描述实体的特征。在值对象中也有部分共享的标准类型的值对象,它们有自己的限界上下文,有自己的持久化对象,可以建立共享的数据类微服务,比如数据字典。
比如将用户的住址就设计为了值对象——住址是用户的属性的一部分,它包含国家、省份、城市、区、街道等。
聚合/聚合根
如果把聚合比作组织,那聚合根就是这个组织的负责人。
聚合根也称为根实体,它不仅是实体,还是聚合的管理者。
一组相关对象的集合,作为一个整体被外界访问。聚合根的 ID 全局唯一
关系
通过聚合根来引用实体,挂载值对象,对外屏蔽内部的实体逻辑
//聚合根
class Order {
public String id;//订单ID,全局唯一
public Address customerAddress;//配送地址
public List<Item> items;//商品信息
public Pay pay;//支付信息
public LogisticsDetail logisticsDetail;//物流信息
public Pingjia pingjia;//评价信息
}
//实体
class Item {
public Long id; //商品ID,实体主键,Order内唯一
public String name;//商品名
public float price;//价格
public int count;//数量
}
//实体
class Pay {
public Long id; //支付ID,实体主键,Pay内唯一
public String source;//支付方式
public int currency;//币种
public float total;//价格
}
//实体
class LogisticsDetail {
public Long id; //物流ID,实体主键,LogisticsDetail内唯一
public int cpCode;//物流公司
public String mailNo;//物流单
public float status;//当前状态
}
//实体
class Pingjia {
public Long id; //评价ID,实体主键,Pingjia内唯一
public String desc;//描述
public byte[] image;//图片
}
//值对象
class Address{
public String province;//省
public String city;//市
public String county;//区
}
四色建模法
四色
1、时标原型(Moment-Interval Archetype,简称MI)
表示事物在某个时刻或某一段时间内发生的,如销售订单、客户账单、收款记录等,使用浅红色表示。
2、PPT原型(Part-Place-Thing Archetype,人/事/物原型,简称PPT)
表示参与扮演不同角色的人或事物,如商品、账户、店铺等,使用浅绿色表示。
3、角色原型(Role Archetype,简称ROLE)
抽象了一种参与方式,由人或组织机构、地点或物品来承担,如客户、商家、仓储团队、财务组织等,使用浅黄色表示。
4、描述原型(Description Archetype,简称DESC)
属于资料类型的资源、目录式的种类性质对象,或者可以被其他原型反复使用的,如商品类目、支付方式、方法值对象等,使用浅蓝色表示。
步骤
接下来,咱们使用四色建模法来分析领域模型,总共分为四大步:
建立时标原型:寻找需要追溯的事件,根据追溯事件寻找足迹。
建立PPT原型:丰富模型,寻找时标原型周围的人/事/物,使它可以更好地描述业务概念。
建立角色原型:进一步从中抽象出可以参与到不同流程中去的角色。
建立描述原型:把一些信息用描述对象补足。
示例
电商DDD的四色图案例
财务领域模型和支付中心模型的一部分
细节
- 粉红色指的是时标原型,是核心业务产生的数据,基本上对应表设计。
- 模型属性不需要体现表的审计字段,比如通用的ID、创建者、修改时间、软删除标识等,模型行为也只需要设计核心行为即可,那种约定俗成的- CRUD方法就不需要写出来了,设计要懂得取舍。
- BC内模型除了依赖、聚合等等连线,可使用箭头连接模型之间的核心交互,跨BC之间的模型使用虚线箭头连接,这里我是结合了DCI建模法(D表示数据,C表示上下文、场景,I表示模型间的交互)。
- 对于表示业务唯一的属性,我使用了加粗展示,再也不用跟别人费劲去解析这些模型是用什么维度去建的了
- 对于还没上线的属性变动(新增/修改),使用红色标记,因为领域模型图是指导我们业务开发的。
- 限界上下文的划分是一种非常主观的边界划分,为了后续代码能够灵活调整,在Controller的URL设计里不需要加上限界上下文。
落地
最好由架构师给出设计方案,并给出骨干实现,开发人员有了可类比的代码,就能够比较准确的去做功能开发。