架构设计的哲学

Posted 科技D人生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了架构设计的哲学相关的知识,希望对你有一定的参考价值。

1. 引言

大家好,欢迎大家来到《技术与哲学》,我是子文。本期也是我们的首期,我们将给大家分享一下关于架构设计的一些哲学理念。

2. 各种名词

在计算机领域,我们经常听到各种“架构”名词。比如:技术架构,系统架构,微服务架构……那究竟什么是架构呢? 架构和框架是一个东西么?

3. 什么是架构?

架构”一词在维基百科上是这样定义的:软件架构是指软件的基本结构以及创建此类结构和系统的规范。每个结构包括软件的元素、元素之间的关系以及元素和关系的属性。1994年,卡内基·梅隆大学的玛丽·肖(Mary Shaw)、戴维·加兰(David Garlan)在《软件架构介绍》(An Introduction to Software Architecture)中提到:“随着软件系统规模的增加,计算相关的算法和数据结构不再构成主要的设计问题;当系统由许多部分组成时,整个系统的组织,也就是所说的“软件架构”,导致了一系列新的设计问题。”

不过,我们这里更喜欢这样的一种定义或描述。那就是杰拉尔德·温伯格在《系统化思维导论》中提到过:系统是对世界的一种看法。而世界是多元的、世界是有机的、世界是变化的,并且世界并不完美。通过这个逻辑引申一下,架构就是对系统的一种看法。系统是多元的、系统是有机的、系统是变化的,并且系统并不完美。架构也就自然拥有了这些属性。在这个世界里,人们都希望完美,希望我们的事业完美,家庭完美,爱情完美……,但其实这个世界原本就不完美。

4. 架构设计的目的

架构设计到底是要解决什么问题呢?

架构设计,大到整个互联网的标准,小到一个项目的设计;在我们生活中好比:大到整个国家或一个城市的道路交通规划设计,小到一栋房屋的设计。一般来说,道路规划设计好后,一般是不会随便更改的,因为更改的成本太高,所以必须要有很长远的考虑和前瞻性。道路规划设计的好坏直接决定未来5年,10年,甚至几十年城市的交通和发展。另外一方面,道路虽然是不能改,但可以增加新的道路,或扩宽原有道路,还可以加铺沥青。从某个角度来说,也很像我们架构设计其中一条原则:对扩展开放,对修改关闭。

举个例子来说:我们的房屋设计,大致要经历:勘探测量、建筑设计、结构设计、地基、主体结构施工、砌墙、防水、水电安装、装饰装修、竣工验收等过程。如果把建筑设计比作业务架构设计,那结构设计就好比我们的技术架构设计。 业务架构设计更关注我们的系统要具备哪些业务模块和功能,各个业务模块的层级和关联关系,而技术架构则更关注为了满足业务需求,各个模块在技术上应该如何实现、如何交互,需要采用什么技术组件。

还记得之前提到过的:“随着软件系统规模的增加,计算相关的算法和数据结构不再构成主要的设计问题;当系统由许多部分组成时,整个系统的组织,也就是所说的“软件架构”,导致了一系列新的设计问题“。随着时代的进步,软件系统也越来越复杂了,记得1989年,求伯君仅凭一己之力就能开发出一套WPS系统,试问在2022年的今天,有哪个系统是一个人就能开发完成的。所以,架构设计的初衷之一就是要解决软件系统复杂度带来的问题。

架构师应当是胸怀理想的现实主义者,高度在理想,落地在现实。一名合格的架构师是需要很强的综合能力的。

架构设计是由架构师根据对业务的理解、对行业的理解、甚至对世界的认知,运用专业技术和经验,来构架和设计整个系统的框架、结构、标准、规范等。按照一定的设计方法,把系统划分成颗粒合适,边界分明,复用合理、扩展良好的系统或模块;使得开发人员能依据规范和标准进行业务逻辑的开发,实现满足业务需求的系统。

5. 什么是好的架构?

满足需求

首先最重要的就是“满足需求”。技术是为业务服务的,脱离了业务的技术都是浮云。如果连需求都不满足就更别提了,凭空想出来的架构没有任何意义。

当然,除了满足需求,实际项目中可能还有很多其他的要求,比如:安全性、性能、高可用……,这些要求是可以根据不同的业务场景有优先级的先后。

比如:在分布式环境下,对数据一致性有:强一致性和弱一致性。在很多互联网应用中,因为流量的重要性,也是站在用户体验第一的角度来考虑,常常会优先保证系统的可用性,而采用弱一致性或最终一致性。而在一些银行金融领域应用中,很多会采用强一致性,来优先保证数据和事务的一致性,提高用户的安全感。如果一个用户在提交转账后,自己账户钱少了,对方却没到账,一定会让他感到很不安心而投诉。像一些toC的系统,会要求达到7x24小时99.99%可用性,而大多企业内部系统,可能就没有这么高的要求,在半夜或非工作日里,宕机一会也不会引起太大的问题。

总之,不同的业务对我们的架构和系统是有不同的要求的。我们在设计时,可以根据业务的特点有针对性地来进行取舍。

6. IT业界格言

IT业界,传闻有8大格言,其中部分也是我们进行架构设计的一些思想和原则。比如:计算机科学中的所有问题都可以通过增加一个间接层来解决。其实中间层这个思想在计算机领域很多地方都有涉及。比如:操作系统分用户态和内核态;CPU的缓存分1级、2级、3级;TCP/IP网络模型分:网络接口层、网络层、传输层、应用层;软件框架里分DAO、Serivce、Controller等层次。分层结构让每个层次的职责单一而明确,只和自己相邻的上下层关联,让原本混在一起的模块显得更清晰明了,解决系统复杂度的问题。架构设计原则中的“单一职责原则”也有类似的思想。后面我们将对架构设计中的3大原则重点讲解一下。

7. 架构设计总原则

7.1.简单原则

简单是可靠的前提

在数学领域有个不成文的共识:如果一个问题有多个数学表示,那么最简单的表示通常是正确的。这个原则不仅适合我们的架构设计,其实在我们很多软件开发和设计时也适用。比如:为什么Redis是单线程?为什么不设计成多线程呢?二级制01最适合计算机识别呢?

其实这个世界上,很多东西都很复杂,但人类认识世界的智慧,就体现在对于世界从复杂到简单、从现象到规律、从表象到意志、由浅入深、从外及里的努力探索过程中。在认识的过程中只要掌握了规律就简单了。人类所发明的航母,火箭,飞机,CPU等等都很复杂,但在软件架构设计领域,并不是越复杂越好。有很多时候,我们希望把架构和系统设计的很精美,很完善,感觉不搞复杂一点,就好像显得没有什么技术含量。却不知大道至简,深入简出的道理。

复杂可能带来的是什么?问题。越复杂,可能出问题的概率就越高。

假设单个系统出问题的概率10%,可靠度就是90%,那么2个系统的可靠度就是90%x90%=81%;5个系统的可靠度=(1-10%)×(1-10%)×(1-10%)×(1-10%)×(1- 10%)=59%。有人说系统多了架构和系统交互太复杂,那我们就只设计一个系统可以吧。我想说这也要看业务场景。假设我们把一整套电商体系的东西放在一个系统里去实现,会怎么样?想想就知道一定将是噩梦。

所以这里,我们引出另外一个原则——合适原则。还记得我们之前说的,架构设计是要把系统划分成颗粒合适,边界分明,复用合理的系统或模块。

7.2.适合原则

合适优于业界领先

很多优秀的开发人员都想挑战自我,想实现多么多么牛的架构或组件,但殊不知,业界领先的组件或方案都是大厂里多少架构师和开发人员多年积累的成果。虽然奇迹是有的,但实现是困难的。这种往往一上来就想实现支撑多少亿的用户或并发量的项目,往往最后都已失败告终。我们应该脚踏实地,实事求是的稳步前行,根据当下我们的业务体量、人力资源、时间要求,资金成本等因素选择当下最合适的架构和技术方案。

中庸之道

中不偏,庸不易;中正、平和、中用。《中庸》原文中这样写到:“喜怒衰乐之末发谓之中,发而皆中节谓之和。中也者,天下之大本也,和也者,天下之达道也。”《周易》认为凡事应以“中”为度,反对走极端,强调事物的平衡。既不能“过”也不能“不及”,盛极必衰,否极泰来,物极必反。

其实在现代计算机领域,很多地方也都类似的有中庸的思想。比如:多线程能提高系统执行效率,但线程池的线程数并不是越多越好;加索引能提高查询速度,但表的索引也不是越多越好;微服务能降低系统耦合,服务粒度也并非越细越好。凡事都需要找到一个合适的阈值,这个就是,不偏不倚,谓之中,才合适。

选择

合适是一个很难把握的原则,什么样才算合适。这也是架构师的挑战所在。很多时候A方案和B方案都可以实现,没有好坏之分,但选择却有对错之别。那究竟哪一种才是最适合我们当下的方案呢?现实情况可能出现:拍脑袋,选最优,选熟悉,Boss决定......等等各种方法。这些方法都有不足之处,比如:选最优方案往往没有考虑实现成本和业务体量;Boss决定方案,很多Boss其实并不了解一些技术组件细节特性,只凭感觉很容易导致问题。

更科学的方法是,我们可以把各个关注的属性点列举出来,按优先级排序后,然后全方位对每个方案进行评估。哪些特性是必须满足的,哪些是可以延时满足或2年内都不需要考虑的,再结合以往的项目经验进行合理略超越当下的选择。

我们假设业务增长速度是每年100%,即一年翻一倍,2年就是4倍。系统的设计支撑容量,也可以参考这个标准来考虑,如果业务发展迅猛一年翻了10倍,那也不用太担心,业务发展如此之好,一定有更多资源来投入改造和重构系统了。

7.3.演化原则

演化优于一步到位

架构是随业务演变而演变的。在演化中,不断进行扩展、重构、甚至重写。演化就像自然进化一样,要保留优秀的设计,摒弃无用的设计,这样架构才能不断地进化,逐渐演变成优秀的架构。就像达尔文在《物种起源》中所说的:人是在数千万年里逐渐由猿演变而成的。

我们不要刚开始就寄希望设计一个大而全的架构或系统,多大体量的业务对应多大体量的架构,杀鸡千万不需要用牛刀。某公司要开发新系统,业务体量TPS为100/s,某技术同学一上来就采用分库分表组件,分了256张表,结果导致系统复杂度和维护成本过高。

不确定性

佛法上常说“诸行无常”,我们世界如此,人生如此,系统亦如此。

所谓不确定性就是指业务发展瞬息万变,很多事情无法预测,计划赶不上变化,考虑太长远可能带来资源浪费、设计复杂、成本过高等问题,最后都可能导致项目失败。我们假设业务在未来x年的发展有几种可能:1.缓慢增长,2.快速夭折,3.快速增长。选项1,既然业务发展缓慢,系统的初始设计足以满足业务需求;选项2,业务夭折,系统没有过度设计,节省了成本;选项3,业务高增长,必然有足够的资源继续投入,做系统升级和改造。

2年的原则

所谓2年原则就是指我们进行架构或系统设计一般考虑2年左右业务发展就可以。我们需要考虑架构的扩展性,但如果太长远,不确定性增大,根本无法预测。这里的2年是业界一个经验数字。据了解,某东的WMS系统,从2007年到2016年,就经历了WMS1.0,2.0,3.0,亚一WMS,WCS,ECLP,WMS5.0(X武)多代系统的发展,才逐步完善。伴随的业务的高速发展,基本上每2年左右就会做一次大的更新。又大家想想90年代Windows3.1和现在的Windows11,想想2003年的淘宝和今天的淘宝是一个系统么?

软件设计和城市道路规划设计还是有区别的。城市道路规划要尽可能考虑的长远,而软件架构设计却不能考虑的太长远。这听起来似乎有点矛盾,我们既要求系统可扩展,又不要求长远考虑。那我们究竟该如何设计呢?其实这就和具体的事项有关系了。我们这里所说的不考虑长远,是指的一般的业务软件系统架构。如果说要做一个软件标准或系统规范的设计,则是需要考虑的更长远。比如:像我们的编程语言,JDBC规范,CPU的指令集,网络通信模型等等,这些系统的设计会考虑的更长远,可能几十年过去了,当初的基本特性和功能都还如初。

所以我们要辩证的来看待和理解这些原则,就像软件工程神作《人月神话》里提到的,对于软件开发项目没有银弹,没有适合一切的原则。

系统是有生命周期的

一种生物有它的生命,一个系统也有它的生命。

笔者当年参加了某东海外一系统早期的开发和建设,开始时整个系统只有10多个虚拟节点,10多个人员开发和维护,支撑当地业务从2015年2000单/日到2018年50万单/日,因为业务的体量已经达到一定的规模,原有系统已经无法再继续支撑,才决定进行系统切换,采用更加先进的国内X龙系统,新系统有100台物理机的规模,虚拟节点多达几百个,由上百人的开发团队多年开发完成。毋庸置疑新系统肯定更先进和强大,而老系统支撑业务度过了快速成长期,也体现了它的价值和使命。

系统如此,人亦如此。我们每个人来到这个世界,开始时不知所然,但随着时间的推移和年龄的增长,我相信每个心中会逐渐浮现出一个问题:“人为什么而活?或者说人活着的意义是什么?”大家可先自行思考,咱这里就不发散了,后续会有专题来探讨这些问题。

8. 软件设计原则

软件设计的具体原则有这么多,这里我们不打算一一讲解。因为已经有太多的资料和书籍可以查阅。我们这里想谈谈这些原则背后的思想——解耦

解耦一词可以在各种软件设计书籍里见到。比如:《设计模式》、《Thinking in java》、《Head First设计模式》、《Java与模式》等等。

解耦:顾名思义,解除耦合性。

耦合:在电子学领域,指两个或两个以上的电路构成一个网络时,若其中某一电路中电流或电压发生变化,能影响到其他电路也发生类似的变化,这种网络叫做耦合电路。耦合的作用就是把某一电路的能量输送(或转换)到其他的电路中去。现在也泛指:两个或两个以上的体系或两种运动形式间通过相互作用而彼此影响以至联合起来的现象。

在维基百科上是这样解释的:在软件工程中,耦合指模块间的依赖程度,用于度量两个例程(routines)或模块间紧密程度。(In software engineering, coupling is the degree of interdependence between software modules; a measure of how closely connected two routines or modules are;the strength of the relationships between modules.)

耦合和内聚相对,低耦合往往意味着高内聚,反之亦然。低耦合是良好的计算系统或设计的特征,同时,低耦合和高内聚可实现高可靠性和高可维护性的目标。(Coupling is usually contrasted with cohesion. Low coupling often correlates with high cohesion, and vice versa. Low coupling is often a sign of a well-structured computer system and a good design, and when combined with high cohesion, supports the general goals of high readability and maintainability.)

用耦合和内聚来度量软件质量,最早在1960s有Larry Constantine在《结构化设计》中提及。The software quality metrics of coupling and cohesion were invented by Larry Constantine in the late 1960s as part of Structured Design.

这些都是一些官方的定义或解释,比较绕口不太好理解。其实我们简单理解:耦合就是有关联。那么解耦就是要解除关联

高内聚、低耦合

在软件领域,零耦合是不可能的,解耦就是要尽量解除不必要的关联,让系统(模块、类)之间的耦合度降到最低,保持高内聚、低耦合的特性,从而使系统在未来的发展和演变中,不至于牵一发而动全身。我们的软件设计原则都是为了这个目标,结合以往的项目经验总结出来的一些规则。解耦的范畴可大可小:大到系统,模块,小到类、函数、方法。

9. 设计的哲学

我们的世界和计算机的世界

虽然计算机是一种人造的产物,但它的很多设计思想,都来源于我们的世界,终究也无法脱离这个世界。

比如:我们人类的大脑在同一时间只能思考一件事情。记得金庸的武侠小说《射雕英雄传》里有这么一种武学,叫“左右手互博术”。需要一个人能同时左手画圆右手画方就可以习得,但此类人世间罕见。不信的你也不妨试试,即使少数人能侥幸成功,但实际上你的大脑也是在不停的切换,在不同时间片里分别执行左手和右手的动作。

我们再想想计算机的大脑——CPU,不也正是这样吗?同一时间只能运行一个进程,如果要运行多个进程,也需要将时间片分片执行,当然这里指的单核CPU。我们再想想,当一个人一天只做一件事时,效率很高,能很快的完成任务,但当分配给他同时做多件事时,居然也能完成多个任务,看似效率更高了,实际上只是多任务占用了他的空闲时间而已。CPU也是如此,多线程执行时,看似提高了CPU(单核)的利用率,其实是CPU空闲时间变少了而已。当继续给CPU增加任务数时,CPU就会显得不堪重负而卡顿,因为上下文切换要耗费大量的时间。我们人类不也是这样,当手头事情多了,就会变得忙乱和丢三落四的,反而效率不高。

我们熟悉的冗余备份机制,其实在我们人体里就有很多的体现,比如我们的肾脏、肺、乳房等等都是两个。理解我们的世界将有助于理解我们的计算机领域里很多设计思想。

设计思想

我们学习架构和软件设计,最重要的就是学习这些思想。比如:多路多道,在操作系统的多进程、多线程、多任务,网络模型里的多信道,多连接,多并发等方面均有体现,但其背后的根本都是采用多路多道的思想来提高系统的吞吐量或性能。理解和掌握了这些思想才是真的掌握了架构设计的内功心法。

我们知道:分布式一致性算法有很多种,但Google Chubby的作者Mike Burrows说过,世上只有一种一致性算法,那就是Paxos,所有其他一致性算法(Chubby,Raft,ZAB,微信的PhxPaxos等)都是Paxos算法的不完整版。

天下武功,不是唯快不破,而是绝招同途异路。从某种意义上来说,这些思想就是“”,《道德经》有云:“道沖,而用之或不盈。”。就是一种规则规律。它来源于我们这个世界,也同样适用于计算机领域。我们只有掌握和遵循了这些思想和规律,才能设计出好的系统架构。

10. 终极原则

很喜欢金庸小说《笑傲江湖》里的一门武学,名叫“独孤九剑“:四十岁后,不滞于物,草木竹石均可为剑。自此精修,渐进于无剑胜有剑之境。或许这才是武学的最高境界吧。那么架构设计的最高境界或终极原则是什么呢?我认为是“没有规则”。没有规则并不是没有规则,而是不拘泥于规则,不局限于规则。我们应根据实际业务场景,灵活应用规则,甚至超越规则。对系统设计理念和各种原则了然于胸,融会贯通,不生搬硬套。最后,我们用《金刚经》里的一句话语来阐述:所谓规则,即非规则,是名规则。所谓的规则,其实并不是什么规则,只是名字叫规则而已。我们不要过于执着于一条条的规则。当一个技术人员“忘掉”所有的架构设计规则时,他就成为了顶尖的架构师了。

11. 结束

各位朋友,本次的分享就到此结束了,希望对你有所有帮助。喜欢朋友们可以点击关注或在公共区留言。后面我将会给大家带来更多关于技术与哲学的理念和思考

以上是关于架构设计的哲学的主要内容,如果未能解决你的问题,请参考以下文章

程序员架构修炼之道:架构设计中的人文主义哲学

架构设计的哲学

架构设计与拆分的哲学

设计模式与哲学

云原生的设计哲学

自动驾驶网络系列二: 从哲学源头开始思考架构设计