QCon 北京 - 遗留系统 & 领域模型

Eric Evans - Domain-Driven Design Strategies Dealing with Legacy System

首先从两个耦合关系很大的遗留系统开始,当我们需要增加新功能时,往往涉及到两个遗留系统的更改,那势必会又增加这两个系统之间的耦合关系。

当问题多到一定程度,遗留系统之间藕断丝连的关系层出不穷,每一个新功能的添加都变得像噩梦,便有念头说要不干脆重写整个系统。

假设整个新系统是一个金字塔结构,新功能的添加相当于塔顶部分,跟业务功能关系不大的基础设施则相当于塔底部分,然后中间层是业务逻辑。

我们计划第一年,先完成基础设施功能的实现,因为它跟业务无关,所以遗留系统仍然继续维护;第二年,完成业务逻辑层的实现,这一层,将会慢慢的将旧的遗留系统中的功能模块迁移到新系统中;第三年,添加新功能到塔顶。

看起来很完美,但是到底会发生什么呢?

我们将不得不重新实现很多我们根本就不关注的功能,在实现中间层的过程中,一方便我们需要实现新系统的需要,另一方面,又要满足遗留系统迁移的要求,甚至,当不能很快迁移到新系统时,遗留系统还会有新功能的添加,那么同时还需要添加到新系统中去;

为了实现移植的要求,团队会一直处于旧的系统思维模式下,用老的概念来进行设计,为了在规定时间结束这个"新"系统,可能会出现很多设计上的"迁就",最后当这个新系统终于结束的时候,大家不是说: Awesome! 而变成了: Thanks God,it finally finished. 新系统刚出来就变成了遗留系统,效果可想而知。

重写不行,那重构行不?

我们将两个遗留系统进行重构整合,让新功能的添加能够独立出来,处于两个遗留系统的顶部,这样在添加新功能的时候,就不需要再在每一个遗留系统中去修改。

但这样还是没有解决两个遗留系统耦合性高的问题,仍然会有很多需求会需要对各个遗留系统进行更改,千丝万缕千疮百孔…

那到底该怎么办?

整个系统的战略价值(Strategic Value)到底在哪里?

日后添加的新功能,还有散布在遗留系统的一些核心功能。

并不是所有的大型复杂系统都是被很好的设计的,所以,我们只需要关注这个 Strategic Value ,那么怎么才能只重新构建这些 Strategic Value 呢?

  • domain: A sphere of knowledge or activity.
  • model: A system of abstractions representing selected aspects of the domain.
  • A model is a distilled form of domain knowledge, assumptions, rules and choices.
  • 模型是被提炼的领域知识、假设、规则、和决策。

但是正如盲人摸象那样,每一个人对大象的认知是不同的,也就代表者每一个人建立的领域模型是不一样的,那该如何选择领域模型呢?

这时候就需要引入 Bounded Context(上下文界定):

An operational definition of where a particular model is well-defined and applicable. (Typically a subsystem, or the work owned by a particular team).

即我们不需要认识到最真实的模型,而且也不应该坚持只有一个模型,只要一个领域模型符合 Bounded Context,那么它就是一个好的适用的模型。

接下来,让我们回到构建新系统的问题。

这次基于领域模型来进行新系统的构建,我们不去动遗留系统,而将其视为不同的模型,新增功能(Strategic Value)作为一个新的模型与遗留系统交互。

很明显新的应用有自己的模型和上下文,它们和遗留模型和它的上下文相分离。它们不能被合并、混合或者模糊定义。所以当我们开发大的企业应用时,需要为每一个我们创建的模型定义上下文。

为了隔离新模型和遗留模型,使用 Anticorruption Layer (防崩溃层)。

有如下四个策略来实现新旧模型的交互:

  • Bubble Context

    使用 Anticorruption Layer 来进行新旧系统功能的转换,即所有的新系统依赖于旧系统的功能都需要经过该层进行转换,然后跟旧系统交互。

  • Starting a New Chapter

    新系统独立实现整个功能,有自己的数据中心,不依赖于旧系统,但需要通过 Anticorruption Layer 定期同步数据到旧的系统。

  • Expose a Legacy Asset

    前面两种策略适合于 Strategic Value 全处于新系统时,但有时遗留系统内部也是有我们的 Strategic Value 的。

    这种情形下,可以把 Anticorruption Layer 当做一个 Open-Host Service, 它通过服务机制向新系统暴露旧系统的 Strategic Value 供新系统使用。

  • Starting a New Chapter

    整个系统采用事件驱动方式,修改遗留系统,用来创建事件,然后通过事件翻译和分发,来让新系统使用遗留系统的 Strategic Value。

以上四个策略实现起来难度依次增大,对遗留系统的修改范围依次变多。

结束的时候问了 Eric 一个问题,那就是人是会犯错的,很有可能我选择了一个错误的领域模型,然后依据它采用 Anticorruption Layer 设计了新系统,但随着认知的不断深入,需要更改模型,这个时候,是否意味着以前的新系统也变成了遗留系统,那么在处理这个新系统时候,会出现多层 Anticorruption Layer,怎么办?

他回答: 之前的新系统当然变成了遗留系统,而且这种情形经常会发生的,随着对一个业务领域的不断深入,人对领域模型的认知是会发生变化的,这时,为了解决这个问题,出现多层 Anticorruption Layer 是没问题的。

PPT 点击下载