如何保持领域模型的完整性

随着团队的扩张以及各种业务需求,我们单一的模型往往会逐步的扩大到一个不可维护的状态,如:概念的复用导致业务的耦合,这时候我们为了保证领域模型和Ubiquitous Language在概念上一致可能会涉及到模型的拆分,将一个单一的大模型拆分到多个小模型中,同时团队也随着模型打散、重组。让各人员各司其职,这个过程往往成本很高且漫长为了少走弯路我们可以有以下几个方法和原则去遵循

Bounded Context

字面意思限定上下文,就是我们要针对我们的业务划分出不同的边界。每一个边界是一个Bounded Context,一个概念在Bounded Context内部是高度统一的,它只作用于这个Context中。不同的Bounded Context之间应该尽量隔离,如果它们需要通信,那么最好约定好一个协议通过接口方式交互。否则,俩个Bounded Context共用一个模型轻则出现一个有N多同质属性的对象,或者一个属性在俩个Context中定义的不一样的情况。

Continuous Integration

字面理解像是持续集成的意思,当我们确定好Bounded Context,为了不断的迭代、精华模型,团队成员要持续的集成完善Bounded Context。【注意Continuous Integration是指团队中的是在一个Bounded Context中进行的】

注意,为了实现Continuous Integration我们应该

  1. 分布集成,采用可重现的合并/构建技术
  2. 自动化测试套件;【单元测试可满足】
  3. 小范围的集成试错,并且制定一每一次集成的Milestone
  4. 集成中坚持使用Ubiquitous Language

Context Map

当一个大项目出现多个Bounded Context时候我们要规划一个全局的Context Map,并且找到他们的关联,以及关联的交互方式。后面会讲集中Bounded Context的交互方式。

Shared Kernel

最理想的方式,假如俩个模型高度重合我们可用共用一部分基础设施或者底层逻辑。避免一部分重复的工作。比如共用一种数据库、共用一套数据层

Customer/Suppiler Development Team

俩个模型是下游依赖上游的单向依赖关系。下游依赖上游输出,但是上游不需要下游的反馈,如:业务的统计系统,需要上游的日志、数据,上游业务系统却不太需要统计系统的反馈。这时候俩个模型可以采用这种客户/供应商关系

  1. 当下游依赖上游的输出和结果,并且是依赖是单向的
  2. 上游愿意配合下游的工作
  3. 一个boss【个人觉得这个最重要。起码在我司】

Conformist

跟随者模式,加入上游不配合或者整个系统没有人维护了,这时候为了上游的数据能响应下游需求,加入上游模型我们可以复用质量不差,便于使用,我们完全没必要推翻他们,可以选择采用跟随者模式。

使用时候严格遵守上游的Bounded Context可以避免俩个模型之间数据格式的转换

Anticorruption Layer

防腐层【隔离层】,为俩个Bounded Context提供隔离机制。由于上游、下游的Bounded Context无法完全复用,那么数据就需要进行转化,为了防止俩个Context的概念互相渗透,这种转换我们往往放在防腐层进行。

在防腐层我们最长用到的是Adapter和Facade俩种模型,下游的service通过Adpater来兼容调用被上游的服务,Facade在被调用者端隐藏对象数据的组装。防腐层可以部署在下游也可以部署在上游

Separate Way

如果上游的Bounded Context和下游的Bounded Context区别非常大。em…各行其道吧。完全隔离开。

PS:我们审视我们的项目是否有必要把项目集成在一起?他们是否能独立存在?如果能,建议各行其到

Open Host Service

为了减少模型之间的转换工作我们可以为我们的服务提供Api,我想着就是微服务为什么兴起的原因。

总结

个人认为根据Context Map的各Bounded Context的紧密程度来划分:Shared Kernel > Customer/Suppiler Development Team > Conformist>Anticorruption Layer > Separate Way

我们在思考方案时候可以遵循这个原则

另外建议在开发中对于Bounded Context的设计采用减法,程序要保持小规模的持续集成。