健客,架构师岗位二面,你觉得软件设计的原则是什么?(架构设计的方法论)

前言

大家有没有发现,高职位的岗位,八股文的技术题面试就越少,反而更多的是考察面试者工作上的心得及经验总结。一位前同事分享了他面试健客的经历,当时他面试的岗位是架构师,面试官问他:作为架构师,架构设计的方法论或者设计的原则是什么?当时这位同事回答的不是很好,因为在平常的工作中,很少会总结这方面的知识,面试结果也可想而知。应前同事的要求,有必要总结一下那些业界知名,给我留下深刻印象的软件架构设计原则及一些经验总结,和大家一起分享。


一. 架构到底是什么

我们可能经常会听到有人说架构一词,但是到底什么是架构,却很少有人说的清楚。

其实架构无处不在,它不只在计算机中存在,它在我们生活当中也很常见,比如我们着手解决一些问题,首先要计划一套方案,一套流程,这些方案和流程其实就是一种架构。

在软件系统中,架构是非常重要的一部分,它统领各个模块的开发和合作,项目从研发到上线运营,我们要在不同的方案中选择合适的架构,比如,我们服务器使用什么操作系统?使用什么语言开发?数据如何获取和存储?客户端使用什么框架开发?

软件架构指软件系统的“基础结构”,创造这些基础结构的准则,以及对这些结构的描述。参考维基百科的定义,我将架构重新定义为:软件架构指软件系统的顶层结构

通俗一点的说法就是,可以把软件架构理解成一栋房子的框架,与现实生活中的房子有异曲同工之处,这个框架有很多个大大小小的房间,每个房间可以放各种类型的东西。

二. 架构设计的目的

通过熟悉和理解需求,识别系统复杂性所在的地方,然后针对这些复杂点进行架构设计。架构设计并不是要面面俱到,不需要每个架构都具备高性能、高可用、高扩展等特点,而是要识别出复杂点然后有针对性地解决问题。

即架构设计的主要目的是为了解决软件系统复杂度带来的问题。


三. 架构设计的六大基本原则

1. 单一职责原则(Single Responsibility Principle - SRP)

译文:永远不应该有多于一个原因来改变某个类。

理解:对于一个类而言,应该仅有一个引起它变化的原因。说白了就是,不同的类具备不同的职责,各施其责。这就好比一个团队,大家分工协作,互不影响,各做各的事情。

应用:当我们做系统设计时,如果发现有一个类拥有了两种的职责,那就问自己一个问题:可以将这个类分成两个类吗?如果真的有必要,那就分吧。千万不要让一个类干的事情太多!

2. 开放封闭原则(Open Closed Principle - OCP)

译文:软件实体,如:类、模块与函数,对于扩展应该是开放的,但对于修改应该是封闭的。

理解:简言之,对扩展开放,对修改封闭。换句话说,可以加扩展类,但不要去修改类。

应用:当需求有改动,要修改代码了,此时您要做的是,尽量用继承或组合的方式来扩展类的功能,而不是直接修改类的代码。当然,如果能够确保对整体架构不会产生任何影响,那么也没必要搞得那么复杂了,直接改这个类吧。

3. 里氏替换原则(Liskov Substitution Principle - LSP)

译文:使用基类的指针或引用的函数,必须是在不知情的情况下,能够使用派生类的对象。

理解:父类能够替换子类,但子类不一定能替换父类。也就是说,在代码中可以将父类全部替换为子类,程序不会报错,也不会在运行时出现任何异常,但反过来却不一定成立。

应用:在继承类时,务必重写(Override)父类中所有的方法,尤其需要注意父类的 protected 方法(它们往往是让您重写的),子类尽量不要暴露自己的 public 方法供外界调用。

4. 迪米特法则(Least Knowledge Principle - LKP)

译文:只与你最直接的朋友交流。

理解:尽量减少对象之间的交互,从而减小类之间的耦合。简言之,一定要做到:低耦合,高内聚。

应用:在做系统设计时,不要让一个类依赖于太多的其他类,需尽量减小依赖关系,否则,您死都不知道自己怎么死的。

5. 接口隔离原则(Interface Segregation Principle - ISP)

译文:一个类与另一个类之间的依赖性,应该依赖于尽可能小的接口。

理解:不要对外暴露没有实际意义的接口。也就是说,接口是给别人调用的,那就不要去为难别人了,尽可能保证接口的实用性吧。她好,我也好。

应用:当需要对外暴露接口时,需要再三斟酌,如果真的没有必要对外提供的,就删了吧。一旦您提供了,就意味着,您将来要多做一件事情,何苦要给自己找事做呢。

6. 依赖倒置原则(Dependence Inversion Principle - DIP)

译文:高层模块不应该依赖于低层模块,它们应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象。

理解:应该面向接口编程,不应该面向实现类编程。面向实现类编程,相当于就是论事,那是正向依赖(正常人思维);面向接口编程,相当于通过事物表象来看本质,那是反向依赖,即依赖倒置(程序员思维)。

应用:并不是说,所有的类都要有一个对应的接口,而是说,如果有接口,那就尽量使用接口来编程吧。

将以上六大原则的英文首字母拼在一起就是 SOLID(稳定的),所以也称之为 SOLID 原则。只有满足了这六大原则,才能设计出稳定的软件架构!但它们毕竟只是原则,有些时候我们还是要学会灵活应变,千万不要生搬硬套,否则只会把简单问题复杂化。

四. 架构设计心得

前几年一直担任架构师的岗位,对软件架构设计有一定的心得,小编认为架构设计时遵循以下三个原则,有助于你做出最好的选择:合适原则、简单原则、演化原则

1、合适原则

合适原则宣言:“合适优于业界领先”。

再好的梦想,也需要脚踏实地实现!这里的“脚踏实地”主要体现在下面几个方面。

1. 将军难打无兵之仗

没那么多人,却想干那么多活,是失败的第一个主要原因。

2. 罗马不是一天建成的

没有那么多积累,却想一步登天,是失败的第二个主要原因。

3. 冰山下面才是关键

没有那么卓越的业务场景,却幻想灵光一闪成为天才,是失败的第三个主要原因。

所以,真正优秀的架构都是在企业当前人力、条件、业务等各种约束下设计出来的,能够合理地将资源整合在一起并发挥出最大功效,并且能够快速落地。这也是很多 BAT 出来的架构师到了小公司或者创业团队反而做不出成绩的原因,因为没有了大公司的平台、资源、积累,只是生搬硬套大公司的做法,失败的概率非常高。

2、简单原则

简单原则宣言:“简单优于复杂”。

刚才我聊的这些原因,会在潜意识层面促使初出茅庐的架构师,不自觉地追求架构的复杂性。然而,“复杂”在制造领域代表先进,在建筑领域代表领先,但在软件领域,却恰恰相反,代表的是“问题”。

软件领域的复杂性体现在两个方面:

1. 结构的复杂性

结构复杂的系统几乎毫无例外具备两个特点:

组成复杂系统的组件数量更多;

同时这些组件之间的关系也更加复杂。

结构上的复杂性存在的第二个问题是,某个组件改动,会影响关联的所有组件,这些被影响的组件同样会继续递归影响更多的组件。这个问题会影响整个系统的开发效率,因为一旦变更涉及外部系统,需要协调各方统一进行方案评估、资源协调、上线配合。

结构上的复杂性存在的第三个问题是,定位一个复杂系统中的问题总是比简单系统更加困难。首先是组件多,每个组件都有嫌疑,因此要逐一排查;其次组件间的关系复杂,有可能表现故障的组件并不是真正问题的根源。

2. 逻辑的复杂性

逻辑复杂的组件,一个典型特征就是单个组件承担了太多的功能。以电商业务为例,常见的功能有:商品管理、商品搜索、商品展示、订单管理、用户管理、支付、发货、客服……把这些功能全部在一个组件中实现,就是典型的逻辑复杂性。

逻辑复杂几乎会导致软件工程的每个环节都有问题,假设现在淘宝将这些功能全部在单一的组件中实现,可以想象一下这个恐怖的场景:

系统会很庞大,可能是上百万、上千万的代码规模,“clone”一次代码要 30 分钟。

几十、上百人维护这一套代码,某个“菜鸟”不小心改了一行代码,导致整站崩溃。

需求像雪片般飞来,为了应对,开几十个代码分支,然后各种分支合并、各种分支覆盖。

产品、研发、测试、项目管理不停地开会讨论版本计划,协调资源,解决冲突。

版本太多,每天都要上线几十个版本,系统每隔 1 个小时重启一次。

线上运行出现故障,几十个人扑上去定位和处理,一间小黑屋都装不下所有人,整个办公区闹翻天。

综合前面的分析,我们可以看到,无论是结构的复杂性,还是逻辑的复杂性,都会存在各种问题,所以架构设计时如果简单的方案和复杂的方案都可以满足需求,最好选择简单的方案。

但是,事实上,当软件系统变得太复杂后,就会有人换一个思路进行重构、升级,将它重新变得简单,这也是软件开发的大趋势。 简单原则是一个朴素且伟大的原则,Google的MapReduce系统就采用了分而治之的思想,而背后就是将复杂问题转化为简单问题的典型案例。

3、演化原则

演化原则宣言:“演化优于一步到位”。

如果没有把握“软件架构需要根据业务发展不断变化”这个本质,在做架构设计的时候就很容易陷入一个误区:试图一步到位设计一个软件架构,期望不管业务如何变化,架构都稳如磐石。为了实现这样的目标,要么照搬业界大公司公开发表的方案;要么投入庞大的资源和时间来做各种各样的预测、分析、设计。无论哪种做法,后果都很明显:投入巨大,落地遥遥无期。更让人沮丧的是,就算跌跌撞撞拼死拼活终于落地,却发现很多预测和分析都是不靠谱的。

软件架构设计其实更加类似于大自然“设计”一个生物,通过演化让生物适应环境,逐步变得更加强大。

大到人类社会、自然生物,小到一个细胞,似乎都遵循这一普世原则,软件架构也不例外。业务在发展、技术在创新、外部环境在变化,这一切都是在告诫架构师不要贪大求全,或者盲目照搬大公司的做法。应该认真分析当前业务的特点,明确业务面临的主要问题,设计合理的架构,快速落地以满足业务需要,然后在运行过程中不断完善架构,不断随着业务演化架构。怀胎需要十月,早一月或晚一月都很危险。

架构即决策。架构需要面向业务需求,并在各种资源(人、财、物、时、事)约束条件下去做权衡、取舍。而决策就会存在不确定性。采用一些高屋建瓴的设计原则有助于去消除不确定,去逼近解决问题的最优解。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容