领域驱动基础知识
DDD解决了什么问题?
DDD 解决对复杂应用建模的问题。DDD 是一套设计方法和思想,而非具体的编程实践。应该区别于TDD、BDD 等名词。
DDD的三原则是什么?如果让你讲,你会怎么讲解这三个原则?(举一个符合的例子,一个不符合的例子)
1. 聚焦核心领域
设计一个应用系统,应该只关注业务的核心问题,其他必要的附属问题应该围绕支撑核心问题来处理。例如垂直电商(也买网)的业务核心在让用户能快速发现专业供应商提供的产品,重点在商品检索上。但是会员系统是业务必须要要求的,所以用户系统则应该为主要业务服务,应该把资源投入到核心领域中。
1. 通过协作迭代式探索模型
整个团队中每个人的信息都是局部的,想要建立一个大的图景,自上而下的规划设计在软件开发中是很困难的(软件开发的固有特点就是不确定性和变化)。通过领域专家、工程师一起探索识别系统中存在的业务需求、现实情况、外部依赖等知识,不断完善模型。
1. 使⽤用统⼀一语⾔
DDD 需要领域专家和工程师、QA、UX 等协作建模,在不同的上下文中不同的名词代表的含义不一样,例如一个报销系统中 bill、ticket 都有单据的含义,但是bill可能指消费的账单,ticket 指在系统中提交的包含bill的工单。
同样也需要统一技术语言和业务语言。领域专家眼里的“流程图”和工程师眼中的“流程图”有时候非常不一样。
DDD的元模型是什么?
TBD
DDD不适合做什么?(举一个适合的例子,一个不适合的例子)
DDD 适合用于复杂业务建模,如果项目比较简单,不适合使用DDD来设计。同理 DDD 会带来成本,在这些成本接受范围之外的组织也不适合使用DDD。
DDD为什么又火了?
DDD 是一个原本就存在的概念,微服务发展的原因需要一个方法论支撑服务划分。DDD 和微服务的出发点都是从业务视角分离复杂度,因此DDD被社区内当做微服务的实践之一。
银弹的定义是什么?银弹跟DDD有什么关系?
软件工程自身的复杂性和变化性,导致软件开发过程里是没有万能的终杀性武器的,只有各种方法综合运用,才是解决之道。DDD 不是银弹,DDD 只能解决特定的问题,而不是万能的,只有再适合使用DDD的地方使用合理运用才能发挥DDD的价值。
DDD跟Design Thinking怎么关联?
Design thinking 设计思维是一种通过角色扮演活动、工作坊、头脑风暴等方式促进学习的方法,在DDD 中需要团队领域专家、工程师和其他角色共通参与建模,工作坊和头脑风暴是一种非常好的方式。
聚焦核心领域
子域有哪三类,通常分别采用什么样的策略处理?(举两个策略不同的例子)
- 核⼼子域指业务成功的主要促成因素,是企业的核⼼竞争力。一般一个系统只存在一个核心子域,并应该投入最好的资源到这个领域。核心子域应该作为企业的核心竞争力。
- 支撑子域不是核⼼,不被整个系统使⽤,完成业务的必要能力,但不是业务成功的原因。例如电商系统中,会员系统必不可少但是应该作为支撑订单等业务来考虑;而社交应用中会员系统是作为核心竞争力对待的,但是也会有电商模块作为支撑。
- 通⽤子域不是核心,但被整个业务系统所使用,通用子域可以看做特殊的支撑子域。通用子域可以使用业界主流通用方案,例如文件服务、通知服务、推送、舆情等。甚至可以考虑购买更专业企业提供的服务。
产品愿景与价值定位有什么用?
对产品的顶层价值设计,对产品⽬目标⽤用户、核⼼心价值、差异化竞争点、痛点等策略略层信息在团队层⾯达成共识。用于对领域划分提供依据,例如微信可能有做支付的想法,支付宝有做社交的想法,但微信的支付和支付宝的社交都应为他们的价值定位不可能作为核心领域考虑。
产品定位的电梯演讲是什么结构?写一个与你的练习无关例子。
例子1
** 对于 ** 基于RESTful 前后端协作
** 它们想 ** 自动化生成文档,便于前端使用
** 这个 ** 文档生成器
** 是一个 ** 通过对Java 代码注解分析,导出文档的工具
** 它可以 ** 在编译部署时自动生成一个在线的API文档
** 不同于 ** 常用的文档编辑工具
** 我们的工具 ** 可以自动生成和更新API文档
例子2
** 对于 ** 没有时间洗衣服的白领
** 它们想 ** 购买能提供上门收件的洗衣服务
** 这个 ** XXX洗衣助手
** 是一个 ** 在线送洗衣物的APP
** 它可以 ** 提供在线下单,上门收件的服务
** 不同于 ** 常规洗衣店
** 我们的产品 ** 能让顾客足不出户解决洗衣问题
事件和命令相关的知识
事件风暴工作坊的参与者是谁?
- 领域专家
- 用户研究⼈人员
- 业务⽅方案设计⼈人员
- 技术专家
- 测试专家
什么是事件?
- 捕获我们所建模的领域中所发⽣生过的事情,会对系统产生影响的事情。
为什么要使用事件进行分析?
领域专家关⼼心的事件,业务上真实发生的事情,因为会对系统造成印象,直接关系业务逻辑。而产生事件的来源又是广泛的,所以选择事件作为系统分析切入比较合适。
事件的表达方式什么?(举两个好的例子,两个坏的例子)
表达事件最好的方式是,描述系统的某个状态被改变。例如订单已创建。
事件可以触发事件么?被触发的事件要不要贴触发源?为什么?
事件可以触发事件,事件由事件触发可以不贴触发源,因为此时没有触发源介入。
事件的触发源有哪些?
- 另外一个事件
- 系统中的命令
什么是命令?
产生事件的某种行为,例如用户的输入。
为什么需要分析命令?
分析命令可以对事件的触发源进行分析,从而分析出系统中的角色(包括外部系统、定时器等隐含角色)
命令有几种?(各举两个好的例子)
- 用户的动作
- 用户提交表单
- 用户点击链接
- 第三方系统
- 第三方API
- 回调通知
- 定时器
- 计划任务
角色、命令、事件,对微服务有什么意义?
角色、命令、事件用于确定服务划分、服务之间的通信、以及API列表。
滚动屏幕是不是命令?屏幕已滚动是不是事件?我们要不要分析?为什么?
是否是事件取决于是否对系统状态造成改变,如果系统不记录滚动屏幕的行为,意味着滚动屏幕是系统之外的行为。反之,如果系统需要记录用户滚动行为,例如做用户行为分析,则滚动屏幕是一个产生“用户行为已记录”事件的命令。
命令跟微服务哪部分相关?
命令和微服务的API有关。
概念集
什么是聚合
聚合是一组相关领域模型的集合,是⽤来封装业务的不变性。通过定义对象之间清晰的所属关系和边界确保关系紧密的领域模型能够内聚在⼀一起。
为什么要使用聚合?
避免错综复杂的对象关系⽹网的形成,确保业务规 则在领域对象的各个生命周期都得以执⾏:
- 聚合保证边界内的领域对象的业务不不变性
- 聚合内部的领域对象具有一致的生命周期
确定聚合的方式:
- 是否可以被独立访问
- 如果能独立访问就可以当做一个聚合否则作为外部的依赖
什么是聚合根?聚合根的职责是什么?
- 聚合需要和外部交互,每个聚合都需要一个和外部沟通的接口,并且聚合需要一个边界。聚合根充当和外部联系的窗口,外部通过聚合根来进行交互。
例如 Order(聚合根) -> Order item (实体)-> Comment(值对象)
外部修改每个订单项的备注,不应该在直接暴露Order item 和comment,应该Order提供接口完成。
聚合根外界对象能不能直接引用聚合内对象?
不能,破坏聚合的隔离性
聚合内对象能不能持有其他聚合根引用?
可以,但反过来不行。
聚合根对象删除,聚合内相关对象是否可以不删除?
不可以,否则这些对象变成了游离对象,造成数据一致性破坏。
例如删除文章时,文章中的图片资源应该顺带删除。
如何提取领域模型?
通过识别限界上下文来提取领域模型,识别上下文的几个原则:
- 术语相同,含义不同。例如支付过程中的订单和购买行为中的订单不是一样的,需要进一步统一语言
- 概念相同,用法不同。例如进销存中的商品和购物车中的商品实际上是不同的
- 外部系统 明显属于领域之外的或者第三方系统提供的,例如通知、第三方支付等
PS: 领域模型、子域、限界上下文这几个概念不是区分的特别清晰,请问是什么具体的关系呢?
领域模型之间有几种关系?
什么是实体,什么是值对象?有什么区别?
实体的特征
- 具有状态
- 具有ID
- 增删改查 需要持久化
- 可变
- 例如 order
值对象
- 对实体的属性描述
- 不可变
- 例如 Address
值对象和实体可能因为业务转化。
一个聚合就是一个微服务么?
理想情况下是,但是需要结合现实环境。
上下文相关概念
什么是限界上下文?
业务的边界和实现业务的上下文。
寻找限界上下文的四个线索是什么?
- 基于前面输出的聚合和领域模型,判断这些领域模型要解决的业务问题,这些问题是否为同一个问题;
- 如果聚合解决了多个问题,应该对聚合进行拆分,然后划分到不同的上下文中。
PS:剩下两个是什么呢?
上下文映射中是如何确定上下游的?上下游是可以颠倒的么?
在事件风暴和命令风暴中存在时间线和依赖关系,上下文的联系是有方向的。
PS:我理解可以存在互相依赖,拿不太准确。
把两个上下文集成模式有哪些?简单说明一下都是什么,各有什么自己的优点和困境,分别举一个例子。并且解释最后的策略选择矩阵。
- 客户-供应方,单项依赖,例如一些专用接口(分词等)
- 遵奉者 下游跟随上游
- 共享内核 例如使用common lib的方式发布模型
- 开放主机/发布语言 这两种方式强相关的,例如使用Rest约定模型
集成方式的两个维度分别是:
- 团队的沟通能力
- 对相关系统变化的感知能力
耦合程度,团队的沟通成本之间平衡。
上下文和子域有什么样的关系?
理想情况下是一一对应关系。
上下文就是微服务么?
理想状态下上下文、子域、微服务为对应关系,实际上不是,特别是微服务取决于服务的部署方式,受限于环境,可以多个子域部署到一个服务中。