架构

知其然,知其所以然。

Posted by ARay on March 8, 2018

买了新机器,忽然想学点啥技能了。

忽然想到 iPad上有个教编程的app Swift Playgrounds ,好像把编程的门槛一下子降低了很多,Mac上似乎只要装上Xcode就可以玩……

首先下载了《Swift Programming Language》,这是基本的语法参考书。

然后再看看 10个最佳的 Swift 教程实例 ,发现看不懂……

语法不明白还可以学,但是这一堆文件之间的关系理不清楚,不明白之间的关系的话,我觉得这种实例照着做完了也是一头雾水。

就好像我做规划设计画建筑图一样,总要理清楚一个先后秩序,有了全盘规划之后才能具体地进行设计。

我得先了解一下做一个APP或者说做一个软件的基本架构才行……

当然,只是针对自己做一个供自己使用的APP来理解。


什么是架构?

架构的英文是Architecture,在Wikipedia上,架构是这样定义的:

Architecture (Latin architectura, from the Greek ἀρχιτέκτων arkhitekton”architect”, from ἀρχι- “chief” and τέκτων “builder”) is both the process and the product of planning, designing, and constructing buildings and other physical structures。

从这个定义上看,架构好像是一个过程,也不是很清晰。

怎么定义架构呢?把一个整体切分成不同的部分(分工),由不同角色来完成这些分工,并通过建立不同部分相互沟通的机制,使得这些部分能够有机的结合为一个整体,并完成这个整体所需要的所有活动,这就是架构。

架构产生的动力

1.必须由人执行的工作(不需要人介入,就意味着不需要改造,也就不需要架构了)

2.每个人的能力有限(每个人都有自己的强项,个人的产出受限于最短板,并且由于人的结构限制,同时只能专注于做好一件事情,比如虽然有两只眼睛,但是只能同时专注于一件事物,有两只手,无法同时做不同的事情。ps. 虽然有少部分人可以左手画圆右手画框,但是不是普遍现象)

3.每个人的时间有限(为了减少时间的投入,必然会导致把工作分解出去,给擅长于这些工作的角色来完成,见2,从而缩短时间)

4.人对目标系统有更高的要求(如果满足于现状,也就不需要进行架构了)

5.目标系统的复杂性使得单个人完成这个系统,满足条件2,3(如果个人就可以完成系统的提高,也不需要别的人参与,也就不需要架构的涉及,只是工匠,并且一般这个工作对时间的要求也不迫切。当足够熟练之后,也会有一定的架构思考,但考虑更多的是如何提高质量,提高个人的时间效率)

当这5个条件同时成立,一定会产生架构。

从这个层面上来说,架构是人类发展过程中,由懵懵懂懂的,被动的去认识这个世界,变成主动的去认识,并以更高的效率去改造这个世界的方法。

根据我的专业,用建筑方面来理解的话……

建筑的本质就是从自然环境中,划出一块独占的空间,但是仍然能够通过门窗等和自然环境保持沟通。

这个时候架构就已经开始了。

对地球上的空间进行切分,并通过门窗,地基等,保持和地球以及空间的有机的沟通。当人类开始学会用火之后,茅棚里面自然而然慢慢就会被切分为两部分,一部分用来烧饭,一部分用来生活。当人的排泄慢慢移入到室内后,洗手间也就慢慢的出现了。这就是建筑内部的空间切分。

这个时候人对建筑的需求也就慢慢的越来越多,空间的切分也会变成很多种,组合的方式也会有很多种,比如每个人住的房子,群居所产生的宗教性质的房子,集体活动的房子等等。

这个时候人们就开始有意识的去设计房子,架构师就慢慢的出现了。

一切都是为了满足人的越来越高的需求,提升质量,减少时间,更有效率的切分空间,并且让空间之间更加有机的进行沟通。

这就是建筑的架构以及建筑的架构的演变

那么再来总结一下

架构就是:

1.根据要解决的问题,对目标系统的边界进行界定。
2.并对目标系统按某个原则的进行切分。切分的原则,要便于不同的角色,对切分出来的部分,并行或串行开展工作,一般并行才能减少时间。
3.并对这些切分出来的部分,设立沟通机制。
4.根据3,使得这些部分之间能够进行有机的联系,合并组装成为一个整体,完成目标系统的所有工作。

认识概念是理解架构的基础

架构实际上解决的是人的问题,而概念是人认识这个世界的基础,自然概念的认识就非常的重要。

概念也属于人认识这个世界并用来沟通的手段,包括“概念”这个概念,也是一样的。在古代,不叫“概念”,称之为“名相”。

何为相?

一般我们认为:看到一个东西,比方说杯子,“杯子”就是一个名字,指代的看到的东西就是相,就是事物的相状。我们一听到“杯子”这个词,脑海里就会浮现出一个杯子的形象。而“杯子”这个是用来指代的是这个相状的,叫做名。合起来就叫做“名相”。

可是当我们把杯子打碎了的时候,我们还会称这个碎了的东西叫杯子吗? 肯定不会,一般会叫“碎瓦片”,如果我们把碎瓦片磨碎了呢,名字又变了,叫做“沙子”。这就奇怪了,同样一个东西,怎么会变出这么多的名字出来?

那究竟什么才是相?

实际上“相“表达的不是一个具体的东西,如上面所提的一个瓷器杯子,并不是指这个瓷器,而是这个瓷器所起的一个作用:一手可握,敞口(一般不超过底的大小,太大口就叫碗了),并且内部有一个空间可乘东西的这么一个作用。并不是指这个瓷器本身。这也是为什么我们从电视上看到一个人拿杯子的时候,我们知道这个是杯子。但是实际上我们看到的都是光影而已。所以说相实际上代表的是这个作用并不是具体的某个东西,而名是用来标识这个作用的用来交流的

为何需要这个作用?

这个作用其实是为了解决“人需要一个可单手持握,但是希望避免直接接触所盛物体”这个问题。

所以说,每个概念实际上所解决的,还是人遇到的某个特定的问题,**我们把解决问题的解决方案**,**给定了一个名字**,**这个名字就是对应的某个特定的概念**。对于概念这个词本身,为了统一指代这些名字,我们称起这类作用的名字称为“概念”

“架构”也是是同样的一个特定概念。

为何我们可以在不同的语言间进行翻译,是因为虽然语言不同,但是人类所面临的的问题是一样的,所使用的名不同而已。

对于不同的事物之间的翻译也是同理。

关于抽象

抽象这个词代表的含义,实际上是把不同的概念的相似的部分合并在一起形成一个新的概念

首先“相似的部分”在不同的人看来,并不一定那么相似;其次,抽象之后形成的是一个新的概念,和原来那个概念并不一样,所解决的问题也不一样。

所以我们不能用抽象来定义一个事物抽象实际上是一个分类的过程,完全是另一码事。举一个例子,杯子和容器,很多人认为容器是杯子的抽象,但是实际上杯子是杯子,容器是容器,它们所解决的问题是不一样的。当我们需要解决装东西的问题的时候,会说容器;当我们需要解决单手持握要装东西的时候,会说要一个杯子。

根据架构的定义,要做好架构所首先必须具备的能力,就是能够正确的认识概念,能够发现概念背后所代表的问题,进而才能够认识目标领域所需要解决的问题,这样才能够为做好架构打好基础。

这一能力,在任何一个领域都是适用的,比如我们如果想要学习一项新的技术,如Hibernate、Spring、PhotoShop、WWW、Internet等等,如果知道这些概念所要解决的问题,学习这些新的技术或者概念就会如虎添翼,快速的入手,学习一个新的领域,也会非常的快速有效;

使用这些概念来解释问题,甚至发明新的概念都是很容易的事。

为什么强调这个呢,因为做架构的时候,很多时候都是在一个新的领域解决问题,必须要快速进入并掌握这个领域,然后才能够正确的解决问题。

如何有效的去认识概念,明白概念背后的含义,以及如何利用对概念的理解,快速的进行学习。

掌握了这些原则,在架构阶段,会有利于快速的识别和定位问题。


如何做好架构之识别问题

做好架构首先需要做的就是识别出需要解决的问题

如果把真正的问题找到,那么问题就已经解决了80%了。

面对问题有哪些困难呢?

先看一则笑话。

女主人公:老公,把袋子里的土豆切一半下锅。

结果老公是把袋子里的每个土豆都削了一半,然后下锅。

当然很多人会说,这个是沟通问题,然后一笑了之。

其实,出现这个现象是由于我们大部分时候过于关注解决问题,急于完成自己的工作,而不关心“真正的问题是什么”而造成的。

当我们去解决一个问题的时候,一定要先把问题搞清楚

去看看软件开发工作者的时间分配也可以看出,大家大部分时间花在讨论解决方案和实现的细节上,基本都不会花时间去想“问题是什么”。或者即使想了一点点,也是一闪而过,凭自己的直觉下判断。

只有真正投入思考问题是什么的工程师,才可能会真正的成长为架构师。

在我们处理问题的时候,都会犯什么样的错误:

  1. 被告知要处理一个问题,但是交过来的实际上是一个解决方案,不是问题本身
  2. 被告知要处理一个问题,直接通过直觉就有了一个解决方案,马上考虑解决方案如何落地,或者有几种解决方案,选哪个合适

那么如何识别问题?

所有的概念基本都有一个很大的问题,就是缺乏主语

而我们大家都心照不宣的忽略这个主语,沟通的时候也都以为大家都懂得对方说的主语是谁,结果大家都一起犯错误。

识别问题的一个最大的前提就是要搞清楚:是谁的问题

这个搞清楚了,问题的边界也就跟着确定了,再去讨论问题才有意义。

找出问题的主体,是做架构的首要问题。

要解决的问题,一定都是人的问题。

更进一步,架构师要解决的,基本都是别人的问题,不是自己的问题。

再进一步,任何找上架构师的问题,绝对都不是真正的问题。

自己做一个APP自娱自乐自己用,那么就是解决自己的问题。

自己对自己的需求是最清楚的,也是最容易解决的。

发现问题永远都比解决问题来的更加重要。

了解自己的需求以及完全满足自己的使用要求是一个发现问题后在不断深化和细化的过程中引申出其他问题以及解决问题的过程。

翻墙出去来举例的话:

需要翻墙出去”,这是最根本的问题,这个问题的主体是:**如何满足自己翻墙的需求**

接下来才是由此引申出来的相关问题:需要采取什么手段来解决翻墙的问题以及采取何种方法可以在解决自己翻墙要求的同时,满足自己的其他要求的问题

首先,明确自己最基本的需求:

  • 翻墙

然后再细化自己的需求:

  1. 稳定的翻墙;
  2. 稳定的翻墙的同时保证网速
  3. MaciPhone都能稳定翻墙并且保证网速;
  4. 电脑和手机都能稳定翻墙并且保证网速的同时,实现国内外网站分流

这时候才出现了最终完整的需求:

  • 让Mac和 iPhone能稳定翻墙并且保证网速的同时,实现国内外网站分流

最后筛选比较各种解决方法:

  1. 最基本的解决方案:在Mac和iphone上设置VPN
    1. 基本解决了翻墙的问题,~~但不能保证网速~~
  2. 进阶的解决方案:在Mac和iphone上安装 cisco anyconnect
    1. 解决了翻墙的问题,能保证网速,~~不能实现分流~~
  3. 高阶的解决方案:在Mac和iphone上安装 Surge
    1. 解决了翻墙的问题,能保证网速,通过自定义规则实现分流。

最终选用方法3来解决问题。


架构切分

在识别出是谁的问题之后,会发现,在大部分情况下,问题都迎刃而解,不需要做额外的动作。

很多时候问题的产生都是因为沟通的误解,或者主观上有很多不必要的利益诉求导致的。

但是总还有一部分确实是有问题的,需要做调整,那么就必须要有所动作,做相应的调整。

这个调整就是架构的切分。

切分就是利益的调整

所有的切分调整,都是对相关人的利益的调整。

为什么这么说呢,因为维护自己的利益,是每个人的本性,是在骨子里面的,我们不能逃避这一点。

随着社会的发展,分工是必然的,为什么呢? 这个背后的动力就是每个人自己的利益。每个人都希望能够把自己的利益最大化,但是每个人的能力和时间都非常的有限,不可能什么都懂,所以自然需要舍掉一些自己不擅长的东西,用自己擅长的东西去换取别人擅长的东西。

对比一个人干所有的事情,结果就是大家都能够得到更多,当然也产生了一个互相依赖的社会,互相谁都离不开谁。这就是自然而然而产生的架构切分,背后的原动力就是人们对自己利益的渴望。人们对自己利益的渴望也是推动社会物质发展的原动力。

在这个模式下,比较有意思的是,每个人必须要舍掉自己的东西,才能够得到更多的东西。有些人不愿意和别人进行交换,不想去依赖于别人,这些人的生活就很明显的差很多,也辛苦很多,自然而然的就被社会淘汰了。如果需要在这个社会上立足,判断标准就变成了:如何给这个社会提供更好更有质量的服务。提供的更好更多的服务,自然就能够换取更多更好的生活必需品。实际上这就是我们做人的道理。

为什么需要切分?

当人们认识到要主动的去切分一个系统的时候,毫无疑问,我们不能忘掉利益这个原动力。所有的切分决策都不能够违背这一点,这是大方向。

一旦确定了问题的主体,那么系统的利益相关人(用现代管理学语言叫:stockholder)就确定了下来。

所发现的问题,会有几种情况:

  1. 某个或者某些利益相关人负载太重。
    1. 时间上的负载太重。
    2. 空间上的负载太重,本质上还是时间上的负载太重。
  2. 某个或者某些利益相关人的权利和义务不对等。

切分的原则

情况1是切分的原因,情况2是切分不合理而导致的新的问题,最终还是要回到情况1。

对于情况1,本质上都是时间上的负载。

因为每个人的时间是有限的,怎么在有限的时间内做出更多的事情?那么只有把时间上连续的动作,切分成时间上可以并行的动作,在空间上横向扩展。

所以切分就要有几个原则:

  1. 必须在连续时间内发生的一个活动,不能切分。
  2. 切分出来的部分的负责人,对这个部分的权利和义务必须是对等的。为什么必须是这样呢? 因为如果权利和义务是不对等的话,会伤害每个个体的利益,分出来执行的效率会比没有分出来还要低,实际上也损害了整体的利益,这违背了提升整体利益的初衷。
  3. 切分出来的部分,不应该超出一个自然人的负载。当然对于每个人的能力不同,负载能力也不一样,需要不断的根据实际情况调整,这实际上就是运营。
  4. 切分是内部活动,内部无任怎么切,对整个系统的外部应该是透明的。如果因为切分导致整个系统解决的问题发生了变化,那么这个变化不属于架构的活动。当然很多时候当我们把问题分析的比较清楚的时候,整个系统的边界会进一步的完善,这就会形成螺旋式的进化。但这不属于架构所应该解决的问题。进化的发生,也会导致新的架构的切分。

原则2是确保我们不能违反人性,因为维护自己的利益,是每个人的本性。只有权利和义务对等才能做到这一点。从原则2的也可以推理,所有的架构分拆,都应该是形成树状的结果,不应该变成有向图,更不应该是无向图。很多人一谈架构,必谈分层,但是基本上都没意识到,是因为把一个整体分拆为了一棵树,因为有了树,才有层。

从某种意义上来说,谈架构就是谈分层,从根节点下来,深度相同的是同一层。

切分与建模

实际上切分的过程就是建模的过程,每次对大问题的切分都会生成很多小问题,每个小问题就形成了不同的概念。


软件架构到底是要解决什么问题?

什么是软件架构呢?先来看看是什么问题,是谁的问题。

要解决谁的问题?

软件实际上就是把现实生活模拟到计算机中,并且软件是需要在计算机的硬件中运行起来的。

要做到这一点需要解决两个问题:

一、业务问题

具体的现实生活状态下,没有软件的时候,所解决的问题的主体是谁,解决的是什么问题,是如何解决,如何运作的?

二、计算机问题

  1. 如何把现实生活用软件来模拟?
  2. 模拟出来的软件,需要哪些硬件设施才能够满足要求? 并且当访问量越来越大的时候,软件能否支持硬件慢慢长大,性能线性扩展?
  3. 因为硬件是可能会失效的,软件如何在硬件失效的情况下,仍然能够保证可用性,让用户能够不中断的访问软件提供的服务?
  4. 怎么收集软件产生的数据,为下一阶段的工作提供依据?

分别是谁的问题呢?

  1. 业务的owner需要提升业务的效率,降低业务的成本,这是动机。这个实际上就是业务的问题,所以一般软件开发的出发点就在这里。
  2. 是软件工程师的问题,要解决业务owner把业务虚拟化的问题,并且要解决软件开发和运营的生命周期的问题。

分别有什么问题?

  1. 业务问题的本质,是业务所服务的对象的利益问题,明白了这个,就很容易搞清业务的概念和组织方式。再次强调一下,有了软件,可以降低业务的成本,没有软件的情况下,业务是一样跑的。如果只是为了跟风要用软件,说不定反而提高了成本,这个是采用软件之前首先要先搞清楚的。我们经常说软件和技术是业务的enabler,实际就是把原来成本很高的降到到了很低的程度而已,并不是有了什么新的业务。另外软件也不是降低业务成本的唯一方式。
  2. 为了能够让软件很好的跑起来,软件工程师必须理解业务所服务的对象,他们的利益所在,即业务问题。业务面对这些问题是如何分拆解决的? 涉及到了哪些概念? 这些概念分别解决了哪些哪些问题? 我们不能自己按照自己的理解,用自己的一套概念体系来表述。如果这么做的话,会导致两个问题:
    1. 业务无法和我们交流,因为他们无法明白我们所自己创建的概念,所以他们无法确认我们的理解是否正确。
    2. 我们所表述的东西,并没有在实际生活中实践过,我们也不知道这些概念是否能够解决业务的问题。
  3. 软件工程师还必须要考虑,用什么样的硬件把软件跑起来,怎样跑得好,跑得快,并且可以随着业务的流量逐渐的长大?

分析问题

对于2,在有限的时间下,软件工程师毫无疑问无法一个人去完成这么多事情,那么我们需要把所做的事情列出来,进行分析。

一、虚拟化业务需要完成这些事情:

  1. 学习业务知识,认识业务所涉及的stakeholders的核心利益述求,以及业务是如何分拆满足这些利益述求,并通过怎样的组织架构完成整个组织的核心利益的,以及业务运作的流程,涉及到哪些概念,有哪些权利和责任等。
  2. 通过对业务知识的学习,针对这些概念所对应的权利和责任以及组织架构,对业务进行建模,把并把建模的结果用编程语言实现。这是业务的模型,通常是现实生活中利益斗争的结果,是非常稳定的。
  3. 学习业务所参与的stakeholder是如何和业务打交道,并完成每个人的权利和义务的,并通过编程语言,结合业务模型实现这些打交道的沟通通道。这部分是变化最频繁的,属于组合关系。明白了这一点,对后续的实现非常有帮助。
  4. 如何把业务运行的结果,持久化,并通过合适的手段把持久化后的数据,在合适的时间合适的地点加载出来。这部分和基础设施有关,变化可能也会比较频繁。

二、代码如何运营,需要完成这些事情:

  1. 需要多少硬件设备来满足访问的需求?
  2. 代码要分成多少个组件部署到哪些硬件设备上?
  3. 这些代码如何通过硬件设备互相连接在一起?
  4. 当业务流量增大到超过一台机器的容量时,软件能否支持通过部署到新增机器上的方式,扩大对业务的支撑?
  5. 当某台或某些硬件设备失效时,软件是否仍然能够不影响用户的访问。
  6. 软件运行产生的数据,能否支持提取出来并加以分析,为下一轮的业务决策提供依据。

三、如果分成不同的角色来完成这些事情,就需要一个组织架构来组织代码的编写和运营,需要做哪些事情:

  1. 完成一和二所列的这些事情,需要哪些角色参与?
  2. 这些事情基本都需要顺序的发生,如何保证信息在不同角色的传递过程中不会有损失? 或者说即使有损失,也能快速纠正?
  3. 这些角色之间是如何协调,才能共同完成虚拟化业务的需求?

会生成哪些架构

如果业务足够简单,用户流量够小,时间要求也不急迫,那么一个人,一台机器就够了,这个时候一般不会去讨论架构的问题。当访问的流量越来越大,机器就会越来越多,代码的部署单元就会拆分的越来越多。

同样就会需要越来越多的人来完成拆分出来的越来越多的部署单元,甚至同一个部署单元也需要分拆为多人合作完成。

但是我们需要注意到一点,整个的概念体系,或者说业务的建模不会有任何的变化,还是完成同样的这些事情。

唯一的区别就是量越来越大,超过了单个人和单个机器的容量,不断地增长。这样就会导致以下的架构:

  1. 当流量越来越大,我们就会发现,软件所部属的机器就会开始按照树状的结构开始分拆,就会形成硬件的部属架构。这就是为什么会形成部署的分层。
  2. 为了把业务在软件中实现并落地,需要前端人员、业务代码人员、存储层等不同技巧的人同时工作,需要切分成代码的架构。这就是为什么会形成代码的分层,形成代码的架构。当然,当这些角色由一个人来完成的时候,不一定会有代码架构,往往会比较乱。
  3. 当参与的人员越来越多,就会形成开发体系的组织架构。因为代码开发的过程是一个连续的过程,会用流程来吧不同的角色串联起来,这就是软件工程。
  4. 为了完成业务的工作,需要识别出来业务架构和支撑业务的组织架构,以及业务运作的流程。这是被虚拟化的业务架构和组织架构,也需要体现在代码中,保持和现实生活中一致。

什么是软件架构

这就是软件比较复杂的地方,涉及到软件本身的业务体系,和所虚拟的业务体系。

根据以上的分析,所生成的架构,究竟那些算是软件架构呢?

  1. 软件因为流量增大而分拆成不同的运行单元,在不同的机器上部署所形成的架构,属于软件架构。
  2. 每个运行单元为了让不同角色的人,比如前端,业务,数据存储等能够并行工作,所分成的代码架构,也属于软件架构。

所以当我们说软件架构的时候,我们一定要讲清楚,究竟说的是部署的架构,还是代码的架构。

软件架构的落地,需要软件的组织架构和流程来保障,离开了这个,软件架构是一句空话。

架构实际上是在量不断的增大,超过了单台服务器的容量,逐渐的分拆,同时导致超过单个人员的能力,工作人员不断的增多,工作内容不断的分拆形成的。

这本身就是架构的意义所在。

不管怎么分拆,所达到的目标没有任何变化,就是完成业务在计算机中的虚拟化。