1.5 使用敏捷原则开发架构

看起来,架构和敏捷开发方法是一种对抗的关系,围绕这个主题有许多不正确的理念。为了在以敏捷的方式开发产品的同时仍然关心它的架构,你应该遵循一些简单的原则。

本质上,敏捷性是迭代式和增量式的。这意味着在敏捷的架构方法中,不能选择一个大的前期设计。相反,应该提出一个小的、但仍然合理的前期设计。最好的情况是,使用决策日志说清楚每个决策的依据。这样,如果产品愿景发生了变化,架构就可以随之演进。为了支持频繁的版本发布,前期设计方案应该逐步更新。以这种方式设计的架构被称为演进式架构。

管理架构并不意味着要保留大量的文档。事实上,文档应该只涵盖必要的内容,这样就更容易保持它的最新状态。它应该很简单,并且只涵盖与系统相关的内容。

还有一个不正确的理念,它认为架构师都是对的,是最终决策者。在敏捷环境中,是团队在做决策。不过话虽如此,相关方对决策过程的贡献也是至关重要的——毕竟,他们的观点决定了解决方案的最终样子。

架构师仍然是开发团队的一员,因为他们经常会带来强大的技术专业知识和丰富的经验。他们应该参与每次迭代之前进行的评估和计划所需的架构更改。

为了让团队保持敏捷性,应该考虑有效的工作方法,并且只考虑重要的事情。实现这些目标的一种好方法是使用领域驱动设计。

领域驱动设计

领域驱动设计(Domain-Driven Design,DDD)是Eric Evans在他的同名书中介绍的一个术语。从本质上讲,领域驱动设计关注的是如何改善业务和工程之间的沟通,让开发人员关注领域模型。基于这个模型的实现通常会使设计更容易理解,并随着模型的变化一起发展。

领域驱动设计和敏捷有什么关系?我们回顾一下《敏捷宣言》:

个体和互动高于流程和工具

工作软件高于详尽的文档

客户合作高于合同谈判

响应变化高于遵循计划

——敏捷宣言

为了做出正确的设计决策,必须首先了解该领域。要做到这一点,需要经常与开发人员交谈,并鼓励开发团队拉近与业务人员之间的距离。代码中的概念应该以通用语言中的词条命名。它应该是业务专家术语和技术专家术语的共同部分。使用双方有不同理解的术语可能会导致无数的误解,从而导致业务逻辑实现中存在缺陷和难以察觉的bug。小心地命名并使用双方约定的术语,项目可以避免很多麻烦。让业务分析师或其他业务领域专家加入团队可以提供很大的帮助。

如果要建模的是更大的系统,那么可能很难让所有的术语对不同的团队而言都具有相同的意思。这是因为每个团队都有自己的上下文。领域驱动设计建议使用有界上下文(bounded context)来处理这个问题。如果要建模的是电子商务系统,你可能想要从购物场景来理解术语,但仔细观察,你可能会发现负责库存、物流和会计的各个团队实际上都有自己的模型和术语。

这些都是电子商务领域的不同子领域。理想情况下,每个都可以映射到自己的有界上下文——系统中具有自己的词汇表的部分。当将解决方案分解成更小的模块时,明确设置这种上下文的边界是很重要的。类似地,每个模块都有明确的职责,都有自己的数据库模式和自己的代码库。为了帮助大型系统的各团队之间进行沟通,可能需要引入一个上下文映射,以显示不同上下文的术语如何相互关联,如图1.1所示。

上面讨论了一些重要的项目管理主题,接下来我们切换到更多的技术主题。

图1.1 两个具有匹配项的有界上下文(图片来自Martin Fowler关于DDD的一篇文章,见https://martinfowler.com/bliki/BoundedContext.html)