《我的架构思想:基本模型、理论与原则》编一

认知层次

p-1

  • L0:机器学习的兴起,最直接的原因是大数据的出现。在大数据出现之前,大量的业务决策过程是所谓“拍脑袋”式的,也就是依靠经验和直觉。虽然数据很早就进入了商业管理的领域,但是时至今日,即使在全球领先的五百强企业当中,很多关键的决策,也只是把数据统计出来,变成图表,然后由“有经验”的管理人员根据数据来“拍脑袋”。

  • L1:当前的机器学习工程师,未必需要深入理解机器学习的数学原理,只要根据一套完善的“套路”,配合类似 R 语言或者 Python 的 scikit-learn、TensorFlow 等工具,就可以开发出一个回归或者分类模型,帮助商业人士决策。

而 L1 认知层次的局限性在于,一旦这个“套路”失效,只停留在这个认知层次的工程师,会束手无策,因为他们并不知道自己使用的方法和套路是怎么来的,自然也无法变通和调试。

  • L2:也就是通过理解“套路”和模型背后的原理,特别是数学原理,进入到方法论的层次。到了这个层次,你才能够在实践中知其然且知其所以然,恢恢乎游刃有余,才能称得上是“高手”

L3:能站在上帝视角来审视自己的学科本身,考虑这门学问的根本问题和长远命运。
L2 的局限性,就在于他们对于自己的这一套做法,还缺乏“反躬自省”的审视。”其有效性的边界在哪里?对什么样的问题可能会失效?

“台湾的高焕堂先生曾说架构的要旨是“以序容易”,我解释成“用规则来包容变化”,高老师说很合他的本意。这里的“易”,指的就是变化。既是变化,那当然是艰难而复杂的了。然而我们通常说一件事易做或另一件事不易做,这里的“易”却都是指简单的意思。所以“易”既是无穷的复杂,也是至极的简单,关键在于如何“容”它。”“知音变而得律,有容则易。”

程序是可被组织的元素,这事实上是对程序的可结构化特性的一个阐释,貌似是说着相同的话。然而如果程序是可被组织的,那么“结构化”其实就只是组织的手法之一。这意味着后者——结构化——只是“程序是什么”的一个解,而绝非唯一解。这就是架构视角的独特处。当它找到一种新的抽象来定义事物时,旧的事物哪怕没有形式与内容上的变化,却在思维框架中有了新的位置、新的理解,以及新的矛盾与冲突。而所谓问题,就来自这些外在视角的变化和内在冲突的产生。架构的目标最终就是直指这些问题,而非解决一个切实的需求,例如写一个程序。

架构本质上是一个映像。洞见映像背后的事实,就如同从镜子去观照现实,知道镜子是一层,知道镜子中的映像是第二层,知道镜子映像所现的实体是第三层。而至第四层时,还要看得到那实体周围的背景,这是实体之为实体所必须的依托,如绿叶之于红花。再深入到第五层,你得知道背景之外不可见的那些影影绰绰的事实,它们是环境中的残片和推想,它们不可确知而又影响着你在镜子中看见的那个主体。再至第六层……

如此层层渐近,才是真正的“镜之用在鉴”,才是“鉴”这一行为的本意。然而一旦你触及到“鉴作为行为的事实存在”,那么你就看到了镜子一侧的自我,进而看到自我之见,看到由自我、镜鉴和自我之见等等所构成的整个系统,这个系统被称为“观察”。当然,在这整个“被称之观察系统”的系统之外,还要有光。否则一切所谓事实都将湮灭,即便存在,亦无可证实,无可证伪。

架构师的思维

“着眼于高远”,便是架构师的基本修养,而几乎所有的架构思维,都从这修养中来。就架构来说,“高”就是指空间上的可拓展性,即系统的复杂性是否可以通过组成部件的增减来解决;“远”就是指时间上的可持续性,即系统的规模是否可以划分为多个时间阶段来实施。以软件架构为例,在讨论系统——这一架构目标的属性时,架构师可能关注的话题包括性能、可用性、可靠性等十余种,我们可以通过高、远两个维度的思考将它们大致地分类:

p-2

架构师在思维过程中使用的工具

p-3

“系统,是对架构师所面对对象的基本抽象。架构师对系统的认识过程、方法与结果,决定了他如何理性地架构之。”

认识系统不是架构系统。认识系统将致力于将系统中的核心概念抽象出来,将核心逻辑梳理出来,将核心问题(关系、依赖与冲突)揭示出来。但是架构系统的目的正好在于通过对概念与逻辑的映射来消弥这些核心问题,使核心问题对其外在(例如用户可见的产品)不构成明显的影响。

架构是一个过程。既然是过程,必然有起始与终的。

1.了解系统的过程

感受一个系统的事实

如同新闻,以体察之,感同身受

系统是一种认知,而非分析的结果

我们作为“计算机专业人士”的日子太久了,我们对太多的事物有了理性的认识,而缺乏感性的认识。正因为我们忘却了这种“感同身受”地了解事物的方式,所以我们对这些事物的认识流于浅表,流于那些有数字个数、形体大小、边界棱角或者演进逻辑的判断推理当中。我们忘了一个“系统”是可以去知道、了解、感知,进而感受的。

我们把对系统的观见与解说当成一种理论,这种理论称为“需求分析”。而我们在一定程度上忘记了,我们所谓之“系统”,并不仅仅是模块的组成,更是一种外界——之于这个系统——的认知。

认知理论中的知识:知得与识得

我们获取知识有两种手段,是所谓“知得”与“识得”。

当我们知道张三,却不知道它的形貌时,是知得,大多数图书馆知识是知得的;当我们亲触这个事物 3,却不知道它是什么时,是识得,大多数野外考察知识是识得的。

p-4

从动词角度上来说,认识是识得的具体方法之一。认,是指记认;识,是指辨识。

作为实践者,我们大多数时候是在讨论“某种记认的方法”,而未能追究:在认知理论上,这种记认的可靠性及其依赖的条件。而忽略这一点,就会产生一些似是而非的方法,例如失效的刻舟求剑。但是,失效并不是无法容忍的,例如 HASH 应用中存在的命中率问题。所以记认并不是准确无误的方法,实践中只是在寻求这种方法的背景限制并进一步控制误差而已。

辨识的一个基本含义在于分辨出差异。如果找不到差异,那么所有的事物也就混沌一物,无从辨识,也无从获得它的知识了。具体来说,辨识也可以分成两种方法:其一是识别,其二是分别。

识别依赖于我们对事实的直观了解,在一定程度上是与我们的感觉器官相关的,例如听见的、看见的或者闻见的等。然而识别是不可靠的。它首先取决于生理机能本身的可靠性。其次它还取决于既识的持续可靠性。“基于识别所构建的既有知识”为既识,称基于既识而识别为持续性。例如,某人此前听过猿啼(并确认正确),当他再听到某种啼声时,识别为“这是猿啼”。但后者并不一定是持续正确的。

分别则相对复杂一些,它建立于一个观察的角度、切面,或者依赖于某种参照。通常,“数”这一抽象,是我们能加以分别所依赖的核心概念。例如,核桃的个体与群体,以及火车的速度,都是我们对观察对象先进行数值化,再加以比较,最后得到的知识。

分别是可靠的吗?答案仍然是否定的,千人千面是一种理想状态,现实往往是一人千面。

分别的问题在于比较所需的角度与背景不同,以及不同人对于抽象概念的理解有异——如你所见的,基于“数的值”的分别往往准确一些,是因为人们对于“数”这一抽象有着大抵相同的理解。

尝试一个“建立知识”的过程

我们从一个系统中获得的知识因人、因方法而不同;既便是相同的方法,由于其实施者的不同以及方法(本质中存在的)误差,也会不同。这就是作为架构师,任何两个人都不可能得到相同的架构结果的根本原因。所有的最终架构都是在实施过程中的调和,以及某些决策者、决策机构的“决定”。

建立知识以陈述现实系统”是不足以架构系统的

归纳(概念)、梳理(关系)、推演(逻辑)这些架构活动所需要的,都是较高层次上的思维方法。

现实中,基于所面对的计算机系统,我们大多数的系统抽象与建模过程中都会用到“分别”这一认知方法。比如说,我们将已知需求规划为条目,然后分门别类,进而整理出子系统、模块、服务,以及规划出服务器、集群等的方案。对系统中的组成、要件、关系等加以分别,是上述这些活动的基点。

2.知识的构建

观察者的背景差异带来了更多不同的正确映像

识别与分别对于了解事物的内在特性来说,都只是辅助手段。而这就是能够建立一个系统的物理模型(组成/结构模型),而难于建立它的逻辑模型的根本原因。

事实上,我们在架构活动中进行的归纳(概念)、梳理(关系)、推演(逻辑),这些活动的核心基础在于图中的“知得”而非“识得”。

p-5

其一,我们是否有能力得到一个物理模型;其二,我们得到上述物理模型的过程是否仅仅依赖“识得”。然而,这两个问题的答案都是否定的。首先,我们可能得到很多种物理模型,这些模型映射了现实系统的不同视角。真正的原因是:你难于一以贯之地采用特定视角去观察现实系统,并且你所了解的系统也会动态地以种种角度呈现给你。

现实中的系统总是自洽的——系统中的角色总是在制造冲突的同时消弭着冲突,这就是所谓的生态,亦或“它们”之所以表现为一个(活着的、动态的)系统的内在能量。

但计算机系统只能描述其中的一部分(事实上这也意味着计算机系统只能解决动态的现实系统中的部分问题),这一部分必须首先成为“我们”——作为观察者的认识,而后才会表达为软硬件系统中的“可计算的”映像。最终,我们事实是通过对“映像”的运算,来还原现实系统中的某些侧面,以达到我们的目的——替代之、推演之,并作为其他可计算系统的组成部分。

所以事实上我们可能得到多个物理模型,它们在表面上看起来都是现实系统的“正确映像”,但其内在是各自不同的。

这种差异表现了不同的“架构意图

当我们试图去表达现实系统的“一个映像”时,我们总是存有特定的意图。这种“架构上的意图”决定了我们的观察视角,也决定了我们之后表达的结果。

抽象概念与模型是展示架构意图的方式之一

如果这是某一个特定类型的办公室成员使用的系统,那么它适宜实现为一个工作系统,用来重现某种特定工作的规则与流程;如果这是一个混合的、由不同成员及其工作需求交织而成的系统,那么这个系统(的本身)必然需要某种东西来使自身规则化。

也就是说,“管理”不是现实系统的意图,而是映射这一系统到计算环境时的一个需求。我们必须确定:如果这一需求来自于现实系统,那么它是原始需求;如果它来自于上述的这个软件系统本身,那么它首先是设计者的意图,其次才是对现实系统的反映。

这是一个典型的因果问题:究竟是现实产生了意图,还是先有了意图再去参考现实。我们强调这一细节的原因于:如果是前者,那么控制这一意图(以这里的例子来说,是指“管理”这一行为)的意义在于“控制原始需求”;如果是后者,那么控制它的意义在于“控制设计欲望”。

一旦我们确认这只是一个意图,并且这一意图的核心仅仅是“规则化”那些需求与需求的用户对象,我们就需要更深层次地设定“被规则化的”这个系统(本身)。它将会是:

  • 与现实系统看起来类似的
  • 具有同等的组织容量的
  • 基本符合现实系统的运作逻辑的
    一个软件系统。

p-6

现实系统中,并没有任何需求方来提出这些设定,例如经营角色会说“我们需要一个饼状图”,营销角色会说“我们每周至少发布一次营销活动”,但是他们都不会说“你的系统中需要这样有着管理层次关系的两个角色”。

系统的识得,是在架构意图的逐步清晰中渐行渐显的

意图,是“识得”的核心,即“你想要什么”决定了系统如何构画,而不仅仅是对现实系统的复制。

意图是架构真正的灵魂。架构活动只是将这种意图表达在架构产出中,并阐述这一意图的合理性;如何得到或形成意图才是架构的精髓,其本质是通过抽象过程,对既有系统的再认识与再创造。简单地说,如果架构师没有意图,那么系统只是目标系统的某一时间上的静态映像 5;而架构师如果有意图,那么系统也就有了灵魂,就能跟随目标系统的实际需求的发展而演化,或至少为这种演化留备了可能。

这存在两个条件:其一,它首先必须是能够被规则化的,这是主要条件;其二,作为附加收益,规则化也可以为其他系统构件带来便利。对这两个条件的思考是架构过程中的一种权衡,即从“想要什么”到“能要什么”的一个过渡。这个过程中,“控制架构欲望”是一种关键素质。而这一素质的源起与核心,是架构师对自身职责的不断的、反复地省思,即“想要什么”应当能决定一个系统在时间与空间两个方面的特性,而不是(仅仅)出于客户需求或自我喜好。

组织机构表达的“人与人的授权”7 以及“被授权者是可以行使系统行为的角色”这两点是可以被规则化的。这很明显。但是它能带来哪些便利呢?表 2 是一个简要的考察。

p-7

在这些考量中最重要的是“概念完整性”,它决定了整个系统的核心逻辑,以及描述架构、功能与内部关系的一般方法。如果一个架构设定没有概念完整性方面的必要,通常它的价值收益就会偏小、偏局部,或者可备选。

最后需要补充的是:这样完备地考察通常是不必要的。这是因为,其一,很少有类似授权这样的架构意图,是能够影响到系统全局并在各考察点上都有相对平衡的重要性的;其二,架构意图通常是反向论证的,即“它不与哪些考察点冲突”;其三,核心架构意图通常是明显的、一贯的以及关键的,因此它的影响面也就巨大,这意味着多个这样的意图并存时将是轻重缓急的问题,而并不是是非取舍问题;其四,如上的轻重缓急是一时的选择,可能会随着所架构的系统——或者说项目——的推进而有变化,这既说明了多种意图的必然性,也说明了多种意图间冲突的根源,亦即是需求的内容与焦点会随时间与空间变化。

最关键的架构意图是架构师对上述第四个因素的推定,而并非依赖当前的、静止的需求。这种推定的合理性是建立在一个非常完整、缜密、基于抽象概念的逻辑推理基础上的,其背景多数已经超出了“软件系统”本身。

知得,始于抽象概念的构建之后

“知得”是一个由抽象概念开始的思考过程。在我们的架构活动中,我强调这是一个由“架构意图”驱动的抽象活动。但这并非惟只的方向,并且可能是一个本末倒置的方向。这里需要强调两点,一是我们并没有完整地讨论“架构意图”的由来 9,二是“本末倒置”并非是一件坏事。

从经典的架构与设计的法则来看,是“需求决定架构及设计”,这种需求通常是以现实系统为核心的。这很合理,毕竟从上述的分析来看,现实系统才是系统的本体,系统只是现实系统的一个侧相,而“架构意图”只不过是由架构师对系统之所用的理解。我们一旦强调由所用来推动架构过程,而忽略了本体的真实与侧相的含义,那么往往就会被指为本末倒置。

我们可以找到这样两个不同的架构:它映射同一系统,由不同的架构师来实现。当我们对这样两个架构作分析时,一定可以找到一些相同的部分。这些内容大体来自于由需求驱动的架构方法,它们是架构师对需求的正确描述、复制与映射。如果这些描述、复制与映射中存在了差异,在这两个或更多的架构师之间是可以调和的,因为这仅仅是对一些真实可见、可以反复而又唯只陈述的需求的不同看法,它可以论证、分解、削弱或搁置,无论如何,它们不会成为两个架构中最核心与典型的差别。

我们也必然会找到一些不同的部分。(除了上述的差别之外,)不同的部分必然来自于架构意图的差别,是明显的主观认识,带有很强的目的性。

“识别架构意图”的核心理论与方法

架构意图需承架构的定义而来,它首先必是“经营角色对方向的设定”在系统上的体现。若架构意图不体现方向,则它将只是局部的、边角的一些架构决策或意图。架构师的核心价值,在于通过架构意图来将“方向设定”映射为“规模与细节”。其中,“规模”表现为架构的边界/范围,“细节”表现为架构部件的联接关系/联接件。

对于架构意图的识别,有三个入手的角度。这三个角度仍是“规模与细节”相关的,其一,是系统的脉络;其二,是系统的组织;其三,是系统组织间的关系。如果一个意图表现了架构师对系统上述三个方面的理解,则该意图应当视为架构意图。

架构意图中最重要的是系统的脉络,其整体动向是本质性的需求,其内在动律是上述需求的表现与表达方式 23。总体来说,任何一个架构意图的形成都是对三个“入手角度”整体的反复考量进而形成的一个最终认识,而决非其单一方面的阐述。

3.最初的事实

真相是相,而不是真

所谓“事实”的形成,与事实本身看起来没什么关系,而仅仅在于观察者的主观判断。这看起来相当地可笑:“科学”总是依赖客观事实,但我们对客观事实的认识本身就是发自主观的——从思维的角度上来讲,如果“毫无主观判断”,那么我们也就连任何概念都无法形成。

真正完整而科学的思维方法是将“概念、论证、应用”三者合而为一的:单独地提出概念确实是主观的,科学之谓科学,在于通过后面的两种行为使概念符合逻辑论证与现实实证。

质疑那些主观判断,是系统架构思维中的第一步。

如何推翻那些最初设定的“事实”?

我们谈到过系统的脉络在架构意图中最为重要,它包括两个部分,即内在动律与整体动向。通常,前者是无可争辩的事实,后者则是主观判断或客户战略。

架构不是为客户设定战略,而是服从客户设定的战略。如果客户没有形成战略,那么架构也就只能依据内在动律来主观判断整体动向。如前所论,这种主观判断是依赖对系统的分析而非对战略的假定的,并且也主要用于描述系统的发展方向,而非系统的客户——企业或领域的发展方向。

所以在架构意图上中对整体动向的考虑主要是三点:依赖、复杂性与持续价值。这三方面的问题都可以从战略设定中去寻求最终答案;如果战略不清晰,则也可以从上述的一般过程中去得到一些(阶段性的、可维护系统自身的发展所需的)设定。

与其他工程活动一样,架构工作也是渐进的,并不是一开始就准确无误。因而架构思维中需要不断反思与回顾,而架构活动也将是持续与迭代的。

仰首者瞻,凝神者瞩

战略与方向,是存在本质性的不同的。方向只表达动向,而战略其实是已经决策的动作,或对其行动步骤的规划 7。对于架构师来说,无法决定的其实是客户的战略决策,但对于客户的方向是可以有自己的判断的。

找到问题也就等于找到了解

在既不存在所谓事实(因而也难有可信的主观判断),又没有所谓战略时,我们是可以藉由前瞻方向来形成架构意图的。而另一方面,我们也可以尝试回溯问题。

我们的软件开发活动向来是从对需求的分析开始的,经过设计、开发等过程,最后交付和维护。这一过程是如此的自然,因而我们将它从历史的开发活动中“识别”出来之后,立即被看成是软件工程作为一个成熟概念的标志。

什么是问题?问题有两个形态:其一,若系统存在某种“一般过程”,则阻碍这个一般过程的,必然是核心问题;其二,若系统存在一个确定的观察者,则所谓问题,就是这个观察者的期望与现实之间的差异。换作精炼一点的描述:
“所谓问题,要么是系统与其要素之间的矛盾,要么是观察与其预期之间的矛盾。”

我们在系统中引入了一般过程与观察者,前者是“导致问题”的内因,后者则是其外因。系统的不变性,一般来说是由前者决定的,所谓平衡,即是在这个一般过程的要素之间的、时间与空间上的权衡;系统的变化往往是后者导致的,亦即观察者——例如经营角色或主管——对于系统的期望缺乏一贯性。

反思那些事实与问题

在此前的讨论中,除了对基本的事实与真相的识别之外,大概涉及三种思维方法:设定、试探和归纳。而本质上来说,这三种思维的过程也是模型与概念抽取的过程。由此所得的,是一个可以用来作为基础并进一步讨论的现实系统的映像:软件系统的架构。