限界上下文 2021-09-04 程序之旅 暂无评论 647 次阅读 ## 限界上下文 在软件设计中,复杂系统中包含了那么多的场景,每个场景都包含了那么多的邻域对象,并且每个邻域对象中还存在那么多的复杂关系,我们对系统的领域模型该如何设计? ### 问题域和限界上下文 首先,我们应该将整个系统划分成许多相对独立的业务场景,在一个个的业务场景中进行邻域分析与建模,这样的业务场景称之为“问题子域”,简称“子域”。 邻域驱动核心的设计思想--将对软件的分析与设计还原到真实世界中,真实世界的业务与问题叫作“问题域”,业务规则与知识叫“业务邻域知识”。 例如: - 电商网站的“问题域”:人们如何进行在线购物,购物的流程是怎么样的 - 在线订餐系统的“问题域”:人们如何在线订餐,饭店如何在线接单,系统是如何派送骑士去配送的 对于这些问题域,我们需要对其进行分而治之的方式来转换为“问题子域”。例如: - 电商网站--用户选购、下单、支付、物流等多个子域 - 在线订餐系统--用户下单、饭店接单、骑士派送等子域 一个复杂系统的领域设计,是以子域为中心进行领域建模,绘制出一张张的领域模型设计,称之为“限界上下文”(Context Bounds, CB)。 > 限界上下文的设计符合高质量软件设计的单一职责原则,即每个限界上下文中实现的都是软件变化同一个原因的业务。 在用户下单的过程中,用户信息的读取是否也应该在“用户下单”这个限界上下文中实现呢?答案是否定的,因为读取用户信息,不是下单的职责,当用户下单发生变更的时候,用户信息不一定变,用户信息变的时候,用户下单也不一定变,他们是用户下单的两个原因。因此用户信息的操作交给“用户信息管理”限界上下文。像“用户下单”与“用户信息管理”这样的相互关系,我们称之为“上下文地图”(Context Map)--限界上下文之间的相互关系。 > 所谓限界上下文内的高内聚,也就是每个限界上下文内实现的功能都是软件变化的同一个`原因`的代码。因为这个原因的变化才需要修改这个限界上下文,而不是这个原因的变化,就不需要修改这个限界上下文。正因为限界上下文的特性,许多团队就以限界上下文作为`微服务拆分`的原则,即每个限界上下文对应一个微服务。 使用限界上下文作为微服务拆分的原则,作用与好处 - 很好地将每次的需求变更,快速落到某个微服务中变更 - 实现低成本维护与快速交付,快速适应市场变化,提升企业竞争力 ### 限界上下文之间低耦合 > 限界上下文通过限界上下文地图相互调用时,通过接口进行调用 ![上下文地图](https://mufeng-blog.oss-cn-beijing.aliyuncs.com/typecho/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%9C%B0%E5%9B%BE-16307244711222.png) 如上左图所示,模块 A 有用到模块 B ,那么模块 A 就模块 B 存在了耦合,这个时候所有复用模块 A 的地方,都必须有模块 B,否则复用模块 A 就会报错。如果模块 B 依赖 C 与 D,那么模块 A 还需要依赖模块 C 与 D,使用模块 A 的成本就变成特别高昂。 如上右图所示,模块 A 并没有依赖模块 B,但是模块 A 依赖了接口 B\`,模块 B 实现了接口 B\`,这样所有用到模块 A 的地方都不需要依赖模块 B,同理如果模块 A 需要调用模块 F 的,那么模块 F 就需要实现 B\`的接口。这样调用方与被调用方的耦合就被解开。 ![限界上下文低耦合](https://mufeng-blog.oss-cn-beijing.aliyuncs.com/typecho/%E9%99%90%E7%95%8C%E4%B8%8A%E4%B8%8B%E6%96%87%E4%BD%8E%E8%80%A6%E5%90%88-16307261611104.png) ### 微服务的困局 ![错误的微服务拆分](https://mufeng-blog.oss-cn-beijing.aliyuncs.com/typecho/%E9%94%99%E8%AF%AF%E7%9A%84%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%8B%86%E5%88%86-16307261533693.png) 当多个微服务需要读取同一个表时,如上,当商品信息表别修改时,其他微服务都需要进行修改,并且所有的内容都需同时发布。微服务的优势不能发挥出来,使得维护的成本更高。这里有一个关键的问题在于,当多个微服务需要读取一个表时,也就意味着同一个软件变化`原因`,因商品信息而变更的代码,被分散到多个微服务中,当系统因为商品的原因而变化时,代码的修改自然分散到多个微服务,各微服务间不能形成高内聚。 ### 最佳实践是邻域模型 - 从 DDD 开始需求分析、邻域建模,逐渐建立起多个问题子域 - 将问题子域落实到限界上下文,它们之间的关联形成上下文地图 - 各子域落实到微服务贫血或充血模型的设计,从而在微服务之间根据上下文地图形成接口 ![错误的微服务拆分2](https://mufeng-blog.oss-cn-beijing.aliyuncs.com/typecho/%E9%94%99%E8%AF%AF%E7%9A%84%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%8B%86%E5%88%862.png) ### 总结 微服务设计的困局是拆分->拆分的核心是“小而专”“高内聚”->破解微服务困局的关键是 DDD 打赏: 微信, 支付宝 标签: 领域模型, DDD 本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。