Skip to content

6.5 架构的关键因素

什么是架构中重要的事情呢?在和同事、社区的朋友交流时,收集到的一些架构关键因素。

抓大放小

架构是一个非常时髦的词,既不属于以前的详细设计,也不属于概要设计。但是在一些场合下,却不得不设置这样一个岗位,来统筹规划各个模块之间的交互和依赖。

所以架构设计有两个方向。一个是归纳法,找出已经存在的详细业务,然后进行归纳,得出模型、架构设计。另外一个是演绎法,根据业界的模型出发,在现有的业务中进行演绎。有时候在极其复杂的系统中,可能有几百个场景和功能,我们根本不可能提前整理出全部的模型,并对齐抽象。

在这种情况下,架构师不像是一个建筑师,有条件勘测所有的信息,并作出合理的设计,然后进行评审。更多时候更像是一个园丁,将花园规划好后,任由花草生长,当一些花草探出篱笆时进行干预。如果将架构师比喻成园丁是合适的话,那么园丁就需要快速识别出最重要的事,避免夏天到来后花草快速生长来不及修剪。

对于架构师来说,认识到什么重要,比事无巨细的设计更为重要,因为这会让本来可以分配的开发工作挤占原本就不多的决策时间。

对于微服务项目来说,当团队规模非常庞大时,最重要的事情有这么几个:

  • 清晰地定义每个服务的职责,以及相互的依赖关系。
  • 在每个微服务中挑选几个核心模型,建立这些核心模型的关联关系,确保其他的模型都能依附这些模型生长出来。
  • 拓展点,抽象结束后需要通过不同的策略设计拓展点来满足个性化需要。
  • 定义建模、架构设计的原则,以便对各个开发团队的产物进行整合以及评审。

因为准确决策会花非常多的时间,所以决策少量的重要事情,比决策大量的不重要事情更加重要。

架构元素和关系

我们做软件架构设计,设计的主体是架构师,客体是软件,这里的软件往往是一个软件系统。系统意味着存在组成部分,以及通过有机的方式组成到一起,并具备一定的能力。

我们说架构就是定义系统的元素和关系。架构设计中往往最让人混乱的是颗粒度问题。当我们说服务这个词汇时,说的是什么呢?有可能是一个可以单独部署的容器,也就是微服务这个粒度。但是其他人可能理解为,某个代码库中的一个服务类。

设计架构时,需要时刻清醒的知道自己工作在哪个层次。如果是微服务层次,我们可以说,这是在做战略架构设计。微服务是战略架构设计中的元素,微服务之间的调用和依赖关系就是系统元素的关系。

当把微服务打开来看,每个类就成为了元素,进入了战术设计的层次。在领域模型部分,基本的类可以再次组合为聚合,以聚合为战术设计的基本元素。通过定义聚合根的概念来明确战术设计的核心元素,分析出聚合的职责就能作为元素的关系。

建模和架构原则

架构师不必事无巨细的评审细节每项内容,并且也不太好通过偏好来评审产出。如果能整理一些架构设计的原则、规范,以符合原则为依据来进行评审和指导开发就行。

制定技术原则时候,有一些"原则的原则"。

  • 客观类规范需要自动化。在框架上、工具上、流程上做出约束,让团队成员在不经过培训的情况下满足建模原则。
  • 主观类原则需要轻量级。轻量级也就意味不能在细节上过多的约束,而只是一个底线。掌握一份几十页的文档是几乎不可能完成的任务,非自动化的架构原则必须足够精简。
  • 可操作性。不能制定一些不切实际的原则,原则需要能够明确的被判定。比如,"服务间依赖合理"不是一个好的原则,而"领域服务之间不允许出现 API 双向依赖" 就能被识别和判定。

比如,这里选择几条领域模型设计的一些比较清晰的原则:

  • 不允许出现多对多关系,多对多关系造成聚合之间的耦合,应该明确找出中间模型并给予一个合适的名称。
  • 聚合的深度尽量不超过 2 层,最多不超过 3 层。
  • 聚合根不共用实体,如果存在共用实体的情况,可以拆开或者将被共用的实体升级为聚合根。
  • 值对象在持久化时需要将字段展开到所属实体上,不能使用单独的数据库表存储。

这里示例的几条原则可能不会被所有人认可,但是当我们在一个团队中工作时,会降低团队的沟通成本。

拓展点设计

抓大放小的方法之一是找到核心模型,但是过于收敛到核心模型,核心模型的职责就会变重,不利于扩展。

架构师需要抓住核心模型的同时为核心模型设计拓展点,这样架构师负责守护核心模型,并给予一线的开发和技术经理拓展和发挥的空间。

举个例子来说,保险行业往往有两个核心模型:投保单和保单。如果将各种场景都收敛到投保单、保单这两个模型上,这两个模型的内容会非常多。

对于投保单来说,可能有非常多的渠道,对于这些渠道不能直接关联到投保单上。一种设计方法是,抽象出各种各样的投保渠道,这些投保渠道在实现上都是一些策略,这些策略使用到的模型不需要直接关联到核心模型上,让其独立存在即可。

通过拓展点设计有非常多的好处。架构师可以通过拓展点识别到核心模型,并建立核心模型之间的关系,找到系统的核心逻辑;拓展点可以用来研发工作,将不同策略的工作拆分出来,交由不同的开发人员负责,让分工更清晰;当然,显而易见的,拓展点可以支持更多业务,而不必侵入核心模型。

最后一个好处单独拎出来说一下。通过明确拓展策略,可以非常容易的说服业务方(产品经理、BA)克制的设计交互,因为这样可以最大的支持更多业务场景。举个例子,一个餐饮系统,一般有外卖、堂吃两种订单,我们可以设计一个核心模型订单,以及拓展模型外卖、堂吃。如果产品经理需要将其列出在一个列表中,并根据外卖、堂吃的专属字段进行分页搜索,这样就破坏了抽象和拓展策略。当我们能说明白拓展策略时,业务方也能接受一定程度上的取舍和克制了。

如何获得拓展点是一个难题。获得拓展点的前提是找到不变点,也就是一组模型中具有相同内涵的属性。基于此来设计抽象后的模型,如果找不到不变点,也就意味者存在过度设计。

团队契约

9个女人不能在一个月内生孩子,现实是这种要求太多了。架构师的目标是尽可能将团队中的人并行化,这是我们想尽办法拆分系统的重要原因。我们想尽办法拆分系统的重要原因。拆分的目的不是让软件设计的多么美妙,而是丢给你几百人能不能在一起工作不发生冲突,这是极为困难的事。

从另外一种角度上来说,既然人多一起工作就必然会产生浪费,接受浪费也是大型系统架构设计的客观需要。

考虑到了拆,还需要考虑合。拆分的越细,合并就越困难。而合并最大的问题是,每个人的做事方法,和想法是完全不同的。如何清晰简单的制定可行的工作规范和产物才能让系统合并运行,这就是架构师需要思考的另外一个问题。

Released under the MIT License.