转载

架构设计原则之我见(一):反思 KISS 原则

写在前面

在架构设计的领域,人们总结出了很多原则。这些原则的用语大都很简略,容易传播。但是提出这些原则的人往往不会特意告诉你,什么场景下应该用这样的原则,什么场景下不该使用。

用心的人也会发现,在实践中应用这些原则时,好像并不是那么回事,有时反而会带来相反的效果。于是,这些原则便沦为心灵鸡汤,或事后总结时作附会之用。

本文针对这一问题,对部分设计原则展开讨论。期望这些讨论可以抛砖引玉,引发读者自己的独立思考,形成读者自己的判断,不再迷信设计原则。而且,不但对本文中所论及的这些原则要如此,对于其他的原则也应当如此。读者对于本文的内容也应保持同样的态度,以形成自己的独立判断为目的,不要简单的全盘接受、全盘认同,那就失去本文的初衷了。

本文将首先从 KISS 原则出发分析,KISS(Keep It Simple, Stupid)原则翻译成中文,意思是“保持简单、愚蠢”。这是一句没有主语的话,猜想主语是指设计师,并且这个“It”所指的应该是设计师所设计的目标系统。这条原则大意是告诫设计师们,在设计系统时要保持目标系统的“Simple and Stupid”。

针对这个原则详细分析,可以发现它有以下几个问题。

没有明确“Simple and Stupid”的判断原则

怎样才能算是“Simple and Stupid”?这是很让人迷惑的地方。人们在认知一句无主语的话时,会下意识地把这句话的主语映射为自己。所以,一般人看到这个原则,下意识给出的都是自己所认知的“Simple and Stupid”含义,当然,这未必是该原则作者所表达的“Simple and Stupid”含义。

要分析这一点,首先需要明确参与目标系统建设的相关角色。

任何一个请设计师设计并建造的为用户服务系统,最少都会涉及到四方人员:系统拥有者、设计师、实施人员、目标用户。而这四方的形成,是由社会分工导致的:

系统拥有者是最终为整个系统买单的人,也是最终获得系统运营收益的人;用户是系统的服务对象;其他两方都是从系统拥有者身上拆分出来的角色,因为系统拥有者不具备设计师的能力,而设计师又不具备按时实施完成的能力。因此,这四方人员在看到这个原则时,对于什么是“Simple and Stupid”都会有各自的看法。

在目标用户的角度,能让业务运作方便,能够节省时间的系统才是 “Simple and Stupid”。因此,用户会要求实施人员做出让他们使用起来“Simple and Stupid”的产品。而在现实生活中,由于分工已经很细,当目标用户的需求传达到实施人员时,已经过许多不同角色的加工,已经严重失真;同时实施人员实现需求也需要较长的时间,因此,系统实现完成后交付给用户使用时,产 生了巨大的时间差。对需求的误解会形成施工的反复,而反馈时间差导致了对需求的处理不及时,往往导致错过业务的最佳时间窗口。因此,用户总对实施人员的输出不满意,而实施人员则觉得是用户的需求不对,两方总是存在冲突。很明显,用户的“Simple and Stupid”很难得到满足。

在目标系统拥有者的角度,花费最少、产出最高的系统才是“Simple and Stupid”。因此,他关注的是如何能够简单地通过这个系统获利,换一句话说, 就是如何能够简单地给他的用户带来便利,节省目标用户的时间。所以,目标系统拥有者的角度,就是在用户的角度之上,多加了一个成本的考虑:为了做到让用户使用起来简单,他需要花的成本是多少?未来的收益又会是是多少?这是他关心的。相对来说,目标用户并不会关心系统建造的成本,用户关心的只是他们在使用系统时所花的成本。

在设计师的角度,他潜意识里当然也会认为方便自己工作的设计才是 “Simple and Stupid”。因此,他会拿出他自己最熟悉的那一套设计,这个思路所带来的后果就是所谓的“金锤子”(Golden Hammer)。

在实施人员的角度,他潜意识里也会希望方便自己的工作,尽早地完成被分派的任务,这是他所希望的“Simple and Stupid”。因此,实施人员会希望设计师给出的设计方案能方便他们落地实现,因为设计师自身的“Simple and Stupid” 观点会对实施人员的工作难度产生巨大的影响。比如体操教练让一个体操队员来做一个后空翻,这是“Simple and Stupid”。但是让一个没经过体操训练的普通人做一个后空翻,这绝对不“Simple and Stupid”,可能会摔断脖子出人命的。

所以,对于技术水平不同的实施者,他会的或者他能够熟练掌握的技术才是 “Simple and Stupid”。如果一个高水平设计师没有考虑到实施团队的水平,给出他所认为的“Simple and Stupid”方案并勉强推进落地的话,要么实现不了,或者勉强实施出来,最后也会问题不断,甚至引发重大事故。因此,设计师要设计 一个系统的话,必须要结合实施团队的技术水平,做出适合他们的架构设计。如此,对实施团队而言才是“Simple and Stupid”。

从上述的分析来看,“Simple and Stupid”是因人而异的,不同的角色有不同的诉求,并不一致,而且这些诉求都存在于各个参与方的潜意识里,很难识别。于是就会形成这样的结果:实施人员的工作常会受限于设计师的设计,因 为设计师要考虑自身工作的“Simple and Stupid”;同时,实施人员在工作时会和 用户直接打交道,而目标用户则会有业务方的“Simple and Stupid”观点,会对实施人员的工作产生冲击。因此,实施人员被夹在用户和设计师的不同“Simple and Stupid”观点之间而痛苦不堪,甚至长期加班都于事无补。难怪实施人员会对业务恐惧,而对设计师则是又爱又恨:遇到适合他们的设计是“爱”,遇到不合适的设计则“恨”。

可见,让各方都得到“Simple and Stupid”是不可能的,那么哪一个才是设计师想要得到的“Simple and Stupid”呢?

首先,设计师这个角色是从系统拥有者身上拆分出来的,需要考虑系统拥有者的“Simple and Stupid”。

其次,系统是给用户用的,需要考虑目标用户的“Simple and Stupid”。

再次,系统拥有者的“Simple and Stupid”已经包含了用户的“Simple and Stupid”,所以,系统拥有者的“Simple and Stupid”才是真正所需要的“Simple and Stupid”,况且他是系统的出资人,理当得到这个利益。而为实现这个利益,先需要考虑用户的“Simple and Stupid”,整个系统才会有收益,才有做的价值;然后才能考虑实现目标系统所需成本的“Simple and Stupid”。也就是说:设计师和实施人员所认为的“Simple and Stupid”,都不是真正的“Simple and Stupid”。

“Simple”与“Easy”

人们在说“Simple”的时候,往往潜意识里说的是“Easy”,即“容易”。如果把“Simple and Stupid”这句话的主语补全的话,那么“Simple”实际 上指的是用户使用起来“Simple”,而人们潜意识里的“Simple”,指的是自身工作的“Easy”。其实, “Simple”并不等同于“Easy”,要把系统做到“Simple”,往往是最难的,一点都不 “Easy”。同样,实施人员负责构建系统,也是设计师所设计系统的目标用户,要让他们也“Simple”,对设计师的要求更高。

当然,如果系统的目标用户是实施人员或设计师自身时,这种情况属于用户、实施者以及设计者三者合体,这是最好的情况。合体之后,减少了分工对设计的影响,需求也不容易失真,系统反而好设计,比如 Git 的设计师本身也是 Git 的用户。如果一个企业系统的设计者自身也是企业系统的用户,这也能提升系统的设计质量,只不过企业系统的用户往往不懂设计。如果大家都意识到这个问题,未来应当会有所改善。

复杂度在不同分工间会互相影响

系统拥有者、设计师、实施者和目标用户,他们之间的复杂度总是有一个整体平衡的关系:如果要把某一方的工作变简单,其他角色的工作则往往会变得更加困难。

比如一个设计师设计出来一个他自认为“Simple and Stupid”的系统,但最终却往往会提升目标用户的使用难度,或者会提升施工人员的实施难度,或者会提升目标系统拥有者的成本、或降低其收益。许多设计师在给企业设计系统的时候,为了其所坚持的“Simple and Stupid”理念,不断地和业务团队发生冲突, 其实只不过是为了方便自己,用自己更熟悉的设计方案而已。然而这么做很容易降低其用户的使用体验,并且这么继续冲突下去,设计师自身的体验也最终会变得一点也不“Simple and Stupid”。

反之,要得到一个让用户用起来“Simple and Stupid”的系统,或让目标系统拥有者觉得“Simple and Stupid”的系统,则会让设计师的工作变得更加复杂、更困难。要做到这一点,需要设计师突破自身的认知,先站在用户的业务角度去考虑,这是非常难的;还要站在老板的角度,要时刻计算着成本,这更难了。许多人都会吐槽,还不如自己来当老板。

如前所述,用户业务访问的“Simple and Stupid”才是目标,所以要先完成用户业务访问的“Simple and Stupid”,然后考虑到系统拥有者的成本,同时去考虑实施者的“Simple and Stupid”,做到低成本可持续迭代,最后才能考虑设计师自身的“Simple and Stupid”,这才是一个设计师所应考虑的“Simple and Stupid”顺序。往往用户的访问方便了,实施者的工作也会相对变得简单,成本也会更低,因为用户的需求清晰了,会避免走很多的弯路。

可见,设计师的工作没法变简单,其自身工作的“Simple and Stupid”只能放在最后才可以考虑。人们总想成为设计师,但为什么只有极少人才能够做到, 可见其工作的困难程度可见一斑。

所以,每个设计师在思考这个原则的时候,都必须先要明确:设计的目的是要先满足谁的“Simple and Stupid”?是自己还是用户?

设计师不能够为了“Simple and Stupid”而去设计

然而哪怕设计师意识到不能只考虑让自己的工作变简单,也知道需要满足用户的业务场景,可如果设计师以“Simple and Stupid”的态度去理解业务场景,也是不可能因此而真正理解业务的。因为在外行看来,用户在其业务领域内的活动永远是复杂的,绝不简单。设计师会因为追求“Simple and Stupid”而简化业务需求,导致很难理解用户的分工,误解业务的需求。

只有当设计师承认自己是业务的外行,放下自己的任何业务观点,放弃自己所谓的设计原则,放下自己的先入为主,从最简单的业务入手,然后逐渐变成业务领域的内行时,他才能真正从业务视角来观察业务。在这个前提下,他才能对业务生命周期以及用户访问生命周期进行分析,才能根据业务分工的不同、或者根据业务流量压力的不同,进行合理的树状拆分。通过这种方式所形 成的设计,一定是符合业务运行规则的;所形成的不同系统,各自的边界一定是清晰的,一定是内聚的,也因此一定是“Simple and Stupid”。

也就是说,只有设计师放低自己的身段,从业务上去分析、拆分,才能够得到一个内聚的结构,这个结构也才因此而被称为“Simple and Stupid”。所 以,这个“Simple and Stupid”的效果只不过是系统设计符合用户业务内聚的一个副产品,是内聚的一个外在表现,并非设计的目标。可见,“Simple and Stupid” 并不是因为追求“Simple and Stupid”而带来的,反而是追求业务“内聚”的一个结果,不能作为设计时目标。

所以,在设计时,设计师一定要站在目标用户的角度,体验并理解用户的 业务,然后再依照目标用户的实际需求进行设计,并形成内聚的系统,那么最终结果一定会是“Simple and Stupid”的。也就是说,“内聚”原则才是设计时的最高目标。

所以,一旦仅仅以“Simple and Stupid”原则作为设计的最高目标,会很容易失去业务的目标,忽视业务人员的诉求,失去业务的“内聚”,从而导致业务问题复杂化,反而使业务的运转变得更加困难。这么下去,也会使设计师、施工 人员和用户三者之间产生冲突,矛盾激化,因为设计师的工作变简单了,用户和施工人员的工作一定会变得更复杂。

“Simple and Stupid”原则的作用

虽然这个原则不能作为设计目标,倒是可以作为审查设计的一个手段。比如在审查一个系统的时候,一旦所设计的系统对于目标用户访问的拆分不够清晰,且不是树状结构的时候,那么这个系统往往会表现出来耦合的问题,牵一发动全身,对用户或施工人员都不够“Simple and Stupid”。因此,这个原则可以作为架构审查时的一个检查点,用来判断一个设计是否合理,反馈给设计人 员,帮助设计人员发现不合理的设计,进而改进设计。

查阅了一下这个原则的出处,发现其原本是军工行业对设计飞机的一个要求。“Simple and Stupid”原则中所说的“Stupid”本义,是形容修理人员对系统组件修理维护时的简单程度,不需要复杂的工具,直接简单替换即可。其针对的是系统组件的修理维护人员,即用户,不是系统的设计者。为达到这一目的,系统设计者必须要做好内聚,不能存在耦合,他的工作因此反而变得更复杂、 更加困难了。感兴趣的读者,可以去研究一下这个原则的历史背景。

不同系统之间“Simple and Stupid”的互相影响

前面讨论的互相影响还仅局限在系统内部。如扩展到更大的范围,那么不同系统之间的“Simple and Stupid”也是会互相影响的,一个设计师对其系统的 “Simple and Stupid”判断也会扩散到外部,对其他系统产生影响,类似“蝴蝶效应”。

比如硬盘设计师设计一块机械硬盘,根本不会去考虑维修的“Simple and Stupid”,因为机械硬盘的维修成本太高,坏了就直接丢弃,不需维修,所以硬盘设计师的工作相对会容易许多。如果要把机械硬盘设计成维修时可以“Simple and Stupid”,硬盘设计师的工作难度会高上好几个级别,还不一定能够实现出 来,成本也会飙升。

而在设计一个软件系统时,则因为机械硬盘无法维修这一前提,也不会在硬盘维修方面考虑“Simple and Stupid”,因此用户在使用软件系统时,就时刻需要考虑硬盘中数据的备份,增加了用户的使用复杂度。可见,硬盘的设计方便了,用户的使用就复杂了。

为了降低用户的使用复杂度,软件系统需要能够自动应对硬盘失效的情况,因此,这一要求就增加了软件系统设计人员和实施人员的复杂度。如果要进一步降低实施人员的复杂度,但却使得软件设计师的工作复杂度进一步增 加。

通过这个例子也可以发现,相关系统的设计师之间,其工作难易程度也是存在连锁反应的:某个系统的设计师工作简单了,其他相关系统的设计师工作则会变复杂。

在目标系统内部拆分树的范围内来说,子系统之间互相影响主要可以分为两个方向:上层节点的设计,会影响子系统的划分;而子系统的设计,则会影响大系统拆分时的取舍。比如上例中,底层硬盘的设计,直接影响了上层软件的设计。而目标系统的设计,也会影响到与其相连的外部系统,并最终扩散到系统外的整个世界。

所以,一旦形成设计师、施工人员和用户三者的分工,他们各自工作的难易程度会有平衡关系,最终会影响到系统拥有者的难度。而设计师是其中最难的工作,不可能达成“Simple and Stupid”。并且在整个系统的设计中,设计师可以对其他某个角色的工作复杂度作出取舍,但绝不能对自己工作的难易程度作出取舍。哪怕需要取舍,也要放在最后一个来考虑。而设计师对自身工作的取舍,往往都是受限于社会整体技术水平的发展,这个取舍最终也会通过其所设计的系统影响到整个世界。

由此也可以看出,“Simple and Stupid”原则无法适用所有的情况。不去了解一个原则的历史,盲目地直接引用到软件行业来,很容易造成误解,因为每个人都可以拿这个原则来为自己的工作辩解。这个原则其实是告诉我们,只有用户的“Simple and Stupid”才是对的。

“Simple and Stupid”与内聚的关系

也有人说,只要做到内聚、低耦合,不就可以满足“Simple and Stupid”了?是的,内聚的系统一定是“Simple and Stupid”。因此,如果已经做到内聚,就不再需要用“Simple and Stupid”原则来判断,“内聚”才是最核心的设计原则。反之, 做到“Simple and Stupid”的系统,则并不一定是内聚的,比如一个足够简单但是耦合的系统,也可以是“Simple and Stupid”,可以很容易让人掌握,可是它并不内聚。所以,“Simple and Stupid”并不能作为“内聚”的判断标准,也不能作为设 计目标。

而“内聚”才是设计的真正目标,只有“内聚”才是各个行业、各个领域通行 的原则,为什么呢?因为只有内聚才能够保证权责对等,才能保障个体在空间 上的连续与完整,不同个体才得以占有独立的空间,才能符合现实世界的特质!因此,做设计时,不如直接强调“内聚”原则。

为了论证内聚,人们用了很多理论,但“内聚”这个词已经足够好用了,应该担心的反而是人们对“内聚”这个词内涵的正确理解,比如下文中的一些原则也有对“内聚”的不同表述,也很容易令人造成误解。

参考资料

KISS 原则维基百科

原文  https://www.infoq.cn/article/J8rGQJfs4tNxKfX1DBEp
正文到此结束
Loading...