尼恩说在前面

在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格,遇到很多很重要的面试题:

谈谈你的DDD落地经验?

谈谈你对DDD的理解?

如何保证RPC代码不会腐烂,升级能力强?

微服务如何拆分?

微服务爆炸,如何解决?

你们的项目,DDD是怎么落地实操的?

所以,这里尼恩给大家做一下系统化、体系化的梳理,使得大家可以充分展示一下大家雄厚的 “技术肌肉”,让面试官爱到 “不能自已、口水直流”

也一并把这个题目以及参考答案,收入咱们的 《尼恩Java面试宝典PDF》V141版本,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。

最新《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请关注本公众号【技术自由圈】获取,后台回复:领电子书

除了本文,尼恩输出了一个 《从0到1,带大家精通DDD》系列,帮助大家彻底掌握DDD,链接地址是:

阿里DDD大佬:从0到1,带大家精通DDD

阿里大佬:DDD 落地两大步骤,以及Repository核心模式

阿里大佬:DDD 领域层,该如何设计?

极兔面试:微服务爆炸,如何解决?Uber 是怎么解决2200个微服务爆炸的?

阿里大佬:DDD中Interface层、Application层的设计规范

字节面试:请说一下DDD的流程,用电商系统为场景

DDD如何落地:去哪儿的DDD架构实操之路

DDD落地:从腾讯视频DDD重构之路,看DDD极大价值

DDD落地:从美团抽奖平台,看DDD在大厂如何落地?

美团面试:微服务如何拆分?原则是什么?

DDD神药:去哪儿结合DDD,实现架构大调优

DDD落地:从网易新闻APP重构,看DDD的巨大价值

DDD落地:从阿里单据系统,看DDD在大厂如何落地?

DDD落地:有赞的生产项目,DDD如何落地?

DDD落地:从携程订单系统重构,看DDD的巨大价值

DDD落地:京东的微服务生产项目,DDD如何落地?

大家可以先看前面的文章,再来看本篇,效果更佳。

另外,尼恩会结合一个工业级的DDD实操项目,在第34章视频《DDD的学习圣经》中,给大家彻底介绍一下DDD的实操、COLA 框架、DDD的面试题。

DDD现在非常火爆,是有其巨大生产价值,经济价值的, 绝不仅仅是一套概念那么简单。

DDD的绝大价值,具体请参见以下视频:

从腾讯视频DDD重构案例,看看DDD极大价值

本文目录

- 尼恩说在前面

- 阿里供应链商品域DDD实践

- 一、软件复杂性是什么?

  - 1. 理解力挑战

  - 2. 不可预测性挑战

  - 3. 协作力挑战

- 二、Why DDD?

- 三、DDD核心

  - 1. 通用语言

  - 2. 分层架构

  - 3. DDD要素

  - 4. 边界上下文

- 四、DDD实施

  - 1. DDD实施的挑战

  - 2. 什么是领域知识?

  - 3. 领域知识提炼,需求和链路5W1H分析法

  - 4. 领域知识提炼,结构化分析

  - 5. 思考方式的转变

- 五、商品域实践相关

- 说在最后

- 部分历史案例

阿里供应链商品域DDD实践

作者:侧帽

供应链商品域DDD实践时间虽不长久,但在历程中我们遇到了众多挑战,有的已找到解决之道,有的则仍在探求之中。近期,我很荣幸能在供应链服务与创新团队分享我的经验,并希望在此与各位共享一些见解,以期引发更多思考和讨论。

DDD不仅是一套理论框架,其成功实践更取决于执行力与贯彻力度。

接下来的内容将分为两部分展开:DDD的基本概念与实践应用。基本概念涵盖通用语言、分层架构、DDD的核心元素、以及边界上下文等;而实践应用则包括领域知识的提取方法、思考模式的转换,并且会结合实际商品案例进行说明。

一、软件复杂性是什么?

在深入DDD实践之前,我们需要首先认识到软件复杂性的本质。DDD作为一种针对复杂软件开发的方法论,提供了一套应对复杂度的策略。那么,软件的复杂性究竟体现在哪些方面呢?

在阿里两年,我感受很深的一个点是,我们不能持续交付不断演进的复杂软件,所以有1.0、2.0、3.0很多的版本,1.0搞不下去了,开始2.0,2.0也搞不下去了,开始3.0,不断循环。

阿里体系复杂度我看来是理解力、不可预测、协作力挑战三个方面。

1. 理解力挑战

  • 需求规模的不断扩大,业务种类的日益增多,以及业务间的深度耦合,都会使得软件系统的复杂性不断升高。例如,供应链领域涉及20多个行业,各种商业模式如经销、代销、一盘货等交织在一起,再加上跨境进口、国内业务及国际化业务的融入,这一切都使得系统复杂度激增。

  • 系统间划分模糊,依赖关系错综复杂。以供应链商品为例,与共享SELL、AIC、IPM等系统的界限划分一直是个难题,每次大型项目的接入都会引发对边界的重新审视和讨论。

  • 系统结构复杂,因为应对高并发、高稳定性等,功能性代码与非功能性代码混合,如业务代码混杂着各种兜底逻辑、灰度逻辑、重试等等,100行代码,可能业务代码不到30行。

2. 不可预测性挑战

  • 快速变化的商业环境和多变的商业规则为软件设计带来了极大的不确定性。例如,今年国际化、智能商业路由、考拉融合等新趋势的涌现,使得设计者难以在前期做到全面规划。

  • 变化不可预测,软件系统变化也不可预测,这为设计者带来了巨大的挑战。

3. 协作力挑战

  • 需求的多方交叉和低效的需求传递问题。在多团队协作的环境下,需求的传递和沟通常常显得低效,导致方案产出的速度缓慢。

  • 团队角色和业务概念的多样性,缺乏统一的术语和语言,常常导致理解上的偏差。

二、Why DDD?

DDD旨在通过构建恰当的领域模型以映射真实业务场景,从而有效地解析业务领域的核心复杂性问题。它是面向对象设计(OOAD)的进一步发展与深化。这一设计哲学提出了以下解决策略:

  • 分而治之,控制规模:这意味着将复杂问题拆解成更小、更易于管理的片段。

  • 关注点分离,应对理解力挑战:这包括将领域模型与数据存储模型分开,将业务复杂性与技术复杂性分开,以减轻理解上的困难。

  • 分层架构、分离核心:这一策略旨在维持结构的清晰性,同时应对各种不可预见的挑战。

  • 统一语言,应对协作力挑战:在团队协作中,采用统一的语言以确保每个成员对系统目标、范围和功能有共同的理解。

三、DDD核心

图片

1. 通用语言

通用语言是领域知识的精炼表达,统一语言的建立实际上是需求分析的一部分,它涉及团队成员在系统目标、范围和具体功能上达成共识。

领域语言是团队特有的,负责解释和维护。即使在相同名称的概念下,不同团队可能会有截然不同的理解。

领域专家、产品经理和开发人员共有的语言,这种语言是连接领域专家和技术的桥梁。

在整个开发过程中,无论是文档编写还是日常沟通,保持概念的统一性都至关重要。例如,在中文环境中,确保术语的一致性,并将概念与代码紧密相连,使得代码中的概念名称与通用语言保持一致,从而减少混淆。

通用语言价值:

  • 定义明确的公共术语,以减少概念上的混淆。

  • 作为沟通的基础,以消除歧义和理解上的偏差,提高需求理解和知识消化的效率。

  • 统一概念与代码之间的桥梁,确保实现与概念的一致性。

图片

2. 分层架构

DDD第二个核心是分层架构,分离模型。一个理想的架构关注点的分离是至关重要的,这样我们可以更有效地对系统进行模块化处理,并提高其可测试性。

一个人同时要做多件事情的时候,难免手忙脚乱。代码也一样,一段代码要处理各种事情的时候,也会乱成一团,所以我们要分解开来,各个击破。

图片

商品域领域模型,在分层架构中的位置,如下:

图片

  • CQRS模式:领域模型在应用层下面,command才走领域模型;查询和搜索服务不走。

  • tunnel层,负责与数据库和外部数据资源的交互,实现了领域模型与数据访问的解耦,这与传统的DAO模式类似。

  • 通过SPI接口,外部系统可以与模型进行交互,采用六边形适配器模式来实现这一目标。

3. DDD要素

1)实体:有id,生命周期、状态、属性和行为的对象。实体的状态和行为可能会因外部事件的发生而发生变化。

为了区分实体和视图对象(VO),我们将不可修改的属性使用final进行修饰。VO的目的是为了减轻领域模型的负担,例如商品可能有超过100个属性,将这些属性展开并不能很好地表示其结构化特征,因此我们将具有相似特征的属性分组封装成不同的VO。

2)服务(Service)的角色:服务在处理批量实体操作、跨实体操作等方面发挥着重要作用,例如商品复制和转账功能。

商品域的工程架构:

  • serivce职责是:实体创建,持久化,跨实体操作等。

  • 不同层次使用不同的数据对象,tunnel层使用dataobjects,它们面向存储,并且需要与实体进行转换。

  • 实体之间存在关系,可以动态加载关联对象;而dataobjects仅包含数据,没有行为,并且一般不会有关系。

图片

4. 边界上下文

  • 边界 = 域或子域。

  • 领域对象只有在领域内部才具有确切的含义。一旦超出这个边界,其含义无法得到保证,就像苹果这个水果一样。

  • 语言是有上下文的。

  • 在不同的上下文中,职责和任务不一样。人有多个角色,在家里是爸爸、在公司是小二,职责和任务不一样。

图片

上下文映射:

  • 当有了明确的边界后,我们需要思考领域如何输出价值。一个完全封闭的系统无法实现价值。

  • 常用的方法包括:共享内核、防腐层等。防腐层的作用是:商品上游提供SPI接口,SPI接口不直接对外开放领域模型,而是建立一层开放视图。在采购域中建立防腐层,以减轻商品变更对本域的影响。

图片

四、DDD实施

1. DDD实施的挑战

  • 识别和提炼领域知识,并体现在模型代码上,强调一次“并体现在模型代码上”!

  • 防腐,保持模型不断演进,需要持续投入,保证DDD贯彻执行。

  • 人的转变,开发思考方式的转变。

图片

2. 什么是领域知识?

领域知识包含多个层次和分类,其中通用的商业规则是领域模型的关键输入,而商家个性化不能下沉到领域模型层。

图片

3. 领域知识提炼,需求和链路5W1H分析法

两阶段分析:用户故事、链路和边界分析。

  • 前3W描写用户故事,用户要什么,为什么要?举个例子,我作为采购小二,需要商品库存为0自动下架,因为有超卖风险,客户会投诉。

  • 后面的When、Where、How是链路和边界分析,触发的条件是什么,要实现这个功能需要哪些域参与进来,分别提供什么能力?

通过这个分析,获取用户需求,和全链路分工。

图片

4. 领域知识提炼,结构化分析

  • 将APP层的至上而下的过程分析与模型层的自下而上的分析相结合。

  • 能力下沉以保持模型的持续演进,标准则是复用性和内聚性。

图片

5. 思考方式的转变

在领域驱动的模型阶段,我们不专注于数据设计、存储或是消息的发送方式,而是将业务和技术视角的关注点分离,从而实现真正的领域驱动。

图片

五、商品域实践相关

商品域工程架构:

图片

图片

最后,保持模型不断演进!!!

商品域模型更新readme,保持模型不断演进。否则会APP层会越来越大,模型层越来越小,最后头重脚轻,领域坍塌了。

图片

说在最后

DDD架构如何落地,是是非常常见的面试题。

以上的内容,如果大家能对答如流,如数家珍,基本上 面试官会被你 震惊到、吸引到。

在面试之前,建议大家系统化的刷一波 5000页《尼恩Java面试宝典PDF》,并且在刷题过程中,如果有啥问题,大家可以来 找 40岁老架构师尼恩交流。

最终,让面试官爱到 “不能自已、口水直流”。offer, 也就来了。

当然,关于DDD,尼恩即将给大家发布一波视频  《第34章:DDD的学习圣经》, 帮助大家彻底穿透DDD。

图片

部分历史案例