• 打造千万级流量秒杀系统第五课 领域建模:DDD 原理及秒杀系统领域模型


    上一讲,我们介绍了如何设计秒杀的系统架构。

    在电商系统中,我们通常把完整的购物流程划分为下单前和下单后。下单是由用户在商城发起的,下单后订单涉及关单、支付、退款、筛单、投递、售后等流程。

    其中,关单涉及库存系统,支付流程涉及支付系统,退款流程涉及客服、支付和财务系统,筛单涉及风控系统,投递涉及物流和仓储系统,售后涉及售后系统。

    说了这么多,你有什么发现没?仅仅一个订单的完整流程,就涉及好几个系统。

    此时,就有一个问题产生了:我们该如何划分各个系统的职责边界呢?也就是说,当订单数据被多个系统用到时,订单数据到底由谁来维护呢?

    这就是我们本讲要解决的问题——DDD 原理及秒杀系统领域模型。

    注:本讲结尾还有秒杀系统领域建模的思维导图哦,可以让你一目了然。

    DDD 原理及作用

    什么是 DDD?

    DDD(Domain Drive Design,领域驱动设计)是一种软件设计方法,是指在软件设计的过程中始终围绕领域来构建模型。构建领域模型的过程就叫“领域建模”。

    怎么理解呢?

    这里的领域,我们可以理解成业务对象。

    举个例子:一个订单中心的业务逻辑总是围绕订单数据来实现的,比如下单、取消订单、订单退款、订单履约等业务逻辑。而订单数据在面向对象编程中的实体是订单对象,也就是订单中心的业务对象。

    领域模型就是业务对象模型,是描述业务功能实现的对象模型,它是对业务对象协作关系和业务执行逻辑的一种抽象提炼。

    那在一个业务系统中可以有多少领域呢?在一个遵循领域驱动设计的业务系统中,可以有多个领域。但是,应当有且只有一种核心领域,因为这样它的职责才非常清晰。另一些非核心领域,我们统称为子领域。

    现在你是不是理解了领域模型是什么呢?而DDD 就是为了解决各个业务系统的职责划分,围绕业务对象而进行模型建构。

    具体它是怎么做的呢?

    DDD 的作用

    DDD 将领域模型分为 4 层,如下图所示:

    Drawing 0.png

    图1 领域驱动设计风格的架构草图(来自 DDDSample 官网)

    这 4 层分别是:

    1. Interfaces用户界面层,有时候也叫呈现层,比如前端或者客户端;

    2. Application 应用层,负责给用户界面层提供业务应用的业务逻辑,如商城接口服务;

    3. Domain 领域层,负责某个核心领域的具体业务逻辑,如电商的订单中心;

    4. Infrastructure 基础设施层,如 MQ、MySQL、Redis 等。

    有了这样的层级划分,加上一些划分层级的规则,我们就能快速找出各个系统的业务边界,将系统的职责划分清楚,以免逻辑混乱难以维护。

    比如,有个接口是提供给运营后台前端用的,结果在划分职责的时候将其划分到商城 API 服务里了,这样可能会直接暴露给外网用户,不仅导致逻辑混乱,还存在严重风险。如果按照 DDD 的分层模型来划分,我们就能将 API 服务和管理后台的职责划分清楚,避免此类问题。

    实际上,现代软件系统往往功能复杂,需要微服务化,以便进行长期维护。而在微服务架构中,由于需要将业务功能拆分成多个微服务,就涉及领域划分的问题。如果没有 DDD 的理论指导,我们很可能将某个功能,划分到错误的微服务里,比如,将订单功能划分到物流服务里。

    如果你想了解有关 DDD 更多的内容,可以学习我们的另一个专栏《DDD 微服务落地实战》

    如何使用 DDD 对秒杀系统领域建模?

    领域建模都有哪几个步骤呢?从整体上看,领域建模分为战略建模和战术建模。

    战略建模

    什么叫作战略建模?战略建模是指从宏观上构建领域模型。

    拿建楼来打个比方:建大楼之前,需要先绘制出大楼的整体外观设计并划分出大楼每个功能区,然后再进行整体结构设计。这些划分出来的功能区,就好比软件系统中的各个子系统和组件。比如在前几讲提到的前端、后端接口服务、后台配置服务是秒杀系统的组件,商品中心、库存中心、用户账号中心是秒杀系统依赖的子系统。

    Drawing 1.png

    怎样进行战略建模呢?

    战略建模主要分为以下几个步骤。

    第一步,确认系统中的各个子系统和组件划分到领域模型中的哪一层。

    以秒杀系统为例,秒杀商城的前端和管理后台的前端,我们可以把它划分到用户界面层。

    秒杀系统接口服务,因为负责给秒杀前端提供活动信息和活动相关商品信息,我们可以把它划分到应用层。

    秒杀系统配置服务、商品中心、库存中心和用户账号中心,因为涉及对应核心领域的具体业务逻辑,我们把这些划分到领域层。

    最后是 MQ、MySQL、Redis、数据统计、监控系统等,负责提供数据的流转、存储、查询的能力,可以划分到基础设施层。

    第二步:为领域层划分核心域和非核心域。

    这样做的目的是区分哪些是核心业务逻辑,哪些是非核心业务逻辑,便于后期设计。

    那么,秒杀系统的核心域和非核心域分别是什么呢?

    我们知道,秒杀系统包括活动信息、商品信息、用户信息、库存信息。而秒杀系统核心功能是提供秒杀活动的能力,不管是商城前端页面还是管理后台页面,交互的入口都是从活动信息开始。所以,秒杀活动信息就是秒杀系统的核心域,而商品信息、库存信息、用户信息是非核心域。

    需要注意的是,为了区分哪些是用于支撑秒杀业务的,哪些是在所有系统中通用的,非核心域要区分支撑子域和通用子域。

    什么叫支撑子域和通用子域呢?

    所谓支撑子域,是指跟当前业务有关联的非核心域,并在当前业务系统中起到支撑业务的作用,如秒杀系统中用到的商品信息、库存信息都是为秒杀活动提供支撑作用。

    所谓通用子域,是指跟当前系统的核心业务逻辑关系不大但又必须要有的非核心域,在所有系统中都通用的,如秒杀系统中的用户信息等。

    第三步,确定各领域的限界上下文,确定领域的业务边界。

    这一步是战略建模最核心的工作,主要是为了明确系统中各子系统和业务模块的具体职责。

    那么,秒杀系统中的限界上下文到底是什么呢?在秒杀系统的核心域中主要涉及的对象有:专题信息、场次信息、商品信息。其中商品信息包括价格、库存、文案,而价格分为秒杀价和原价,库存分为秒杀库存和实际库存,文案主要是秒杀文案。

    下面我们用一张图来表示它们的关系:

    Drawing 3.png

    图中大的椭圆表示领域模型分层中的领域层,虚线表示各领域的边界,虚线圈定的范围是领域,领域内部的椭圆表示限界上下文,实线表示限界上下文之间的映射关系。限界上下文和上下文之间的关系组成上下文映射图。

    最后一步,为各限界上下文建立上下文映射图,为战术建模做准备。

    在秒杀系统中,核心域的限界上下文是活动上下文,比如:活动主题、活动场次等。对于商品的活动信息,因为包含活动价格、活动文案、活动库存,初看应该归属活动上下文。但是,我们也有按照商品原始信息安排的销售活动,比如新品发布会当天的新品销售。所以,商品活动信息是属于商品的销售属性,应当分拆给商品上下文和库存上下文。

    各限界上下文的上下文映射图如下所示:

    Lark20201127-102212.png

    有了上下文映射图后,我们接下来就可以做战术建模了。

    战术建模

    刚才咱们提到了战术建模,那战术建模又是什么呢?所谓战术建模,就是从具体细节上构建领域模型,它是对战略建模中限界上下文的具体实现。

    还是以秒杀系统为例,秒杀系统的战术建模就是分析活动领域中各个对象的类型,针对类型特点做抽象设计。

    那具体要怎么做呢?

    不知道你有没有注意到,这些对象里有的是可以通过 ID 或者名称唯一确定的。

    比如,通过专题名称或 ID 唯一标识专题,通过商品 ID 唯一标识商品,通过账号 ID 唯一标识账号或用户。这些能被唯一标识出来的对象我们称之为“实体”。虽然场次在时间上也是唯一的,但我们不需要唯一标识来区分它,只需要保证时间上不重叠即可。

    那些不能被唯一标识出来的对象,要么是一个具体的值,比如库存数和价格,我们称它为“值对象”;要么是将其他对象聚合而来,比如场次信息聚合了专题 ID 和商品,我们把它叫“聚合根”。另外,领域对象还可能触发某些事件,比如活动开始和结束,我们把它叫“领域事件”。

    所以,在秒杀系统中,战术建模后的结果如下:

    1. 实体,包括主题、商品、账号;

    2. 值对象,包括实际库存、销售库存、原价、活动价;

    3. 聚合根,包括场次、活动商品;

    4. 领域事件,包括活动未开始、活动进行中、库存已售罄、活动已结束。

    Drawing 6.png

    有了战术建模后,我们就可以针对领域做各种抽象类设计了。比如,我们将抽象出主题类、商品类、场次类、库存类、账号类等。当然,这块属于详细设计,后续我会在代码实现那几节细讲。

    小结

    这一讲我们初步学习了领域驱动设计,以及以秒杀系统为案例进行领域建模实战。通过领域建模实战,你是不是既加深了对需求的理解,又学会了一种新的软件工程方法论呢?

    使用 DDD,我们可以清晰地划分领域边界,划分子系统的职责,设计出扩展性良好的系统架构。由于系统职责划分清晰,也就能给核心业务和非核心业务合理地分配好资源,确保核心业务系统的性能和可用性。

    给你留一个思考题:如何为订单系统构建领域模型?可以把你的想法写的下面留言区哦。

    这一讲我们就先介绍到这里,下一讲,我们将具体来介绍秒杀系统的高可用架构设计。

    Drawing 7.png


    精选评论

    *明:

    读完文章,关于秒杀系统的ddd的分析,已经很清楚了,但是如果我们企业级比较复杂的业务,进行战略和战术分析,有什么建议嘛,还有就是如何衡量业务适不适合ddd呢,谢谢老师

        讲师回复:

        复杂的业务系统很适合用DDD。首先需要理清楚逻辑视图中的各种功能,然后按照功能之间的耦合关系强弱划分出多个业务领域,每个业务领域是个一级子系统。一级子系统内部视功能逻辑的复杂程度再拆二级子系统。总之就是通过拆分出多个高内聚低耦合的子系统,化繁为简。

    **彪:

    牛,厉害。看别人的视频看几遍都看不懂别人讲的领域椭圆图,老师讲课完全是说给他自己听的。反而看您的文章,一看就懂了,好文

    **升:

    看得不是很明白啊

        讲师回复:

        领域驱动设计中涉及多个比较抽象的概念,需要多结合工作中的项目来理解。就像软件设计的7大法则和23种设计模式,需要结合项目多看几遍,特别是项目中遇到痛点寻求解决方案的时候,结合问题来看更容易理解。

    **成:

    想请教下,domain模型里根据实体,值对象,服务,仓库,工厂和聚合如何去规划目录会好点

        讲师回复:

        这个看项目复杂度。根据项目复杂度来采用合适的目录结构。根据实体、值对象等划分目录,颗粒度比较细,适合代码量较多的复杂项目。

    **个咪的汪:

    核心域:订单上下文 订单信息支撑子域: 商品上下文 = 物流信息通用子域:用户上下文 = 账户信息

    **福:

    订单系统包括商品、库存、用户、结算、物流、售后几个部分。

    **3251:

    感谢作者,收获蛮大,感觉还是比较精致的,后面看看如何,希望后面能把5视图详细分析清楚,以及案例,我不是计算机专业毕业的,物理视图这块还想能够有深入的理解,能推荐些文章看看也好

        讲师回复:

        物理视图描述的是最底层的物理设备间的拓扑关系。需要对计算机物理设备有一定了解。特别是网络设备,它是整个互联网的神经系统。另外物理设备的部署方式决定了物理设备的可用等级,只要是设备,就必定有需要维护的时候,就需要在部署的时候考虑到维护设备带来的稳定性问题。可以找一本IDC机房相关的书籍了解一下。

  • 相关阅读:
    2022-1月报
    最新AI创作程序源码ChatGPT系统网站源码/Ai绘画系统/支持OpenAI GPT全模型+国内AI全模型/详细搭建部署教程
    c++ chilkat-9.5.0 库使用CkZipW创建压缩包
    k8s上对Pod的管理部分详解
    ⑩④【MySQL】什么是视图?怎么用?视图的检查选项? 视图的作用?[VIEW]
    springboot整合elasticsearch
    echarts 设置 折线图
    Linux操作系统——校招高频考点汇总
    Java单例模式
    MySql 数据库【表】
  • 原文地址:https://blog.csdn.net/fegus/article/details/126341463