为什么要用领域驱动设计DDD

领域驱动设计思想最早由Eric Evans出版的《领域驱动设计:软件核心复杂性应对之道》中提出。领域驱动设计的思路和我们平常接触的面向数据库和三层架构编程完全不同。因此学习领域驱动设计时,必须抛弃之前的固有编程思维。

1、为什么要使用领域驱动设计DDD?

1.1、什么是软件退化

从书名《领域驱动设计:软件核心复杂性应对之道》可以直观的看到领域驱动设计是要解决“复杂性”带来的问题。在我们碰到的实际场景中,复杂通常是由于“需求规模”不断扩张造成的。

当你入职一个初创公司,从头开发一款产品,由于需要快速上线验证,功能可以做的非常简单:下单,支付,减库存一气呵成。

1
2
3
4
5
6
7
8
9
10
public Class MallService{
public void buyProduct(){
//查询用户信息,商品信息,计算价格
int money = caculateMoney();
//付钱
payService.payMoney(money);
//减库存
stock.reduceNumber();
}
}

随着公司进一步发展,业务开始变得复杂。你的产品经理要求你支付的时候可以使用活动优惠。包括满减、满2送1、打折、第二件半件等等。采用传统的模式,你必须在这里加入大量的判断逻辑。这增加复杂性,降低了可维护性。此时软件开始退化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public Class MallService{
public void buyProduct(){
//查询用户信息,商品信息,计算价格
Order order = getOrderInfo();
int money = 99999999;
//判断活动信息
if(满减){
money = caculateMoney(满减,order);
}else if(打折){
money = caculateMoney(打折,order);
}else if(满21){
money = caculateMoney(满21,order);
}else if(第二件半件){
money = caculateMoney(第二件半件,order);
}
//付钱
payService.payMoney(money);
//减库存
stock.reduceNumber();
}
}

1.2 如何避免软件退化

如果要避免软件因为需求变更导致退化。我们必须升级软件的设计。质量好的代码需要满足两个要求:开放-封闭原则(OCP)。通俗的说就是代码需要有良好的扩展性,于此同时扩展新功能时不能影响老功能。如果说一项改动会导致很多级联改动,说明这段代码设计不太行。

拿上面的商城来说,如果加入“活动优惠”的新需求后,需要变更代码设计才能算得上是高质量的代码。于是我们需要新建Promotion接口,所有的优惠活动都需要实现此接口。具体算价格的时候直接调用实现类就好了。假设后期需要新增活动类型,我们只需要新增一个Promotion的实现类就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public Class MallService{
public void buyProduct(){
//查询用户信息,商品信息,计算价格
Order order = getOrderInfo();
int money = 99999999;
//查询可以用的活动
for(Promotion promotion : promotionList){
if(promotion.isAvaluable()){
money = caculateMoney(order);
break;
}
}
//付钱
payService.payMoney(money);
//减库存
stock.reduceNumber();
}
}

从上面例子可以看出,避免软件退化,需要不断的优化代码设计。但是现实情况很残酷,很少有人会因为需求的增加而改动代码设计,或者使用设计模式来优化代码。

1.3 避免软件退化更好的方式

难道就没有更好的办法避免软件退化吗?办法是有的,他就是领域驱动设计,他能保证你在不断多变的需求下一直让代码处于最佳设计状态。
领域驱动设计一直强调的是对真实世界的建模。使用建模来指导程序设计,而不是基于数据库设计来做程序设计。这个是和我们目前传统编码方案的最大区别。

2、领域驱动设计DDD缺点是什么?

  • 领域驱动设计不能解决复杂的查询问题,领域驱动只应用于“增删改”。
  • 充血模型需要具备更强的设计与协作能力,对人的要求更高!

Boss:卡尔辞职了,他是唯一一个知道维护老代码的人;这应该不难,搞定他;工程师:我擦!