在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业字节、如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格,遇到很多很重要的面试题:
谈谈你的DDD落地经验?
谈谈你对DDD的理解?
如何保证RPC代码不会腐烂,升级能力强?
用电商系统为例介绍一下领域驱动设计DDD?
最近有小伙伴在字节,又遇到了相关的面试题。小伙伴懵了, 当然,面试也就挂了。
这里尼恩给大家做一下系统化、体系化的 DDD 梳理,使得大家可以充分展示一下大家雄厚的 “技术肌肉”,让面试官爱到 “不能自已、口水直流”。
也一并把这个题目以及参考答案,收入咱们的 《尼恩Java面试宝典PDF》V122版本,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。
《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请到文末公号【技术自由圈】获取
出了本文,尼恩输出了一个 《从0到1,带大家精通DDD》系列,帮助大家彻底掌握DDD,链接地址是:
《阿里DDD大佬:从0到1,带大家精通DDD》
《阿里大佬:DDD 落地两大步骤,以及Repository核心模式》
《阿里面试:让代码不腐烂,DDD是怎么做的?》
《阿里大佬:DDD 领域层,该如何设计?》
《极兔面试:微服务爆炸,如何解决?Uber 是怎么解决2200个微服务爆炸的?》
《阿里大佬:DDD中Interface层、Application层的设计规范》
大家可以先看前面的文章,再来看本篇,效果更佳。
另外,尼恩会结合一个工业级的DDD实操项目,在第34章视频《DDD的顶奢面经》中,给大家彻底介绍一下DDD的实操、COLA 框架、DDD的面试题。
领域驱动设计(Domain-driven Design,DDD)是一种软件设计方法,该方法的核心思想是将业务领域作为设计和开发的中心,强调对业务领域的深入理解、业务语言的建模以及领域对象的设计和实现。
这样可以更好地将软件设计和业务需求紧密结合起来,从而提高软件的可维护性、可扩展性和可重用性,使得软件更加贴近业务需求。
DDD设计的两个阶段包括两部分,战略设计部分和战术设计部分:
第1步: 战略设计
战略设计主要从业务视角出发,包括了业务场景分析、领域建模、划分边界上下文三个阶段。限界上下文可以作为微服务设计的参考边界。
第2步:战术设计
战术设计则从技术视角出发,侧重于领域模型的技术实现,完成软件开发和落地,
战术设计包括:聚合根、实体、值对象、领域服务、应用服务和资源库等代码逻辑的技术设计和技术设计。
在战略设计阶段,我们最主要的过程大致包括了业务场景分析、领域建模、划分边界上下文三个阶段。
实际上战略设计是 DDD 过程中的核心步骤。
在这个阶段我们所有做的就是进行全面的业务梳理,把业务中涉及到的所有细节都梳理出来,为后续进行领域建模分析提供足够的、全面的业务输入。
战略设计 经常使用到的业务场景分析方法主要包括
一般使用事件风暴法。
事件风暴是一种快速,轻量级且未得到充分认可的群体建模技术,它对于加速开发团队而言非常强大,有趣且有用。
这里我们使用事件风暴进行业务场景的分析以及梳理。
(1)事前准备
在进行事件风暴之前我们需要进行一些准备,主要包括贴纸、笔以及讨论的会议室,
会议室中最好不要有椅子,目的是想让大家都能够站立在一起、全神贯注的去进行业务讨论。
(2)邀请参会的人
会议的参与方主要包括用户、产品经理、PD、研发、测试、架构师等。
其中,PD为产品设计师,也可能叫产品规划师、需求分析师、小产品经理。
PD侧重于将对应用做功能级的设计,在这个模块上,PD类似是一个小产品经理、模块级别的产品经理。
架构师(系统分析师)会与PD紧密合作,架构师 这时候开始考虑技术可行性,性价比。
PD的职位描述:
(1)调查市场并研究需求,形成市场需求文档。
(2)负责新产品设计,拟定设计规划和方案。
(3)负责新产品的原型设计。
(4)组织产品开发团队,协调资源,跟进产品的开发,保证日程进度。
(5)分析产品运营数据,收集运营意见,及时调整产品形态,优化产品,并提出合理的运营建议。
(6) 以用户体验为中心,改进现有产品,或设计新产品。
(3)业务讨论
首先确定我们今天需要讨论的业务是什么,目标是什么。
咱们业务场景中,如果讨论的业务就是电商,那么,目标就是完成业务梳理,确保没有业务方面的理解 gap,在团队中达成业务理解的的一致性。
事件风暴过程需要问题驱动,一般通过提问的方式来驱动交流。
a、分析业务中的事件,搞清楚事件发生的前因后果
这些我们都需要梳理清楚。
还有一点需要注意, 需要全面梳理
b、寻找业务逻辑和业务规则
注:在进行事件风暴过程中,所有的参与人都要全身投入整个过程,
大家都是站立形式,聚焦全部注意力,
大家都放下手机以及电脑,一起参与整个业务梳理过程,只有这样,事件风暴才可能有比较好的效果。
在前面的事件风暴业务梳理中,我们已经把电商业务涉及到的参与者、动作以及事件等都进行了全面的梳理。
参与者、动作以及事件 整个协作流程,是一个粗粒度的 业务流程, 非常粗。
那么接下来我们就要在此基础之上,进行细粒度的 领域建模,这是整个 DDD 的核心。
DDD领域模型 细分为两步骤,第一步是发散,产生很多实体、命令、事件等领域对象,
DDD领域模型 细分为两步骤,第二步是收敛,我们从不同的维度对进行聚类形成聚合,建立最终领域模型, 这是一个收敛的过程。
(1)发散阶段:领域对象分析
领域对象分析,也就 实体、值对象、领域事件、领域命令的分析。
(2)收敛阶段:构建业务聚合
完成领域对象分析之后,我们需要构建业务聚合。
想要构建聚合,那么首先就要在实体中找到聚合根。
来看看,一个 聚合根的特点:
获得了整个业务流程中的所有聚合后,我们需要更具业务语义上下文将具体的聚合划分到对应的上下文中,
在战略设计阶段,我们通过事件风暴法对整体的业务进行了全部的梳理,同时构建了领域模型,以及划分了边界下文。
那么接下来我们就要将领域模型映射到工程结构,以及代码中实现最终的实现落地。
另外在这个阶段实际还有很多细节需要明确的。
需要哪些领域服务,领域服务依赖哪些属性,依赖哪些实体,依赖哪些值对象,这些都是需要在战术设计阶段明确下来。
在领域分层方面,可以按照cola分层结构来进行,这个后面结合cola框架进行说明。
当我们把领域对象进行进一步的细化之后,同时把对应的领域服务敲定之后,我们可以把这些分析后的内容映射成工程分层后的代码了。
所以,后续就进入到阶段了,还有很多工作要做,比如详细设计、编写代码以及功能测试,
特别实在详细设计阶段,我们还要涉及很多的细节问题的敲定,比如数据库表的设计、比如使用什么 MQ,用不用缓存,怎么保证缓存和数据库的数据一致性问题,分布式服务有没有分布式事务的问题,应该怎么解决?
有没有服务幂等问题,应该怎么解决?
这些都是需要在详细设计阶段进行确定的。
因此 DDD 就像是框架,通过它把业务映射成为领域对象以及领域服务和领域事件,再把这些领域相关内容再读映射为实际的代码。
使得我们的服务更加的逻辑清晰以及扩展性更强,但是分布式的技术实现细节,我们还是需要有对应的解决方案来进行解决。
大致可以梳理出下面的参与者、动作以及事件
通过对领域事件的记录和处理,可以在电商系统中实现更加复杂的业务逻辑,提高系统的灵活性和可维护性。
电商系统中的聚合和聚合根是什么?
在电商系统中,可以将订单作为一个聚合,其中包括多个领域对象,例如订单项、收货地址、发票信息等。
订单作为一个聚合,它的内部领域对象之间有明确的关联关系,并且需要满足一些业务规则,例如订单项的数量不能为负数,订单状态必须是待付款、待发货、待收货、已完成等状态之一。
在订单聚合中,可以将订单对象作为聚合根,用于保证订单聚合的完整性和一致性。订单对象具有唯一标识和全局访问权限,它可以被其他领域对象引用,例如订单项和收货地址等。
使用聚合和聚合根可以将复杂的业务逻辑封装在一个边界内,提高系统的可维护性和可扩展性。
电商系统是一个涉及到多个业务领域的复杂应用系统,经过上下文建模和边界上下文划分,最后确定电商系统所包含了众多的子域。
以下是电商系统中常见的一些子域:
在实际的电商应用系统中,可能会根据业务需求进一步细分和扩展各个子域。每个子域都可以作为一个独立的微服务进行设计和开发,从而实现更好的业务解耦和系统扩展性。
核心是领域服务设计
电商系统中包括的领域服务,主要如下:
这些领域服务之间相互协作,共同实现电商系统的核心功能和业务流程。
通过领域服务的划分和封装,可以提高系统的可扩展性和可维护性,降低系统的耦合度和复杂度。
领域驱动设计(DDD)和微服务是两种不同的概念,但它们可以结合在一起来提高软件的质量和可维护性。
微服务架构是一种将应用程序拆分成多个小型、自治的服务的架构模式,每个服务专注于某个特定的业务功能,通过轻量级通信机制进行协作。
微服务架构通常需要处理大量的业务逻辑,因此需要一个清晰的领域模型来管理这些业务逻辑,这时领域驱动设计就能够发挥作用了。
通过领域驱动设计,开发人员可以更好地理解业务需求,更好地建模业务领域,将领域模型作为微服务架构的核心,从而更好地支持微服务架构。
具体来说,领域驱动设计可以帮助实现以下方面:
微服务的拆分和划分:通过领域驱动设计,可以将业务领域划分为不同的子域,并将每个子域划分为一个或多个微服务,从而实现微服务的拆分和划分。
服务间的通信:微服务架构中的服务需要通过通信机制进行协作。
通过领域驱动设计,可以在微服务之间定义明确的接口和协议,使得服务之间的通信更加清晰和稳定。
微服务的扩展和维护:通过领域驱动设计,可以将业务逻辑清晰地划分为不同的领域模型,从而使得微服务的扩展和维护更加容易。例如,在需要修改业务逻辑时,只需要修改对应的领域模型和微服务,而不需要修改整个应用程序。
因此,领域驱动设计可以帮助开发人员更好地支持微服务架构,并实现更好的软件设计和开发。
领域驱动设计和敏捷开发是两种不同的方法论,但可以相互结合,提高开发效率和软件质量。
在敏捷开发过程中,团队通常采用迭代式的开发模式,不断地根据用户反馈和需求变化进行调整和优化。
这种敏捷开发模式与领域驱动设计的思想相契合,因为领域驱动设计强调将业务领域建模为一个相对独立的系统,同时也强调不断优化和迭代。
以下是一些结合领域驱动设计和敏捷开发的方法:
DDD 面试题,是非常常见的面试题。 DDD的学习材料, 汗牛塞屋,又缺乏经典。
大家面试的时候, 可以参考以上的内容去组织答案,如果大家能做到对答如流,如数家珍,基本上 面试官会被你 震惊到、吸引到。
另外在面试之前,建议大家系统化的刷一波 5000页《尼恩Java面试宝典PDF》,并且在刷题过程中,如果有啥问题,大家可以来 找 40岁老架构师尼恩交流。
最终,让面试官爱到 “不能自已、口水直流”。offer, 也就来了。
当然,关于DDD,尼恩即将给大家发布一波视频 《第34章:DDD的顶奢面经》, 帮助大家彻底穿透DDD。
……完整版尼恩技术圣经PDF集群,请找尼恩领取
《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》PDF,请到下面公号【技术自由圈】取↓↓↓