实施DDD阅读-策略设计
1. 概念篇
1.1 领域
广义上讲,领域即是一个组织所做的事情以及其中所包含的一切,也是组织的业务范围以及在其中所进行的活动。软件所讨论的领域即是这个组织的领域,应该是清晰明确的。不同的层面或粒度,领域一词承载的内容不同。为了简化问题,避免大泥团这样的架构出现,我们认为领域拆分是必要的,可以帮我们简化问题域,是有好处的。领域不是领域模型。比如电子商务系统中电子商务是我们的领域。
1.2 子域
子域是领域的一部分,领域可以划分为若干个小的逻辑独立子域,从而更好的应对问题的复杂性。子域包括核心子域、支撑子域和通用子域三种类型。子域并不一定要做的很大,子域可以只包含一套算法,只要是独立的、内聚的。在DDD实施时这种简单的子域可以称为一个独立的模块,从核心子域中划分出来,更容易重用及维护。比如电子商务系统中包含订单子域、产品目录子域、发票子域、库存子域、物流子域。
1.2.1 核心子域
核心子域是整个业务领域的核心,是企业业务核心竞争优势,也可以是业务成功的关键因素。比如电子商务系统,订单子域就是核心子域,是整个业务的关键所在。
1.2.2 支撑子域
支撑子域关注业务的非核心方面,它对应的限界上下文可以通过创建或购买来支撑我们的业务。比如电子商务系统中发票子域、物流子域便是支撑子域。
1.2.3 通用子域
如果一个子域被整个业务系统所使用,那么它就是通用子域。比如电子商务系统中库存子域。
1.3 限界上下文
限界上下文指业务语言层面的上下文边界,它是显示的、是充满业务语义的。在一个好的限界上下文中,每一个术语应该只表示一个领域概念,无歧义且唯一。一个限界上下文并不一定包含在一个子域中,一个子域也可以包含多个上下文。对于一个领域中的限界上下文不是孤立存在的,是通过多个限界上下文的协作完成业务。对于限界上下文的识别是关注点分离的明确表象,它可以隔离其它不相关业务、减少干扰噪音,识别隐藏的领域概念。同一个物件在不同上下文中的领域概念是不同的,这些易于混淆的领域概念是理解限界上下文的关键。比如库存,在仓库中无人购买的库存称为积压件;已经被订购即将发货的库存称为即将发送件;被损坏的库存称为无用件。在库存的不同上下文中需要区别对待。
1.4 问题空间
问题空间是领域的一部分,问题空间中考虑的是当前业务所面临的挑战,如库存系统的成本较高问题。对于问题空间的开发将产生新的核心子域,问题空间的子域随着项目的不同而不同,关注着各自不同的业务问题。在我们完成问题空间分析时,我们需要对其进行评估,需要与业务人员(客户)一起确认我们对问题空间的核心子域以及要达成的业务目标的理解,其中包含哪些核心概念,它的支撑子域和通用子域是什么,从而确认相关利益方在目标上达成一致,也即是我们通常在项目启动时所讲的构建业务愿景。
1.5 解决方案空间
解决方案空间讨论的是如何用软件来解决这些业务挑战,它包括一个或多个限界上下文,是一组特定的软件模型。限界上下文在这里有更多的阐释,限界上下文即是一个特定的解决方案,划分限界上下文往往也意味着对于解决问题空间的分析映射和实现。解决方案空间通常会收到现有系统和技术的影响,需要考虑是否重用,资源时间的约束,如何集成,风险控制等。在解决方案空间中,限界上下文是重要的建模工具。
2. 上下文是王道
限界上下文组成解决方案。我们在实施DDD战略设计的时候,应该是从问题空间出发,确认解决方案空间,划分限界上下文,从而识别其中的核心领域模型;并通过问题空间的更新和解决方案的更新/正实时的调整模型及其关系。上下文的划分由问题空间和它要达成的业务目标所决定,与组织文化相关,与stakeholder相关。同一个术语在不同的企业组织、不同的业务范畴它代表的领域概念是不同的,这也是可行的,只要在组织内团队内达成一致。
2.1 限界上下文不只是领域模型
1)领域模型是限界上下文中的主要公民,当前的上下文决定了它所代表的唯一的、具体的业务术语或概念。每个领域模型具有自己的属性和操作,领域模型之间互相交互完成限界上下文的业务。内聚的领域模型是一个好的限界上下文的重要组成。
2)但限界上下文并不仅是领域模型,它同时也包含了那些为领域模型提供交互手段和辅助功能的内容,比如数据库Schema设计等。但如何确认领域模型/组件/服务在上下文的边界内是一个需要解决的问题。
2.2 限界上下文的大小
限界上下文的粒度需要适中。限界上下文需要足够大,以能够表达它所对应的整套通用语言。限界上下文需要清楚包含的核心领域概念,清楚那些不属于通用语言的外部概念。上下文映射可以帮助我们做出相对正确的判断。限界上下文也需要足够小,从而使得它所封装的通用语言和领域对象具有清晰的定义,但也不要基于约束它的范围。限界上下文可以通过分析,由上而下,大粒度到小粒度逐渐分解,直至团队达成一致。
2.3 几点注意
限界上下文首先考虑的一定是领域问题、通用术语。 * 避免从技术层面考虑限界上下文,技术组件不能定义限界上下文。 * 避免以开发任务的分配来拆分限界上下文,这些可能导致错误的上下文建模方式。 一个可以帮助划分限界上下文或者子域的方法是假设这部分从第三方购买,从而思考所带来的变化和合适的划分。
3. 上下文映射
上下文映射关注于解决方案空间中限界上下文之间的集成关系,可以帮助界定和划分与其他系统/模块之间的依赖关系,识别交付风险(如集成瓶颈、组织管理问题等)及其需要应对的方案。
Eric Evans 在DDD种定义了九种产品和组织的集成关系。
3.1 集成关系
协作关系
共享内核
客户方和供应方开发
遵奉者
防腐层(ACL)
开放主机服务(OHS)
发布语言(PL)
另谋他路
大泥球
绘制上下文映射图时需要首先定义上下文之间的集成关系和集成方式,是基于协作的,还是客户供应关系的。在SaaSovation的例子中,用户身份与访问上下文与协作上下文是客户和供应方的关系,身份是协作的上游,提供主机服务;而协作是身份的下游,消费身份提供的服务,并采用防腐层保证内部的稳定性。
4.总结
两个概念:子域与限界上下文。
1)子域是指组织内所做事情的一个独立的部分;子域不会随着系统的替换而发生变化,无论解决方案是什么,我们的问题空间仍然存在。
2)限界上下文是解决问题中的一个独立的具有一组清晰的通过术语的范畴,限界上下文可以跨子域,可以是已有系统,是模块。
一种思考方式:假设替换法
在讨论解决方案空间的概念时经常可以采用的一种思考方式是假设替换法,如果这个限界上下文被替换会出现什么变化?