软件架构的意义
软件架构的意义是什么,有很多不同的理解和争议,这里不想就软件架构的意义给出完整的定义,而是想聊聊其中的一点:软件架构是沟通 (Architecture is communication),关于软件架构的更多意义,建议参考这篇别人的旧文。
为什么软件架构意味着沟通呢?因为软件工程本身是一个组织一群人为了一个问题进行创造性劳动的过程,因为软件工程本身的特点,所以沟通的重要性是软件工程区别于传统工程的一个显著特点。关于这一点,我之前的帖子已经解释过,这里不再展开。
什么样的架构有利于沟通呢?
在回答这个问题之前,我们先来看一张图。
如果汽车设计师通过这张图来向其他人解释汽车是什么的时候,我想除了相关的专家不会有人能够轻易理解每个部件在整个汽车中的用途,以及他们是如何在一起工作的。
为什么呢?在《金字塔原理》这本书里提到,人一次能够理解的思想或者概念的数量是有限的,所以如果需要表述一个复杂的思想时,需要通过金字塔的结构来组织整个表述。回到软件架构来说,其道理是类似的,为了让我们的架构设计更好地让大家理解,可以通过一个金字塔的形式来组织我们的架构设计,事实上我们也是这么做的。
所以下图可能能够让我们更加容易理解一辆车是如何组织的(这张图也来自网络,不完全匹配本文,见谅)
软件架构中的具体问题
从上面的例子以及我们实际的经验来看,金字塔型的结构确实是一个非常有效的沟通组织方式,那具体应用到软件架构来说,有哪些具体的问题和解决思路呢?
什么时候需要拆分?
软件架构设计中经常碰到的一个问题就是,什么时候需要拆分,包括分成不同的模块,应用或者系统?关于这个问题,很难找到一个直接的答案,但是我们可以侧面来回答这个问题,也就是团队组织是否需要拆分。个人的建议是要考虑的是问题的复杂度和人之间的关系,当一个问题的复杂度大到一个小团队(参考亚马逊的two-pizza team理念)都无法承接的时候,我们需要考虑将其拆分成多个系统或应用,当一个问题的复杂度大到一个工程师在日常工作中无法承载的时候,则应该拆分成不同的模块或应用。因为现实中问题的规模本身就是模糊的,所以这里没有明确的量化指标,具体的拆分还需要考虑复杂度以外的因素,这里只是强调一下,拆分的原则是需要首先考察问题的复杂度。
要不要引入抽象层?
关于引入抽象层的时机,需要从两个角度来考虑,一方面是需要放在一起讨论的事物或者概念的数量大于普通人所能接受的范围时(神奇的数字7±2),我们可能需要考虑抽象层。
另外一方面就是当明显不在同一个抽象层面的事物摆在一起讨论的时候,比如说下面就是一个错误的例子:
发动机 车架 底盘 轮胎 示廓灯
一个简单的判断标准就是看看这些事物能否按照同一条规则来分类,并且共同组成高一层的抽象概念,如果不能的话,往往就是我们把不同层面的事物摆到了同一个抽象层面上。
什么时候共享?
共享或者说复用是软件工程师最喜欢的概念之一,但是实际上很多时候我们想复用却复用不了,或者复用本身带来了比较大的成本。复用的关键因素在于对于问题和解决方案适当抽象,具体来说一方面我们需要确保解决问题所需要的能力都能通过抽象接口(interface)展示出来,也就是说接口的能力必须是完整的,同时这个抽象能够屏蔽掉无关的细节,也就是尽可能地简化。
由于实际的问题错综复杂,并且我们在描述问题的时候有很多模糊的名词,所以一个常见的误区在于我们通常会混淆两个看起来类似但是有不同实质的问题,比如汽油发动机和柴油发动机虽然只差了一个字,但是其结构和原理是完全不同的。这个例子虽然很好理解,但是实际工作中我们却还是会因为名字相近就把不同的问题放到一起去考虑,这里就不展开了。
一般来说,当我们能够清楚而精确地定义一个问题的时候,就是一个产品可能被共享的时候。在考虑一个产品是否能被共享的时候,我们不要被问题域的名词所迷惑,一定要从其对应的抽象模型,包括具体的行为方式和特性来确定两个问题的实质是否同一个问题,两个问题能否真正使用同一套模型来描述和解答。
问题的核心和边界
我们的一个常见的做事方式就是求大求全,却没有清晰的关于问题核心和边界的概念,常常突破产品所在的抽象层次,看起来是带来了更多的能力,实质上却是破坏了整个架构的设计,模糊了各个概念的边界。由于潜在使用者无法理解这样的组件对应的问题,同时也担心其潜在的复杂逻辑关系,导致了这样的组件反而很难被复用。
我觉得在软件设计的过程中,我们一定要想清楚问题的核心是什么,边界是什么。为了解决一个问题,我们所需要的最小的抽象模型是什么?在服务化的架构理念里,当我们能够给出一个尽可能简单而有效的服务时,才更有可能在更广阔的场景下使用这个服务。
业务架构和技术架构?
在我看来,需要我们讨论的问题的是业务架构,或者说从服务化(SOA)的角度来说,我们更多地要考虑的是问题域和问题所对应的解决方案。这里所说的业务,不完全是整个公司对外提供的产品,也包括每个服务自身的对其他服务和产品输出的能力。换句话说,当一个团队明确了一个需要解决的问题的时候,这个问题就是就是这个团队的业务,而这个问题的解决方案的模型和表述,就是我们的软件架构本身。
至于我们常常谈到的技术架构,在我看来很多时候是一个比较模糊的概念,很多时候我们的技术架构仅仅是对于中间件和数据库技术的选择,当我们所需要解决的问题以及相应的方案都基本确定的时候,具体技术方案的选择相对来说是争议比较小的部分,这样的技术架构没有太多需要讨论的内容。对于另外一些技术架构,同时包含对于技术栈和系统逻辑关系的描述,后者大多都可以融合到我们的软件(业务)架构设计中去。
因为菜鸟业务的复杂性,现在已经很难有人能够对于所有的组件都有比较深入的了解,而每个业务线的同学都会对自己所在的业务线有更加深刻的理解,所以我建议技术部架构委员会更多地可以关注如下几个问题:
- 如何让同学们给出比较合理的问题模型和相应的系统架构,而非具体某个产品的系统架构
- 处于抽象层次上层的架构,也就是说重点关注和讨论大的系统分工和边界
- 系统和服务复杂度的合理性,包括团队规模的合理性