WHAT?
DDD 是一种处理高度复杂领域的设计思想,它试图分离技术实现的复杂性,并围绕业务概 念构建领域模型来控制业务的复杂性,以解决软件难以理解,难以演进的问题。DDD 不是 架构,而是一种架构设计方法论,它通过边界划分将复杂业务领域简单化,帮我们设计出清 晰的领域和应用边界,可以很容易地实现架构演进。
注: 虽然是汉语, 但是我看不懂
WHY?
- 服务怎么拆? 服务拆多小?
- 这个功能放到哪个服务里?
- 这次需要要不要新开个服务?
DDD中的概念
通用语言
通用语言是团队统一的语言,不管你在团队中承担什么角色,在同一个领域的软件生命周期里都使用统一的语言进行交流。
e.g.
- 产品叫
上架
, 开发人员叫更新商品状态
- 阿柯叫
删除货号
, 我和珍珍叫货号审核关闭
通用语言可以是术语, 也可以是用例场景, 并且能够直接写在代码中.
e.g.
/**
* 透明通道图片
*/
private ImageDTO alphaChanelImage;
/**
* 确保主力没有删除后再保存
* 创建 -> 提审 -> 拒绝 -> 删除 -> 提审
*/
protected void ensureNotDeleteThenSave(String mspuNo) {
.....
}
/**
* 批量上架商品
*/
public void shelveGoodsBatch(List<String> gidList) {
.....
}
限界上下文
通用语言都有它的业务边界, 超出了边界理解上就会出现问题。
e.g.
GoodsCenter的商品与TradeCenter 的商品都叫商品, 但是他们有不同的属性, 不同的行为, 不同的弹性边界, 提供不同的业务价值.
实体
一系列属性与行为(除了Getter、Setter以外的行为)的集合, 大多数情况与数据库表是一对一的关系, 有自己的唯一标识(id), 能够实现基本功能自治.
e.g.
public class Person {
private int id;
private int age;
private String name;
private Address address;
public void growing() {
age++;
}
}
值对象
一系列属性的集合, 需要依附于实体存在, 例如:
public class Address {
String province;
String city;
}
原则上是不可以修改的, 只能使用另一个对象去替换
person.address.city = "北京"
×
person.address = new Address("北京", "北京")
√
值对象嵌入实体方式
- 属性嵌入:
Person@{id=1, age=10, name="吴", province="北京", city="北京"}
- 序列化嵌入:
Person@{id=1, age=10, name="吴", address="{"province":"北京", "city":"北京"}"}
address 的值是 Json 序列化后的 String
持久化方式
根据业务不同可以选择以下两种持久化方式
范式持久化
person 一张表, address 一张表, address 表中有一个 person_id 的属性关联 person.id,
这种方式保留了业务含义, 但是增加了数据库复杂度.
反范式持久化
全部 address 属性都加到 person 表中, 可以field嵌入, 也可以序列化之后嵌入.
这种方式破坏了业务含义, 但是没有增加数据库复杂度.
聚合
领域模型中的实体和值对象就好比个体,而能让实体和值对象协同工作的组织就是聚合
个人理解比较像是项目中使用的 XXService
, 这里理解的不是很清晰, Mark下
聚合根
聚合根是一种特殊的实体, 可以理解为聚合根是聚合内实体与值对象的管理者
领域事件
一个领域事件将导致进一步的业务操作, 例如: 密码连续输入错误三次,导致锁定账户的操作
记得有次DDD分享时分享人说过, 领域事件就是该存到数据库中的事件
领域事件的发布通常使用MQ进行发布, 通知订阅者处理领域事件
HOW?
事件风暴
1. 确认需求愿景
用户故事: As a (Role), i want (Activity), so that (Business Value). 在完成用户故事确认之后会留下有效的用户故事, 以有效的用户故事来确定通用语言.
2.
DDD 和微服务的关注点
- DDD 主要关注:从业务领域视角划分领域边界,构建通用语言进行高效沟通,通过业务抽 象,建立领域模型,维持业务和代码的逻辑一致性。
- 微服务主要关注:运行时的进程间通信、容错和故障隔离,实现去中心化数据管理和去中心 化服务治理,关注微服务的独立开发、测试、构建和部署。
那为什么DDD适合微服务? DDD的过程会产出实体、值对象, 这些用来建立数据表. 还会产生限界上下文, 这个是微服务拆分的重要参考, “到底该拆多小? 这个功能该放在哪个服务?” 限界上下文会给你答案.
微服务可以怎么拆?
1.按照流程拆
商品的流程: 生产 -> 浏览/收藏 -> 下单 -> 发货 -> 确认收货/退款
每一个阶段提供的业务价值都是独立且无交集的
2.弹性边界
这个弹性边界与云原生的弹性边界概念相同, 一个应用内某个模块的请求量远高于其他模块, 这时候高请求量的模块可以拆出来做单独的运维, 单独给这个模块升级配置