关于系统的理解
1.1 系统的概述
随着人类社会的发展,人们面对越来越多的规模巨大、关系复杂、参数众多地复杂问题,这些问题的复杂度已经远远超出人类的理解能力,系统论就是为了分析和解决这些问题而生。我们平时接触的计算机系统包括软件系统,本质上属于系统论的一个范畴。系统论是一门独立的学科,经历了多年的发展已经形成了体系化的理论。系统论里的一些原则、理论、方法同样适用于计算机系统,计算机系统里遇到的复杂性问题在系统论里肯定会有原则性的指导。相信前人肯定比我们聪明,我们遇到的问题,前人肯定也遇到过,只不过以另外一种形式呈现。多年的互联网从业经验很容易让我们拘泥于互联网软件系统,这样很容易忽略更一般性的规律和原理。
所以,把互联网软件系统放到软件系统里看,把软件系统放到系统论里看。
从计算机系统出来,进入系统论的层面,再回到计算机系统。这种思维的切换,仿佛上帝视角与人间视角的来回切换。
关于系统定义:系统由相互作用和相互依赖的若干组成部分结合成的、具有特定功能的有机整体。系统论强调整体与局部、局部与局部、系统本身与外部环境之间互为依存、相互影响和制约的关系。
系统论要求:把事物或者现象当作系统来研究,并用数学模型去描述和确定系统的结构和行为。系统的思考,区别于系统化的思考,系统的思考是要求我们把事情当做一各个个的系统来看。
系统的整体不是系统的部分之和,系统的整体一定大于系统的部分之和。一个系统能支撑的能力超越于系统组成之和。例如汽车由轮子、发动机、车架组成。汽车都能行驶,但是轮子、发动机、车架都不能行驶。
1.2 系统三大基本特征
目的性:任何系统都有一定的目的。
这里可以理解为业务系统的边界。我们的系统是为了做什么事而设立的?能做什么事?不能做什么事?
动态性:动态性说明系统会发展。
放到我们的业务系统上来说,就是会演进,会向前动态发展。系统内部会随着时间而变化,系统与外部的交互关系也会随着时间而改变。
有序性:任何系统本质上都是有序的,如果不是,说明我们对系统的描述还不够深刻。
如果我们的业务系统仍然很乱,很杂,那说明我们还没有找到系统的深层次的结构,复杂是因为我们掌握不够。
1.3 系统思维的四层境界
认识系统:认识并了解系统的形式与功能、结构与关系。
预测系统:当系统发生某个事件时,能够根据已有知识对系统的行为做出预测。
决策系统:对系统足够了解,拥有充足的依据,可以干预系统,对系统进行认定、分析、权衡,最终做出决策。
组装系统:系统思维的最高境界,可以根据系统的部件重组一套系统。
系统思维的方法论:
通过抽象思维识别出系统中的实体并用概念模型表达。
通过整体思维对关键问题进行分析、归纳,筛选出恰当的实体作为系统的组装部件。
1.4 系统的分类
系统的分类有很多,按照不同的维度可以划分不同的系统,例如按照是否人工可以分为人工系统、自然系统、社会系统等。
这里简要讲一下两个系统,决定论系统,演化系统。
决定论系统:有明确的因果关系,掌握系统内部规律就可以做出明确的判定。机械系统、软件系统等均属于这个范畴。
例如飞机、汽车等只要掌握对应的物理原理,就能够让飞机飞行,让汽车在马路上奔驰。
演化系统:更多的是相关性,因果关系不明确或者难以理清,其难度是深不可测。例如人类的免疫系统,医学上虽然知道免疫系统,但是仍然难以理清其原理。人类的大脑,自然界中的蚁群系统,自然界的生态平衡系统等。
对于不同的系统,有不同的方法论,处理的策略也不一样。
系统论是一门科学,也是一门哲学,有兴趣可以深入研究,这里只是蜻蜓点水。
02
关于架构的理解
“把桌子放在房间里看,把房间放在院子里看,把院子放在城市规划里看。”
2.1 什么是架构
架构,是对系统的描述。
维基百科的定义是:软件架构是有关软件整体结构与组件的抽象描述,用于指导大型软件系统各个方面的设计。
系统的三大特征表现在架构上就是:横向可并列,纵向可推导,整体可演进。
物理学的熵增定律表明孤立系统总是趋向于熵增的方向发展。在软件系统里同样适用,只不过是以复杂度的增加表现的。
互联网软件系统总是朝着复杂度增加的方向发展。所以架构的第一目的是控制复杂,使系统朝着可控的方向发展。
2.2 什么是好的架构图
简洁抽象:好的架构图一定是简洁的,表现上简洁有力,能够一眼看上去就经纬分明。有一定的抽象度的,如果一个架构图存在各种飞线环线,那一定是抽象的不够。抽象才有意义,架构里如果存在各种细节,那就是堆砌。
可解释:好的架构图一定能够用来解释当前系统的现状和行为。
指导行动:好的架构图一定是可以指导行为的,指导行动才是架构图的最大价值。能够预测未来,指导行动。对于某个领域架构图,根据架构图都不知道把某个模块放哪里,那就是失败的。好的架构图应该是对于一个没有经验的人,都能根据架构来做模块划分。
可进化:对应于系统的动态性,架构也会随着时间而进化的。不能进化的架构就像花瓶,看着很美,一碰就碎。
2.3 架构图
对架构的呈现业界已经存在不同的框架。有4+1视图、C4 模型、TOGAF 提出的企业架构模型等。不管哪种模型,其核心思想都是从不同的维度对软件架构进行描述。下面着重从这几个方面来简述。
2.3.1 4+1模式
4+1视图由 Philippe Kruchten 提出的对软件工程逻辑架构的描述,目前已经成为事实上的软件结构标准,分别以终端使用者、开发者、系统工程师、软件经理等不同的视角对软件进行描述。如下图所示:
逻辑视图(Logic View):终端使用者的视角,从功能角度来描述不同功能组件的层次关系。
开发视图(Development View):开发者视角下,从实现层面描述不同代码的包、类、库的构成关系。
过程视图(Process View):不同组件之间的行为关系,通常以时序图的形式来表示,有一定的时序延展性。
物理视图(Physical View):部署视图,系统所依托的物理视图。
场景视图(Scenarios):系统所涉及的不同对象之间的关系。通常以用例图的形式来呈现。
基于这5个视角,可以衍生出5种架构模型。场景、功能、实现、过程、部署,一层层的抽象。
4+1架构视图,构建了一个观察了解系统框架。它告诉我们可以从逻辑视图、开发视图、过程视图、物理视图、场景视图这几个层面来对系统进行描述、观察、理解。对于一个系统,这5个视角已经是很完备了。值得注意的是4+1更大的价值是提供了一套分析系统的框架,实际上怎么呈现不同的团队可能有不同的形式。对于一个系统从不同的视角看会得到不同的理解,横看成岭侧成峰。
2.3.2 C4模型
C4 模型是由 Simon Brown 在2006年至2011年之间创建,在4+1模型的基础上建立( https://c4model.com/ ),实际上就是以下4个单词的缩写:
上下文 Context:描述的系统与周边系统、人的关系。重点是该系统与外界的关系。这里的外界包含人、以及其他的系统。
容器 Containers:容器是一个功能的单位,是从技术层面来描述,可以是一个服务,也可以是一个技术组件或者一个功能模块。例如一个基金系统会包含交易服务、订单服务、商品服务等。
组件 Components:组件是容器的的组成,组件是对容器的放大,例如商品服务里包含 sku 管理、行情数据、衍生指标等。
代码 Code:这一层次是代码级别,包含接口、类、对象的继承、组合、包含等。
该模型是对一个系统从宏观到微观逐级展开来描述,犹如拿着放大镜从太空看地球一样。
第一层看到的是地球与其星球的环绕、第二层是看到地球上的山川海河,第三层看到的是不同的国家城市,第四层看到的是不同的房子家庭。
C4 模型基于4+1模型,但是也有些差异。如果说4+1重点是横看成岭侧成峰。那 C4 模型则是一窥到底的放大镜。
C4 模型告诉我们,不同抽象层次的关注点、挑战点、问题域都是不同的,站在不同的层次就要思考对应的事情。
关注点一旦与该层次不匹配就会出现逻辑错乱问题。能分清楚问题域在何种层次其实已经把问题解决一大半了。
有时候,在低层次很难解的问题,上升一个层次就迎刃而解了。
有时候,在高层次看不清的问题, 降低一个层次就一目了然了。
高层次是低一层的抽象,低层次是高一层的具化。
高手应该是能够识别不同的抽象层次,并且可以游刃有余地在不同抽象层次之间穿梭。
处于高层次时不应该被低层次的具体牵绊,处于低层次的时候也不应该好高骛远。
2.3.3 TOGAF-4A 架构
业务架构:业务战略,治理,组织和关键业务流程。从企业视角来看,重在价值、信息、协作,关联多部门。
应用架构:要部署的各个应用程序的蓝图,其交互以及与组织核心业务流程的关系。
数据架构:一个组织的逻辑和物理数据资产和数据管理资源的结构。
技术架构:支持部署业务,数据和应用程序服务所需的逻辑软件和硬件功能。这包括IT基础设施,中间件,网络,通信,处理和标准。
TOGAF 认为架构的目的是为了帮助企业实现如下能力:
异构到同构(塑造同构 IT)、事后到事先(塑造规划 IT)、离散到统一(塑造统一 IT)、无序到有序(塑造有序 IT)
2.3.4 实际模型-互联网模型
实际上,相对于传统的软件系统,互联网行业发展比较快,业务存活周期比较短,就形成了互联网行业特定的架构描述方式。更多是以业务架构、技术架构、部署架构三种形式呈现。
业务架构:从业务角度描述系统承载的功能集合、领域边界、各组成部分的逻辑关系。区别于技术架构,业务架构图里避免出现技术类的术语,如 DB、MySQL、CMQ、同步、异步、并发等。
技术架构:从技术角度描述系统各组成部件之间的交互关系,技术架构体现的要具有技术特色,例如同步、异步、消息等。
部署架构:从物理角度描述系统的部署分布。
2.4 微服务的理解
软件架构归根结底无非两种模式:从技术层面和业务功能层面来设计。在理解这两个之前先区分一下技术语言和业务语言:
技术语言:是实现层面的。如 DB、MySQL、查询、超时、读写分离、快慢分离、逻辑层、缓存、创建订单、同步、异步、多线程、多进程。
业务语言:是功能层面的。如买入、取出、基金信息、行情、基金详情、资产、产品列表、持仓列表、申购列表、赎回列表。
技术人员要做的是摆脱技术语言体系,走进业务体系,不能被技术语言限制住。从本质上来说技术是为了业务服务的,所以理解业务第一,技术第二。对业务有了深刻的理解,再转过去用技术来实现业务。最好的实践就是在业务代码中看不到技术词汇,只有业务。
微服务最早由martinfowler提出,定义如下:
“In short, the microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.” --- https://www.martinfowler.com/architecture/
说一下我的理解,微服务不是小服务,如果只是因为规模小,那直接叫小服务即可,更准确的叫法是:小而完整的服务,这里的小是指体积,完整是指能够提供完整的业务能力。微服务是一种理念,其表达的是用一个服务来表达一个实体相关的所有行为,某个实体与外部的所有联系均通过该服务来发生。区别于以往按照技术功能划分的服务,ao 做逻辑层,dao 做存储层,vo 做展示层。一个实体的行为要通过 vo、ao、dao 三个服务的关联才能表达出来。而微服务是纯粹从业务语义层面出发,只需要一个服务,对外的表示只有一个。类似于一个国家,虽然小,但是有自己的法律、武装、税收等。微服务拥有自己的逻辑、存储、领域等。微服务核心思想:服务即实体,我即全部。服务是实体概念的载体。其出发点是从业务领域或者功能层面就进行彻底的解耦。微服务之间完全异构,微服务之间甚至都无技术层面的共通性。
例如代表保单的微服务,所有跟保单的相关行为都是该服务提供的,该服务内部实现保单的存储和查询,外界无需关心,创建保单、查询保单、理赔保单均是通过该保单微服务实现的。
但是在实操中,限于硬件水平和当前的技术能力,单个微服务又难以承接实体相关的所有行为。例如保单的查询对性能要求比较高,保单的写入对一致性要求比较高,这种情况下,如果放在一个服务里就会带来实现上的困难。这时可能又会回到了传统技术功能划分服务上来,考虑读写分离,分出一个查询和读的保单微服务。有时候也是无奈的妥协,但是一般的原则是先坚持原则再妥协。先按照微服务领域的不可分割性来设计,遇到技术性的挑战再做调整与妥协。
03
关于复杂的理解
“计算机编程的本质就是控制复杂度” ---Brian Kernighan
3.1 什么是复杂?
对于一个系统来说达到怎么样的情况下才是复杂呢?物理学家劳埃德提出了一个观点:
描述它有多困难;
产生它有多困难;
其组织程度如何?
我个人的理解是,如果对于一个系统出现如下情况,即可认为是复杂的:
无法表达其概念,超出了人类语言的表达能力范畴
无法描述其过程,超出了人类的理解能力。
无法度量其结果,没有度量就无法管理,复杂到难以有精确的方式进行度量。
3.2 复杂的分类
-
表面复杂度:一个系统经过抽象、简化、分层、构建呈现出来的复杂度,是人类最直观理解的复杂度。例如一个系统架构图所呈现的复杂度就是表面复杂度。
-
必备复杂度:支持一个功能所需要的必备复杂度,也就是理论复杂度。
-
实际复杂度:实际上包含因为技术限制、资源限制、过程浪费导致的不必要的复杂度。
表面复杂度是人类所能理解的复杂度,必备复杂度和实际复杂度往往超出人类的理解能力。
有一种观点认为:系统架构的目的就是为了把系统的表面复杂度控制在人类的理解范畴内,把实际复杂度降低到接近必备复杂度。
3.3 CyneFin 框架
关于复杂,内涵很丰富。有一个大佬叫戴夫·斯诺登,他于1999年创建了一套辅助决策的框架 Cynefin 框架,这套框架里就很好地把我们平常说的复杂进行了归类。见下图。
这个图直观上看,分五个象限,从右下角依次逆时针看。
Simle(简单)、Complicated(繁杂)、Complex(复杂)、Chaotic(混乱),中间有一个黑色区域是Disorder(无序)。
这五组概念,可以理解为复杂度逐级提高。简单理解:
-
Simple(简单):知道因就能知道果。
-
Complicated(繁杂):由因可能推出不同的果,需要一定的领域知识,才能分析出因果。
-
Complex(复杂):不知因,也不知果。直观上找不出因果,必须事后复盘才可以。
-
Chaotic(混乱):知道因果不重要了,重要的是要构建秩序,使系统稳定下来。
-
Disorder(无序):复杂到都无法按照以上四个概念定义。
我们平常遇到的任何的业务、环境、情形、项目、系统都可以用这五个概念中的一个来形容。
一个系统的发展也大概会沿着从简单->繁杂->复杂->混乱->无序的状态发展。这个过程跟物理中的熵增概念很吻合。
Simle(简单):已知的知识,存在直接因果关系,一看就明白。这个不需多说,任何我们已经熟悉的系统,都是这样的。
对于这种状态的,我们最好应对方式,是采用感知-分类-响应模式。因果关系非常明确,我们只需要进行归类就好。
Complicated(繁杂): 这个系统存在大量的已知的未知,非专业人士很难看出其中的因果关系,需要专业人士结合大量的专业知识才能分析出因果。
例如在政府部门的设置上分纵线和横线两套体系,俗称“条条块块”。既垂直又水平。某县教育局纵线要向上级教育厅汇报,横线又要向地方县政府汇报。诸多类似的部门形成了错综复杂的关系,呈现出来就是网状的关系。面对这样的系统,体制外的人很难理清某个部门应该向谁汇报。这个时候如果来个公务员老司机,他能够很快速地告诉你其中的奥秘。
再例如,对于一个没有任何医学专业背景的人,你给他一堆指标,然后问他为啥会胃痛。他肯定觉得太繁杂了,无从下手。对于他来说最好的方式,就是请教医学生或者系统性学习医学类的专业知识。
所以面对繁杂的情形,最好的方式是,学习领域知识,快速入门。实践上采用:“感知-分析-响应”的模式。注意重点是分析。分析的前提要拥有领域知识。所以深入学习+分析才是应对之道。大部分情况下我们遇到的是这种系统,我们需要的是增加专业技能,补充领域知识,提高识别能力。这种也最好解。
Complex(复杂):代表了未知的未知。存在不确定的情况,可能存在也可能不存在,需要复盘才能找到原因。需要逐步探索,通过反馈才能分析到原因。
例如你突然被提拔为一个管理者,你的任务是团队文化建设。面对这项任务,既不知道因也不知道果。因为团队文化是个很虚的东西,你都不知道怎么衡量。更不用说采取什么方法去预测了。对于这种,你只能通过试探,然后事后归因。
所以采用模式是:“探索-感知-响应”。关键是要去探索,不断地探索,不断地反馈,最终找到因果关系。
Chaotic(混乱):混乱状态通常是指危机时刻。是指你能接触到信息都是不稳定的。这种情况下因果关系不清晰,处于杂乱无序的状态。尝试去识别因果已经没有意义了。
处于各种不稳定中,行动起来,把无序状态稳定下来。用行动来构建秩序。
对于这种情况,一切未知,只要行动起来,通过行动构建秩序。使混乱场面扭转到复杂的场面。这种状态下的应对模式是:“行动-感知-响应”。
Disorder(无序):复杂到无法对系统复杂度进行分类。完全无序,抓瞎状态。这种的应对策略,就是先观察,以静待变,等你理清楚了处于某种复杂度状态的时候,再去想对策。想不清复杂度,就不要动。一直想。直到你能区分系统处于以上四种状态的一种。
总结:
不同级别的复杂对应的处理策略也不一样。我们每天面对各种的情形,利用这个框架的指导思路,有助于我们透过现象看本质。能力越强的人处理的复杂度的也越高。
04
后记
本文的内容是结合以往的学习、收集整理而来。越整理越发现里面的知识越庞大,每个点都可以展开。所以这里很多地方只是简要带过,有时间再进一步整理。推荐三本书 :
《系统架构-复杂系统的产品设计与开发》对我来说,简直是开天眼的书。本文的有些思路和语句也是从这本书里摘录的。
《软件架构-架构模式、特征及实践》
《领域驱动设计》 这本书在笔者部门几乎人手一本。