DDD系列-战术设计
2022-11-16 23:54:36    67    0    0
weibo-007

什么是战术设计

按照上一回合,我们使用事件风暴的方式,把我们一个复杂领域的微服务划分方案解决了。但这个时候,如果要你写代码,那肯定不可能,因为这个东西距离代码实现还有很长的路。那我们如何落地代码实现,这就战术设计需要解决的问题。战术设计负责最后的落地阶段。

用界限上下文将用户故事连起来

我们用划分出来的界限上下文(不好理解的话可以理解成微服务)将用户故事连起来,这一步我们把限界上下文当成黑盒,确认它们之间是如何协作的,但是我们不关心限界上下文内部的情况

这里借用一下尤达老师自动售卖机的例子,围绕自动售卖机为例子梳理出来的限界上下文,自动售卖机系统的界限上下文如下:

然后我们借助架构师,PM,领域专家梳理的用户故事,用限界上下文交互的方式将整个用户故事串联起来。

我们这里只用到一个用户扫码在自助售卖机上扫码支付的例子来串联一下。注意,有的时候我们可以只针对业务的几个关键用户故事进行串联,串联的时候需要把真正的研发人员也召集到一起进行讨论了,因为这里距离研发已经很近了

 

值得一提的是,有的同学可能会问,这里为什么没有用户上下文,注意,这只是用户故事之一,如果列举全的话,比如涉及免密支付的场景,就肯定会出现用户上下文。包括运营上下文,如果涉及商品补货的用户故事,肯定会出现运营上下文。

 

注意:这张图必须是多个限界上下文负责,包括即将分配的研发人员一起讨论,因为这里已经可以看到很多开发关注的东西了

1)图中连线表示是接口操作,箭头表示自己,或者对方必须要提供的接口协议,比如设备上下文的负责人必须提供一个弹出商品的接口

2)据我的经验,一般业务会有5-8个核心流程,这些核心流程都需要串联一遍,方便我们再检验一遍我们划分出来的限界上下文是否合理

 

如果经过充分讨论,没问题的话,这一步基本把限界上下文的职责界定清楚了,其实相当于限定了微服务功能点。比如支付下文的功能描述

1)对外:对业务方提供创建支付订单接口,创建成功返回支付链接

2)对外:提供支付结果回调,支付结果会异步回调业务方

3)内部:调用微信开放平台接口,获取微信支付code

4)内部:接受微信支付回调结果,变更支付订单内部状态

 

所以接下来,再深入到每个限界上下文内部,如何实现这些功能。

限界上下文内部实现

这一步开始充斥大量的细节,好比我们平时用微信开放平台进行支付,微信开放平台暴露给我们的是非常简单的接口。但是其内部的实现,我们做技术的应该不难猜测,是非常复杂的。 笔者确实没有找到比较切合实际的详细用例子,这里使用张建飞老师的电话计费系统来举例子,来描述如何实现一个微服务复杂的内部。

 

需求如下:

运营商向用户提供电话服务,支持用户拨打/接听电话,并对通话收取费用。如:主动拨打电话收取 0.5 元/分钟的通话费用;接听电话收取 0.4 元/分钟的通话费用。

运营商为了吸引客户,定义了若干电话套餐,总共有三种类型的套餐。这三个套餐分别是:

  • 基础套餐:主叫收费 0.5 元/分钟;被叫收费 0.4 元/分钟

  • 固定时长套餐:套餐月固定费 100 元,包含:200 分钟主叫通话时间+200 分钟被叫接听时间

  • 家庭套餐:套餐月固定费 20 元,用户可以指定 N 个号码作为自己的亲情号,用户接听/拨打亲情号均不收费

我们要设计一个 计费系统 用于套餐计费规则的执行,保存计费记录,并通知账户系统扣减费用。注意:在一次通话过程中,通话控制系统可能会调用多次计费系统进行计费。

 

我们首先可以按照上面的事件风暴法,将限界上下文划分出来,一共三个上下文

1)通话控制上下文,主要是实现两个手机能互相打电话

2)计费上下文,主要是实现计费功能

3)账户上下文,主要是实现账户充值,办理套餐功能

这里假设我们用这张图已经和领域专家,PM达成一致了,那么我们负责计费上下文的实现,通过这张图,我们了解到我们要实现的功能

1)计费状态的设定,开始计费,计费中,结束计费

2)可以读取账户购买得套餐,获取其中的套餐信息

3)在通话结束后,可以对账户进行扣除费用

 

至于里面的计费上下文如何设计,我们必须深入到细节,也就是上面的需求,我们需要挖掘其中的领域对象,然后把领域对象之间的关系建立起来。 

如何挖掘领域对象

找领域对象有很多种方式,这使用比较简单的名词法来构建领域对象,首先我们从需求中找到全部的名词,这里主要需要包含抽象

这里主要的难点是抽象,一定要去和组内架构师对齐,并且拿到最后的模型和领域专家,产品协同对齐修改

(如果实在忘记了这个方法,没关系,可以回到大学补补课:https://www.bilibili.com/video/BV164411b7HX/?p=17&vd_source=f7c8976d4ccdc1e13b3168ae9cd17611)

名词英文描述
账户account 
套餐combination
 
套餐类型customerType

这里需要抽象,合并,这里其实是套餐一个属性,不算一个新名词
1)基础套餐

2)固定时长套餐

3)家庭套餐 

计费规则billingRules

这也需要抽象,合并

1)主叫0.5元/分钟+被叫0.4元/分钟

2)月固定100元 + 权益

3)月固定20元 + 权益

消费记录record


通话session
权益rights

权益(张建飞老师抽象的是资源)

1)200分钟免费主叫通话时间

2)200分钟免费被叫接听时间

3)N个情亲号码


 刚才确定了我们这个计费系统的核心概念,这是现实生活概念的一个抽象,但是这个举例代码还有很长的举例,研发人员看到这个还是不知道怎么写代码。接下来也是非常重要的一步,我们需要画出这些概念的关系。

这就是电话计费系统的领域建模,这张图非常重要,务必和架构师,领域专家确定建模的正确性以及合理性

实体和值对象

为什么要提实体和值对象,因为领域模型的基础单元是:实体和值对象。 如果这个领域对象在其它聚合内维护生命周期,且在它依附的实体对象中只允许整体替换,我们就可以将它设计为值对象。如果这个对象是多条且需要基于它做查询统计,我建议将它设计为实体。

比如下面这个保险领域的实体和值对象

 

 

 

 

 

 

Pre: DDD系列-战术设计-实践

Next: DDD系列-领域驱动设计思想概览

67
Sign in to leave a comment.
No Leanote account? Sign up now.
0 comments
Table of content