作者 | 编程原理林振华
【问题】
- 什么是系统设计,系统设计的核心是什么?
- 如何训练系统设计的思维模式?
- 有什么方法来帮助我们理解复杂的系统?
- 如何进行系统分析?
- 架构设计的本质是什么?
- 如何进行架构设计?
- 如何进行业务领域建模?
- 模型如何推导出架构设计?
- 架构设计需要遵循哪些规范?
【关键词】
系统思维,系统分析,系统设计,架构元素,架构视图,架构模型,业务模型,概念模型,系统模型,分析模型,设计模型,用例驱动,领域驱动,物件,功能,物件结构,功能交互,利益,架构工具,决策选择,架构师,架构图
全文概要
软件从业人员的成长路线大体是在管理线和技术线上形成突破,当然也有结合起来相得益彰的。而技术上的追求,架构师则是一个重要的门槛,对于刚入行的程序员可能会认为架构师就是画架构图的,诚然架构师很重要的一个职责是绘制架构图,但这只是其中一个很小的环节而已。
实际上架构也只是系统设计里面的一个重要环节,除了架构还包含了商业诉求,业务建模,系统分析,系统设计等重要领域。本文尝试从更高视角重新审视架构设计的工作,把架构设计的上升到系统设计的立体空间去探索,最终勾勒出系统设计的全域知识体系。
思维分析
1. 系统总览
人类社会活动中的不管大大小小的,简单抑或复杂的事物,总要先出现在我们的脑海里,然后再投射到现实的物理空间来。我们总是在孜孜不倦地追求美好的事物,但现实存在的问题就是,首先我们的脑袋也理解不了太过复杂的东西,其次脑海里的想象有时候也很难真实无损的映射成现实的系统,再者由于总是资源有限的,我们并没有花不完的预算。
归结起来设计一个系统,或者朴素的说,做一件事情,我们需要解决以下问题:
在解决以上提出的问题前,首先声明我们要实现的是一个系统,而不是随意混搭的一件物品,毕竟现在讨论的不是行为艺术。那么就需要先来了解系统的定义:
系统是由一组实体和实体之间关系构成的集合,其功能大于各个实体功能之和。
系统可以分为自然系统和人工系统,但是本文特指需要人类参与的人工系统。
自然系统:
- 人体系统
- 生态系统
- 大气系统
- 水源系统
人工系统:
- 机械系统
- 电子系统
- 操作系统
- 社会系统
2. 系统演化
上面谈到在系统设计流程主要是使用了分析思维和系统思维的结合,当然人类思维还有其他的运作模式,比如批判思维,创新思维和发散思维等,以此衍生的又是另外一套截然不同的方法论。下面我们主要分析系统设计过程中的思维活动。
通常谈起架构师就会联想到各式各样的架构图,谈架构图就要搞清楚什么是架构设计,那么架构设计之前是什么呢?架构设计是整个系统建设的核心环节,犹如设计图纸之于建筑那么重要,那架构设计之上应该就是系统设计了。先搞清楚系统设计的定义:
系统设计是根据系统分析的结果,运用系统科学的思想和方法,设计出能最大限度满足所要求的目标系统的过程。
1)业务描述
上节弄清楚系统的概念,也就是先把边界框定下来,那么我们要实现的无非就是以上类别的系统。自然系统是天然形成的,或者你愿意的话也可以认为是盘古开天辟地形成的,那也可以归为人为系统。我这么说的原因是尝试把视角从软件这个领域往更加宏观的方向提升,让我们暂时忘掉软件架构师这一根深蒂固的角色。
假设现在我们想登上火星,言下之意是需要借助一套设备要把人类送到火星上,大胆一点,发挥仅存那点为数不多的物理知识储备,要设计出一套系统,能够把人类送到火星。这个时候老板就是愿意出资去火星豪华 7 日游的金主,那么需要一个负责人来实现这趟旅程,我们姑且把这个负责人就称为登火旅行系统架构师(叫总设计师也行,不需要在意这种细节)。那么这个系统架构师的工作,就是把登陆火星的一系列需求和目标转化成为足于支撑登陆火星庞大工程的系统架构。
根据系统总览提到的问题,先一一作答。
由于人命关天,这项工作看起来是挺复杂的,初次接到这个单子时我内心是彷徨的。但是回答了以上问题后,感觉明朗了不少,我们在完成系统性质,受众,利益和目标的分析和解答后,才能进入到系统的架构阶段。
首先对以上提到的需求,我们先用动画片里面的简单画面为基础来描绘我们的设计,然后大致根据能想到的过程完成初次业务流程的描述。
业务流程画图元素:火箭,机舱,地球,火星,来回,基础功能(安全,舒适,成本)
通过以上的描述,基本涵盖了火星旅程的四个阶段:登机,航行,下机游玩,返程,这本质上跟我们平时搭个飞的去趟浪漫的土耳其也是差不多的。而在此之前我们脑海里可能还是一片混沌,沉溺在登陆火星这项浩瀚的工程而不知道从而入手。
从混沌到开始有点头绪,其实无形中已经完成了一次建模,我们称为业务建模。翻回去查阅系统总览的表格,其实我们已经把需求这个维度大致列举出来了,把登陆火星的几大领域给分离开来了。那么接下来就是要把登陆火星这个项目的主线给说明清楚。
2)概念抽象
怎样把这件事的主线说明清楚?滔滔不绝的把一件事情讲完其实反而是很难讲明白,除非这件事情本身足够非常简单的。那么就需要抓重点的来说,这个时候就需要一个叫做“概念”的工具。
概念是抽象的、普遍的想法,是充当指明实体、事件或关系的范畴或类的实体。
简单来说,概念就是用简单的一个词汇,就可以让在坐的大家都能准确无误的理解这个词汇所表达的含义。这个是语言独特的魅力,可以说有个概念这个武器,才有了人类多次工业革命的文明大爆发。有了“概念”这个工具,再对概念进行组合,会爆发出无穷的生产力。
这里穿插讲一下概念的应用,比“傅立叶级数”这个概念,我敢打赌有 80% 的人不知道所谓何物,但是没关系,我们并不是要来科普这个概念,先根据百度百科来看看这个概念的描述:
先不要怕,我这么说的目的不是为了让大家搞懂什么是傅立叶级数,这里我们可以看出即使这么鬼畜概念也是很普通的基础概念元素组成的,比如收敛公式,比如三角函数,比如 Σ 求和概念,甚至像 1,2,3 这些阿拉伯数字。这里不得不说学数学最核心的环节就是深刻理解概念,没有之一。
说回来,这里的语境就是在大家都共同理解接受这些基础概念后,经过一系列复杂组合的高级概念,也依然能够清晰严谨的表达出来,下面傅里叶级数的产生过程的动图看看就好。
好了,现在我们知道了概念这个工具的重要性和功能,前面我们已经列举了登陆火星要做的事情,那么现在就需要精确简洁的把这件事给说清楚了,这个是个困难的任务,因为如果主线没有梳理清晰,后面整个工程将万劫不复。
在业务建模后就是概念建模,作为架构设计的输入,这个阶段就需要对核心业务的充分理解,同时在基础性和通用性方面的功能也需要同时考虑,这个阶段需要大量的业务专家和各个领域的科学家通力协作,保证对系统的理解没有偏差。经过一系列的概念抽象和组合,最终输出登陆火星工程的架构图,这里只是用于说明登陆火星项目同样遵循这业务-概念-架构-设计的流程,不要在意架构图本身合不合理。
3)系统落地
当然这还远远不够,系统之所以复杂,就是我们对系统总有无数更多的要求,更多的功能,更好的性能,那么接下来就是对各个模块进行分析,细化,设计和实施。当然我们不会班门弄斧真的在这里去分析登陆火星的实际流程,以上这个例子虽然比较粗旷,但是基本也描绘了一个复杂系统建设的过程,也就是从需求,建模到架构的思维过程,是从最原始的登火需求一步步扩展的过程。
其实我们还可以举个小一点的案例,比如一个有趣的需求“赚钱”,引申出来就是做一个能盈利商业项目架构,有兴趣的同学可以根据这个思维模式一步一步勾画出整个流程出来,相信这也是一个不错的方法,也许还真能解决些许困惑。下面演示的就是登月过程宏观层面落地的步骤。
3. 架构思维
1)架构目标
一直以来我听过很多人在讲架构,有些人在做架构,但是很难讨论出一个大家都满意的定义,什么是架构师,架构师需要做哪些工作?或者说很少有往深的去思考,只知道被称为架构师说明这个人很厉害。在我毕业的时候有个同学打趣的跟我说,你们做程序的无非就是增删改查,当时我竟无言以对,当时脑海里浮现的是一系列工具的应用技巧,比如 tomcat,nginx 的使用,还有对业务的翻译。
随着对业务的贴近和对计算机技术的进一步认识,我重新审视“这世上的系统无非就是增删改查”,这句话说对也对也不对,这句话就跟计算机软件无非就是 0 和 1 的集合,也对也不对。特别是对刚入行的人可能觉得设计离自己比较远,因为习惯了打开 idea 才开始考虑业务,写代码才开始思考领域模型,这是非常不好的习惯,好像如果没有在 coding 状态下是无法进行建模思考,这个很难,需要持久的训练才能达成设计阶段进行思考。
架构设计只是系统设计里面的一个阶段,而系统设计是应用建设里面的核心环节,有一些简单的应用建设是不需要系统设计的,当然有一些复杂的应用,在能力超强的工程师团队,有足够的默契后,也可以直接进行建设。
软件架构之道最核心的问题是解决复杂性的问题,并且在解决问题的过程中找到最佳的平衡点,既要简单又能满足发展。描述系统设计的本质,就是实现纵向上的时间,横向上的空间进行考虑,规划出决策路径,最终拿到目标结果。
架构师眼里第一件事不是多流行的技术,多高性能的框架,或者多完善的业务模型,而应该聚焦在利益之上。对,这个可能会颠覆一些认知,当我们真正把利益放在首位后,再去考虑接下来要完成的事情,我们的工作才能称得上架构。也就是说,架构师的天职就是最大限度地实现客户的利益,这里的客户可以是市场客户,也可以是协作团队,还可以是同一个团队的项目成员。
再直白的说,架构师就是负责把老板画的饼给实现了,在相当长的一段时间内保证产物有足够的利益回报。有人会说那我们做的就是公益项目,就不考虑利益,我补充一下,这里说的利益不止是经济收益,还有系统带来的社会价值。那么又有人会说,架构是追求利益回报,那老板的目标就是炒股发大财,请架构师你给我选几支股票吧,那我会说其实优秀的基金经理也可以称为广义上的架构师。
2)架构过程
自然在增熵,而系统架构过程其实就是减熵的过程,一个架构的诞生始于目标的确立,然后是对需求的刻画,继而是落地方法的抉择。
所谓条条大路通罗马,有的是一路平川而有的则是崎岖不平,那么架构过程就是不断归类合并同类项,力求最合适的决策选择来实现我们所要达成的愿望。在面对复杂业务的场景下,我们需要做出如下的思考:
- 确定系统实体对象和预期功能
- 抽象系统实体之间的关系,功能与实体的关系
- 划定系统的边界和外部环境的关系
- 预测系统带来的效果
在架构过程中,很重要的一项任务就是识别系统的实体关系和功能关系,进而对系统效果进行预测,也就是在完成一系列的分析建模工作后推导出来的系统架构需要在预测上达到我们要的效果,那么系统预测通常有如下四种方式:
- 经验
- 实验
- 建模
- 推理
3)系统思维
系统思维不等于系统化思考,与系统思维并列的可以是批判思维,分析思维,创新思维,而我们追求的是元认知,也即是认识到自己处于何种思维模式。系统思维目标:
- 理解系统是什么
- 预测系统的走向
- 为决策提供知识支持
系统思维首先是高效地理解分析现存的系统,对系统重构做好理论指导基础。
这一节介绍了设计一个系统需要经历哪些重要的环节,并且强调了谋求利益是系统设计的核心诉求。然后通过登陆火星这项任务把一个庞大的工程变成了可理解的独立步骤,并且还有模有样的画出了架构图,体现了对业务建模到架构输出的流程。下面章节我们将会展开来介绍一套核心的方法论,如何破局系统架构设计。
系统分析
上一节谈论了系统设计的心智模型和投射到物理世界的演化规律,但前提是建立在已经具备丰富系统设计经验基础上。而在进行系统架构之前,需要先对系统分析有一定的理解,好比我们制造发动机之前,得先把发动机拆下来好好研究一番,直接上来就要设计出发动机有点像空中楼阁。
本节将提供一套基础的方法,来对现有系统进行分析,得出一些系统架构相关的推论。按照惯例需要先搞清楚系统分析的概念:
系统分析,旨在研究特定系统结构中各部分的相互作用,系统的对外接口与界面,以及该系统整体的行为、功能和局限,从而为系统未来的变迁与有关决策提供参考和依据。系统分析的经常目标之一,在于改善决策过程及系统性能,以期达到系统的整体最优。
大到银河系,小至原子粒子都有着特有的结构,何谓结构:
结构是指在一个系统或者材料之中,互相关联的元素的排列、组织关系。
而系统在物质世界里面当然也遵循这样的规则,分析系统跟分析银河系也一样,需要对它的组成元素和元素之间的关系进行分析。而对系统的分解也是讲究方法的,可以参考以下总结的一些方向:
- 体系归纳
- 层级分解
- 逻辑关系
- 自顶向下
- 自底向上
- 由外向内
- 由内而外
1. 实体分析
实体指系统物理时空存在的单元,彼此通过一定的结构形成系统,那么在分析实体之前,我们可以带着下面的问题进行分析:
- 系统是什么?
- 构成系统的元素有哪些?
- 系统元素之间的结构是什么?
- 系统的边界在哪里?
- 系统的使用场景是什么?
实体是系统的一项基础属性,是系统的物理体现或信息体现。对功能的执行起工具性作用,而描述实体通常可以使用以下工具来表达:
- 文字描述
- 符号描述
- 插图
- 插画
- 示意图
- 三维图
- 透视图
实体之间的关系就是结构,分析结构时需要对实体进行分解,实体可以建模为对象及其之间的结构,进一步可以分解为小的实体,又可以聚合起来称为系统本身,对实体之间的各种结构分析则可以得出系统架构,即是把功能元素组合成物理块时所用的编排方式。
1)分析实体
- 对实体的载体进行抽象聚类,形成对象,体现出边界
- 用适当的层次来分解架构的实体
2)分析关系
即是实体的结构,是对象之间存在稳定关系,有助于功能交互的执行系统实体有如下关系:
- 空间拓扑关系
- 连接性关系
- 地址关系
- 顺序关系
- 成员关系
- 所有权关系
- 人际关系
2. 功能分析
上面一节我们了解了系统的物理基础,对组成系统的实体进行分解,分析,进而对实体的关系描述为结构,结构抽象是得出架构的基础步骤,而系统物理基础存在的理由是为了实现我们的诉求,也即是系统的功能。毕竟万物皆有因,存在即合理,系统构建最终也是要达成我们的意愿,完成这个诉求才算是合格的架构。分析形式相对来说毕竟简单,毕竟实体是有形的便于理解,而功能则是由实体组合涌现出来的属性,功能分析过程需要跟实体不断的交互穿插。
关于系统功能其实可以朴素的认为就是动宾短语的集合,功能=动词+宾语,含义就是实体状态变化的过程,就是功能的体现,具体分析下文会详细展开。功能 = 主体 + 操作 + 操作对象,比如嘴巴有“吃饭”功能,飞机有“搭载乘客”功能,报表平台有“展示报表”功能。
- 操作:对象经历的一种转换模式,过程设计操作数的状态变化;
- 操作对象:操作数是一个对象,在某段时间内稳定且无条件存在,操作数不需要先于功能的执行而存在,操作数可能会由功能中的过程部分来创建,修改或消耗。
总结起来,系统分析就是建立一套方法论,去分析复杂的系统,令系统不再那么难懂。
系统设计
经过了上几节的思维训练和系统逆向分析,我们也大概理解了系统设计的流程和系统架构的形成过程,本节将介绍系统设计,包括设计工具,需求分析,模型建立,架构推导,设计规范完整的系统设计流程。
系统设计,即设计出一套良好的系统架构,就是构建一套具备必要复杂度又不难懂的系统。下面在介绍方法论的同时,同时会穿插一个数据平台的大致设计过程。
在进入本章节系统设计前,我们先要来学习学习一个架构 TOGAF:
TOGAF:框架开放组体系结构框架(The Open Group Architecture Framework,缩写:TOGAF)是一个企业架构框架,它提供了一种设计,规划,实施和管理企业信息技术架构的方法。TOGAF 是一种高层设计方法。它通常被建模为四个级别:业务,应用程序,数据,和技术。
在 TOGAF 中,任何一种企业能力的建设都需要对如下四种领域进行设计,包括针对这一可持续性架构实践建设:
- 业务架构:突出了架构治理、架构流程、架构组织结构、架构信息需求以及架构产品等方面;
- 数据架构:定义了组织中架构连续体和架构资源库的结构;
- 应用架构:描述了用于支持此可持续架构实践的功能和服务;
- 技术架构:描述了架构实践中用于支持各架构应用和企业连续体的基础设施需求和部署方式。
TOGAF 架构框架是一组工具,可用于开发各种不同的架构:
- 描述了一种用于根据一组构建块来定义信息系统的方法
- 展示构建块如何组合在一起
- 包含一组工具
- 提供共同的词汇集合
- 包括推荐标准列表
- 包括可用于实现构建块的兼容产品列表
企业可以通过应用企业架构开发方法(ADM)来建设各种业务能力,下面我们再来介绍另外一种系统设计的思路。
1. 设计工具
工欲善其事,必先利其器。前文讲到思维分析,不同思维模式决定不同的方法论,那么在分析思维层面,人类大脑其实很难理解太过复杂的东西,这个时候就需要借助一些工具来协助思维的活动。
首先第一工具当然是语言,这个不用多说,没有语言作为基础将寸步难行,单个体的时候语言用于描述系统的诉求,而多个体的时候语言则扮演着沟通的角色,但是如果语言不互通的话可能就像鸡同鸭讲。即使是同一种语言,不同的表述都会形成很大的偏差,那么就需要一种普遍认可的统一语言,在系统分析审计领域,我们首推统一建模语言(英语:Unified Modeling Language,缩写 UML),当然还有其他比如 SYSML 或者 OPM,下面我们先大致介绍下 UML,列出 UML 的核心语言元素,视图,模型和过程。
1)核心元素
- 参与者
- 用例
- 边界
- 业务实体
- 包
- 分析类
- 设计类
- 关系
- 组件
- 节点
2)核心视图
静态图包括:
- 用例图
- 类图
- 包图
动态图包括:
- 活动图
- 状态图
- 时序图
- 协作图
- 泳道图
3)核心模型
- 业务用例模型
- 概念用例模型
- 系统用例模型
- 业务领域模型
- 系统分析模型
- 系统设计模型
- 系统组件模型
4)核心流程
- 业务建模
- 系统建模
- 模型分析
- 模型实施
5)软件工具
- draw.io
- StarUML
- Visual Paradigm
2. 需求分析
本节不打算讲需求分析师的工作流程,因为我们已经很熟悉需求分析师对需求的分析过程了,所以无需多言,在讲需求之前我们先来看看架构师需要完成的工作。
架构师并不是全能的通才,无法了解所有细致的需求,所以架构师要做的就是简化系统的复杂度,消除业务歧义,致力于输出健壮兼容的系统架构。由于系统需求分析需要由架构师这个角色全程参与,深度理解业务,下面我们简单对架构师角色进行讨论。
1)架构角色
我们先看看传统系统设计两大核心角色的定义:
系统架构师:是在信息系统研发中,负责依据需求来确定主要的技术选择、设计系统的主体框架结构,并负责搭建实施的人。系统分析师:是在信息系统研发中,负责通过需求分析确认系统的需求,并进而形成系统产品设计的人。通常他们也会涉及可行性评估、项目管理、开发前评估、需求验证等工作。
传统意义的系统开发分为系统架构师和系统分析师两个角色,但是随着互联网的快速发展,如今系统建设越来越趋向于将两个角色结合起来,那么互联网时代架构师有如下职责:
- 了解问题领域,消除歧义
- 树立业务目标,抽象业务用例
- 完成涉众分析,发现系统主要受益者
- 划清系统边界,确立对外交互方式
- 划分优先级别,聚焦系统核心诉求
- 分析业务需求,输出业务模型
- 抽象业务概念,输出概念模型
- 推导系统架构,输出架构模型
- 负责技术选型,完成系统落地
架构师是软件开发活动中的众多角色之一,它可能是一个人、一个小组,也可能是一个团队,我们分析的是架构师这个角色,能胜任这个角色的才是架构师,那么在这个角色上能做得更加出色的就是好的架构师。
以上架构师职责是整体上的描述,在细分领域有不同的分类。微软对架构师有一个分类参考,我们参考一下,他们把架构师分为 4 种:
- 企业架构师 EA(Enterprise Architect)
- 基础结构架构师 IA(Infrastructure Architect)
- 特定技术架构 TSA(Technology-Specific Architect)
- 解决方案架构师 SA (Solution Architect)
既然对架构师角色有诸多要求,那么也可以来归纳一下架构师必备的一些技能,能力模型可以参考《职业成长的逻辑模型》一文中对能力模型的描述,架构师能力要求:
- 现有资源评估盘点及资源编排能力
- 消除歧义分清问题主次能力
- 业务简化描述,用例抽象思维
- 通用市场法务市场领域基础常识
- 业务分析架构推导能力
- 计算机基础理论知识体系
- 通用技术栈原理认知
- 工具使用熟练,排查定位问题能力
- 技术深度广度
- 分布式高并发性能调优技能
- 产品思维
2)利益分析
首先当然是要确立好客户,所谓客户第一,听起来很简单,如果只是单一的服务好客户,那确实不算很难。难的是如果同时存在多个业务方向的客户,而且客户直接的利益产生交集,而且存在矛盾,怎么权衡好利益分配,区分客户利益优先级,才是困难的。
不忘初心这一点尤为难得,很多项目做着做着就偏离了当初的目标,这个过程我们一定要紧紧抓住系统最重要的受益者,梳理好系统众多涉众的利益分配。
3)资源评估
资源评估不仅仅是项目经理的事,而且还是对团队资源的评估和编排,比如某项业务技术团队中研发和数据人员的配比,决定了数据平台投入的资源范围,这要求架构师在做设计分析的时候需要充分考虑到资源的利用效率,包括人力资源和机器等资源。
4)需求规范
用户的诉求体现为需求的输出过程,不同层次分解需求得出了不同的复杂度,我们知道架构师的一项重要职责就是消除歧义,精准的把握需求来匹配用户的诉求。那么就需要一系列规范来保障需求采集的过程中不失真。
下面列出了需求采集过程的一些指导原则:
- 每个软件需求是否都有唯一的标识符?
- 每个软件需求都可以验证吗?(如果可能,是否可正规化,量化)
- 是否对每个软件要求进行了优先排序?
- 所有不稳定的软件要求是否都已标明?
- 软件需求是否完整?(涵盖了所有用户要求,考虑了所有相关的输入情况)
- 软件要求是否一致?
- 是否明确指出了软件需求之间的重叠交叉?
- 是否明确规定了初始系统状态?
- 软件需求是否表达了逻辑模型, 而不是实现形式?
- 软件需求是否以结构化的方式表示为抽象层次?
- 是否足够清楚,逻辑模型的结构
- 软件要求是否已正式形式化?
- 是否已证明软件需求的关键属性?
- 所有形式化的图表材料是否都随附了充足解释性文字?
- 是否针对项目团队缺乏经验的领域描述了探索性原型?
5)需求描述
在进行需求描述时,我们可以从多个角度来审视需求是否合理地表达出来:
- 满足需求,能带来什么价值,符合什么利益诉求?
- 需求无法满足时,会带来什么危害,有何潜在风险?
- 需求是否紧迫,必须在什么时间段内完成?
- 多个需求直接是否产生耦合,完成一个需求后是否带来了新的问题?
- 是否能多个备选方案来完成需求?
6)需求采集
回到我们平台设计的案例上,经过用户访谈粗略的采集的需求:
• 单项业务壁垒是个困局,本质上是功能缺陷,打通数据壁垒
• 业务各个阶段的数据管理,要对数据底层进行管理
• 需要对由相同特性的报表实现快捷地生成
需求背后:
• 可以一次性看更多的数据
• 可以方便的切换数据
• 可以更快的看到数据
so,这个真的是客户想要的吗?整体上,用户想看什么数据?同时我也在思考下面的问题:
- 深入分析用户需求
- 搞清楚我们的客户是谁?
- 定义好问题,搞清楚问题的本质,分析问题矛盾之处,我们要解决什么问题?
- 我们要在多大范围内去解决问题,要解决跨度多长时间可预计的问题?
- 我们的边界在哪里?
- 我们的使命是什么?有了使命后再谈我们自己,愿景是什么?
3. 模型建立
在系统设计这个阶段,我们已经介绍了如何运用工具,还有用户需求的管理,接下来就是要把需求“消化”成我们需要的架构。但是架构不是平白无故就产生的,前文我们用登陆火星的案例也大概描述了系统的建设过程,那么在推导出架构之前,把用户不那么清晰的诉求转化成严谨的业务概念模型就很有必要了。
1)模型基础
首先我们要搞清楚模型相关的概念:
模型:是指用一个较为简单的东西来代表另一个东西。科学模型:是科学研究中对一类研究方法的通称,使用数学公式、电脑模拟或简单的图示来表示一个简化的自然界,透过分析这个模型,以期能够进一步了解科学,包括说明、验证假说、或分析资料。
概念模型:是用一组概念来描述一个系统,或用任何代替的形式来描述一个概念,以期能进一步了解或说明事物的运作原理。具体的形式可能包括思想实验、数学模型、电脑模拟、示意图、比例模型等。
业务建模:是以软件模型方式描述企业管理和业务所涉及的对象和要素、以及它们的属性、行为和彼此关系,业务建模强调以体系的方式来理解、设计和构架企业信息系统。
2)建模目标
即是说业务建模是一种建模方法的集合,目的是对业务进行建模。这方面的工作包括了对业务流程建模,对业务组织建模,改进业务流程,领域建模等方面。针对复杂难懂的系统,我们构造出一个比较简单的模型,来代表复杂的业务,这个是一种有效的办法,这也是我们需要建模的原因,随着计算机的飞速发展,或许以后计算机可以帮人类承当一部分的设计工作,而计算机是不怕复杂业务的,也许那个时候就不再需要这种特地适应人类思考的模型了。
建立模型不是最终目的,而是把复杂的业务诉求构建成简单的业务概念,在软件开发团队沟通过程中能形成共识,消除歧义,而且信息传递不失真,为输出架构奠定基础。
3)模型分类
在业务不同的阶段,通常会使用不用的模型来表达,一般情况下我们把模型分为:
- 业务模型
- 概念模型
- 系统模型
- 分析模型
- 设计模型
- 物理模型
4)建模方法
建模有很多种方法,对于同样的问题域使用不同的建模手段,得到的模型可能也不尽相同。建模是一种对现实事件的抽象,不同的心智会产生不同的模型,比如宗教,不同宗教就是对人生观世界观产生不同的模型,我们先介绍常用的建模方法:
- 领域驱动(DDD)
- 用例驱动(UDD)
- 四色建模
- CRC建模
- CQRS建模
下面我们以用例驱动和领域驱动为案例来介绍这两种思维方式的建模过程。
5)用例驱动
用例驱动是一种由外而内,先招式后内功的思想。我们先从涉众对系统的期望开始,定义出系统如何满足他们的愿望。这一过程是感性的、外在的、符合当前需求的。
用例驱动的结果是我们的软件是以实现一个个场景为目的的,认为当一个系统的行为满足了所有涉众的期望之后,即满足了涉众使用系统的场景之后,该系统就是一个成功的系统。
【建立用例】
用例定义:工具—>过程—>操作数 (主 谓 宾)
- 参与者:某些具有行为的事物,可以是人,计算机系统或组织;
- 场景:参与者和系统之间的一系列特定的活动和交互;
- 用例:一组相关的成功和失败的场景集合,用来描述参与者如何使用系统来实现目标。
【用例规范】
用例其实就是对一件独立事情的描述,这非常符合我们人类语言的表达过程,我们日常沟通很大部分是陈述一个观点,那就是以主谓宾的方式来表达,同样的编写用例也可以遵循这个结构。
【建模过程】
- 用例模型
用例:每个用例提供了一个或多个场景,该场景说明了系统是如何和最终用户或其它系统互动,也就是谁可以用系统做什么,从而获得一个明确的业务目标。编写用例时要避免使用技术术语,而应该用最终用户或者领域专家的语言。用例模型:用例模型是系统既定功能及系统环境的模型,它可以作为客户和开发人员之间的契约。用例是贯穿整个系统开发的一条主线。同一个用例模型即为需求工作流程的结果,可当作分析设计工作流程以及测试工作流程的输入使用。
用例有严格的规范,回顾上文系统分析里面,我们对系统功能分析给出一个公式:功能 = 主体 + 操作 + 操作对象。用例也是需要这样的结构,比如“我爱你”是完整的用例,能完整的描述一件事情,而“爱你”则不能称为一个用例。所以用例模型建立阶段就要力求把用户诉求都完整的以用例表达出来。
- 业务模型
业务模型:业务模型采用业务用例来绘制,表达业务的观点。
我们在数据平台对用例模型进行抽象。
分析师 为客户 制作 业务 报表:
抽象起来就是分析师制作报表,这个是我们最朴素的模型,我们以这个最原始最核心的用例为立足点点开始发散。
- 主语:分析师
- 状语:客户
- 谓语:制作
- 定语:某一项业务
- 宾语:报表
经过我们对语言的分析,已经很清晰地呈现出我们的业务模型,就是分析师制作报表,加上状语和定语的修饰,我们知道是为客户这个主体创建的报表,而且是特定领域的报表,状语就是跟分析师强相关的。
- 概念模型
概念模型:概念模型是一种或多或少的形式化描述,描述的内容包括建立软件组件时,所用到的算法、架构、假设与底层约束。这通常是对实际的简化描述,包括一定程度的抽象,显式或隐式地按照头脑中的确切使用方式进行构建。
现在我们明确了业务模型后,接着就是细化用户,补充更多的细节:
- 分析师 为 不同的客户 制作 不同业务的 报表
- 分析师 为 不同的客户 制作 几款业务的 报表
- 分析师 为 不同的客户 制作 一项业务不同区域的 报表
- 两个分析师 为 某个群体用户 制作 业务线的 报表
- 客户 授权 某个群体 查看 不同业务的 报表
结合我们对业务的了解,可以丰富领域的属性,还有一个隐性的“权限”名词,我们需要独立出来,因为权限不属于任何一个领域。
通常我们需要角色概念来管理用户访问报表的权限。
- 管理员 为 不同的客户 创建 一项业务不同区域的 角色
- 管理员 为 不同的客户 分配 一项业务不同区域的 角色
- 小二 为不同报表 创建 不同 权限
- 系统模型
系统模型:系统模型是一个系统某一方面本质属性的描述,它以某种确定的形式(如文字、符号、图表、实物、数学公式等)提供关于该系统的知识。
丰富业务场景后,整体的用例如下图:
- 分析师 为 不同的客户 制作 不同业务的 报表
- 工程师 为制作 个性 报表
- 小二 给不同业务创建报表模板 来生成报表
- 小二创建权限 来 匹配报表
- 客户创建角色
- 客户分配角色
- 客户筛选人群进行营销活动
- 前置条件:业务告警?
6)领域驱动
用例驱动是一种从局部到全体的思维方式,刚刚接触某一行业的人员从零开始来了解业务,复杂业务很难一开始就拥有上帝视角来分析业务。而领域驱动则是一开始就站在上帝视角来着手业务,领域驱动要求化整为零,它是一种由内而外,先内功后招式的思想。它要求团队里有资深的业务领域专家,该专家对业务领域极其了解,不但要了解其然,还要理解其所以然,或者是能够跟领域专业人员学习到足够的领域知识。
在此条件下,团队将从业务领域里找出反映业务本质的那些事物、规则和结构,把它抽象化,描述业务运行的基本原理和业务交互的机制,识别出用户的首要利益。
领域驱动需要领域专家深度参与,访谈专家,才可能得出领域模型,单靠技术人员本身很难得出完成得领域模型。语言就是承载思想或者想法的模型,不同的语言建模出不同的思想,中西语言差异造就思维差异,所以领域模型需要从语言谈起,用语言描述事物。领域模型本质上传递的是概念,是知识性的信息,语言正是让知识传递成为可能。
对于软件开发的场景来说,把这些知识显式化,能快速对齐不同角色、不同参与方之间的概念,加速沟通,避免误解。
【领域模型】
我们先得搞清楚领域模型的概念,然后才有领域驱动。
领域模型是采用业务对象建立起来的一种模型,我们把领域模型当中使用到的业务对象称为领域类。
回顾我们学了很多年的面向对象变成设计,而实际上真正使用面向对象开发的思维却是比较稀少的,比如传统 MVC 架构下的 web 开发,基本是失血模型的对象,让我们很少真正使用面向对象来实现我们的业务。而正是因为缺少面向对象的业务实现的必要训练,让很人使用领域驱动时觉得困难重重,这就需要我们对领域模型有一些基本的认识,然后在训练中来深化对领域模型,面向对象的认识。
领域模型的核心思想是对象,而领域驱动的核心是分层,需要对实现架构进行分层,不同的团队,不同业务可能会有相应不同的分层,但是整体上分层的思想就是解耦,把复杂的事情分解开来简单化处理。
传统架构挂着面向对象的名号,实际上干的全是面向过程的勾当,用户界面,数据库操作以及其他辅助性代码进程被写到业务对象里面,原因就是能让业务快速的跑起来,而领域驱动则打破了这个传统,给出了通用的架构解决方案,包含 4 个概念层:
将应用按层分离并且建立好约束的交互规则是很有必要的,代码如果没有被放在正确的位置上,则很快会发生混乱。领域层最核心的职责只应该关心领域方面的业务问题,基础设施则只需关心底层的数据交互和外界的数据通讯交换,而无需关注业务的实现。
代码层面上各层的实现职责如下:
- 接口层:该层包含与其他系统进行交互的接口与通信设施,在多数应用里,该层可能提供包括 Web Services、RMI 或 Rest 等在内的一种或多种通信接口,该层主要由 Facade、DTO 和 Assembler 三类组件构成;
- 应用层:Application 层包含的组件就是 Service,在领域驱动设计的架构里,Service 的组织粒度和接口设计依据与传统 Transaction Script 风格的 Service 是一致的,但是两者的实现却有着质的区别,TransactionScript 风格的 Service 是实现业务逻辑的主要场所,因此往往非常厚重;而在领域驱动设计的架构里,Application 是非常“薄”的一层,所有的 Service 只负责协调并委派业务逻辑给领域对象进行处理,其本身不真正实现业务逻辑,绝大部分的业务逻辑都由领域对象承载和实现了,这是区别系统是 Transaction Script 架构还是 Domain Model 架构的重要标志;
- 领域层:Domain 层是整个系统的核心层,该层维护一个使用面向对象技术实现的领域模型,几乎全部的业务逻辑会在该层实现,Domain 层包含 Entity(实体)、ValueObject(值对象)、Domain Event(领域事件)和 Repository(仓储)等多种重要的领域组件;
- 基础设施层:作为基础设施层,Infrastructure 为 Interfaces、Application 和 Domain 三层提供支撑,所有与具体平台、框架相关的实现会在 Infrastructure 中提供,避免三层特别是 Domain 层掺杂进这些实现,从而“污染”领域模型,Infrastructure 中最常见的一类设施是对象持久化的具体实现。
【建模过程】
有了领域建模的基础知识后,下面我们介绍下领域建模的过程。
- 用户访谈:充分贴合业务,基于现有人员资源能力;
领域知识:首先我们分析项目在领域分层后的概念项目涉及到:
- 名词:分析师,工程师,客户,小二
- 报表,报表模板,权限,角色,告警,人群,活动,决策
- 动词:登陆,创建权限,匹配权限,授权,建表,圈人,营销
- 实体:报表,报表模板,权限,角色,人群,活动,决策
- 值对象:告警
- 服务:登陆,创建权限,报表匹配权限,授权给用户,创建报表,圈人,营销
- 模块:报表域,权限域,洞察域,营销域
- 聚合根:报表(报表模板,报表数据),权限(权限,角色),活动(人群,营销规则)
- 工厂:报表模板工厂,人群工厂,决策工厂,权限工厂
- 资源库:数据库,消息,外部接口
- 领域模型:经过对领域知识的消化,就可以输出领域模型图。
4. 架构推导
经过了漫长的前戏--模型建立,本篇终于到了架构设计了,真的不容易啊。一开始我总是在纠结架构师应该输出什么架构图,什么才是标准的架构图,但是当我理解什么是架构,架构形成的过程后,我不再纠结了,架构存在每一个阶段,以不同的形态出现,业务,产品,技术,实施不同的阶段都需要一张提纲挈领的架构图来指导系统建设。
系统架构这个词经常放在一起说,以至于我们觉得天经地义,经常混为一谈。系统指的是由一堆实体组成的一个具备某些功能的整体,而架构则是架和构,即是框架和结构,也就是具备稳定诉求而且是可以支撑整体的组件。系统可以没有架构,比如我们乱糟糟的系统。但是系统同时也是需要架构的,架构就像是系统的 DNA,架构决定了系统的走向和生命周期,好的架构可以支撑系统持久运行和更新迭代。
1)架构定义
我们先来对架构进行定义:
架构:对系统中实体与实体之间的关系进行抽象的描述,用于指导软件系统各个方面的设计。
2)架构分类
随着互联网的发展,应用从单体到分布式,到如今基础设施的变革,我们迎来了云原生时代,系统的架构随着基础技术的突破也不断演化,单体应用最简单最常见的架构就是分层架构,比如我们熟悉的 MVC 架构,由于业务发展到一定层度后,需要对服务进行解耦,进而把一个单一的大系统按逻辑拆分成不同的子系统,通过服务接口来通讯,面向服务的设计模式,最终需要总线集成服务,而且大部分时候还共享数据库,出现单点故障的时候会导致总线层面的故障,更进一步可能会把数据库拖垮,所以才有了更加独立的设计方案的出现。
随着分布式技术的成熟,微服务架构开始大行其道,在此基础上的边车服务和 servicemesh 也开始进入蓬勃发展期,整体上架构有如下分类:
- 分层架构:MCV,六边形架构,洋葱架构
- 事件驱动架构
- 微核架构
- 微服务架构
- 云原生架构
3)推导架构
先问题,后定位,即:先使命后愿景,解决什么问题?先定义问题,何为问题,有矛盾即存在问题,专业的抽象和架构知识,以及背后的归纳和演绎的逻辑思考方法,加上丰富的业务用例,通过逻辑排列,形成业务架构,首先我们会用以下的表格来描述问题。
演绎
- 将用例进行抽象分类成为业务模型
- 将业务模型进行 IT 层面的思考,增加非功能性的组件形成系统模型
归纳
- 将用例以及问题进行分类聚合
- 业务用例形成系统架构过程需要进行归纳
- 对行为稳定性,性能考虑的总结,归纳为通用组件
4)架构输出
- 方案概述:对设计方案的概括性描述;
- 设计约束:包括要遵循的标准或规范,技术上依赖的假设条件等;
- 技术选型:包括系统运行的软硬件环境,研发、测试的软硬件环境,编程语言,现有或开源框架、平台、模块、基础库的重用策略;
- 系统结构:包括系统的网络部署结构,子系统划分,推荐用 UML 部署图、包图描述;
- 关键技术设计:每个系统关键点不一样,但一般都会有安全设计,一些算法的设计;
- 接口设计:包括协议栈,子系统间的接口数据结构,子系统间的业务流程描述。业务流程推荐用 UML 序列图描述;
- 数据设计:流动的数据已通过接口设计,这里描述要存储的数据,数据的组织形式不一样,比如 NoSQL,NewSQL,SQL 等不同类型,描述方式也会不一样,关系数据库推荐用 ER 模型描述顶层逻辑结构,字段表描述物理结构;
- 质量预测:对遗留缺陷率、平均无故障运行时间等质量指标进行预测,提出可能出现的缺陷和问题。
5)架构总结
- 自底向上:由点及面,步步为营,通过用例堆积,分类,归纳,划分,内聚,逐步扩大范围,再通过剥离,复用,从业务架构到技术架构;
- 自顶向下:洞察客户背后的本质需求,定义问题,分析问题,问题分类,优先级,升层思考,一上来自带上帝视角。
实际应用,两者结合。
5. 设计规范
建立用例后,由于对用例分析的方法差异可能生成不同的领域模型。
1)模型约束
推导出模型过程中,需要参考业界沉淀出来的经验,比如 sold 原则,开闭原则等:
- GRASP 设计原则(职责分配原则)
- 信息专家原则(information)
- 创造者原则(creator)
- 低耦合原则(low coupling)
- 高内聚原则(high cohesion)
- 控制器原则(controller)
- 多态原则(polymorphism)
- 纯虚构(pure Fabrication)
- 中介原则(indirect)
- 受保护变量原则(protected Variations)
2)设计原则
GRASP 原则,设计原则有很多,我们进行架构设计的主导原则是 OCP(开闭原则),在类和代码的层级上有:SRP(单一职责原则)、LSP(里氏替换原则)、ISP(接口隔离原则)、DIP(依赖反转原则);在组件的层级上有:REP(复用、发布等同原则)、CCP(共同闭包原则)、CRP(共同复用原则),处理组件依赖问题的三原则:无依赖环原则、稳定依赖原则、稳定抽象原则。这些原则是前人大量的经验总结,比如设计模式的原则,SOLID 是几个重要编码原则的缩写:
- 开闭原则(Open Close Principle):开闭原则就是说对扩展开放,对修改关闭,在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果;
- 里氏代换原则(Liskov Substitution Principle):里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一;
- 依赖倒转原则(Dependence Inversion Principle):这个是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体;
- 接口隔离原则(Interface Segregation Principle):这个原则的意思是:使用多个隔离的接口,比使用单个接口要好,还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合;
- 迪米特法则(最少知道原则)(Demeter Principle):为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立;
- 合成复用原则(Composite Reuse Principle):该原则是尽量使用合成/聚合的方式,而不是使用继承。
3)设计模式
在编码过程中,前人抽象出来的 23 个设计模式也是很值得参考的:
【创建型模式】
- 简单工厂模式(Simple Factory)
- 工厂方法模式(Factory Method)
- 抽象工厂模式(Abstract Factory)
- 创建者模式(Builder)
- 原型模式(Prototype)
- 单例模式(Singleton)
【结构型模式】
- 外观模式(Facade)
- 适配器模式(Adapter)
- 代理模式(Proxy)
- 装饰模式(Decorator)
- 桥模式(Bridge)
- 组合模式(Composite)
- 享元模式(Flyweight)
【行为型模式】
- 模板方法模式(Template Method)
- 观察者模式(Observer)
- 状态模式(State)
- 策略模式(Strategy)
- 职责链模式(Chain of Responsibility)
- 命令模式(Command)
- 访问者模式(Visitor)
- 调停者模式(Mediator)
- 备忘录模式(Memento)
- 迭代器模式(Iterator)
- 解释器模式(Interpreter)
架构落地
说了这么多,架构如何落地?相信这个是大家最关心的,前文我们已经从整体上建立了系统设计的方法论,再从 it 领域上升到通用商务领域的设计思维,在系统设计的层面又步步为营给出了工具和剖析模型建立架构推导的一步流程。
其实到了这一步,架构设计已经到了柳暗花明的阶段了,因为我们已经已经把最核心的环节都弄通了,接下来无非对症下药,根据需求找到系统薄弱的地方,相应地使用适用的工具来发挥最大的作用。
1. 行业架构
目前大部分行业其实都已经有相对稳定成熟的应用架构,也形成了基本的套路,比如金融行业有传统的基于 IOE 的商业应用架构,也有新型互联网的去 IOE 基础上的架构,比如微服务化的流行,在即时通信的消息架构也是有成熟的解决方案。另外产业互联网各个传统行业的互联网化也可以应用边缘计算架构来实现。
2. 技术架构
行业下沉到技术架构层面,从微小企业到大型企业应用的解决方案,都逃不过网关设计,流量管理,服务治理,容错设计,监控告警,性能调优,数据管理等环节,而这方面的设计实现,业界也提供了成熟的开源解决方案,可以参考《分布式设计知识体系》一文,除了巨型企业需要自研外,多数开源的工具已经可以满足大部分需求,架构设计其实就是选择最适当的工具来解决我们的问题。
总结
系统设计犹如医生看病需要对症下药,医生需要博学多才精通药理,才能对症下药,就像架构师经验丰富,懂得各种软件工具(药)的利弊,各种设计原则和设计理论(药理)可以设计出架构图(药方),把软件工具精妙的组合在一起。
学习的最佳方式是先进行比喻,其次是模仿,最后回归到概念的本质定义。一个好的软件架构师,同样可能成为很好的 hr 专家。本文共分为三个部分从思维讲起到系统逆向分析,到后面的正向设计。从“道,理,术”三个角度诠释了系统架构设计的全面知识体系。
“阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”