软件开发中的著名定律
软件开发中的著名定律
https://www.timsommer.be/famous-laws-of-software-development/
和其他领域一样,在软件开发的世界中也有一些有趣而著名的定律,开发人员、管理人员还是架构师,都经常在会议或闲谈中提到他们,很多时候我们都只是点头附和,免得让人知道自己其实根本没听说过布鲁克斯(Brooks)、摩尔(Moore)或康威(Conway)这些大佬。
在这里,我把这些定律整理出来,分享给大家。
这些法律由规则、原则或来自发展世界中伟大而鼓舞人心的人物的名言组成。同时它们很有趣,有趣,值得了解,并且都有很棒的背景故事,令人惊叹。
在这篇文章中,我将分享我对软件开发中最著名和最常用的法律的收集、解释和想法。
这是一篇大文章,所以如果你想跳过一些,我已经包含了一个索引:
-
墨菲定律
-
布鲁克定律
-
霍夫斯塔德定律
-
康威定律
-
波斯特定律
-
帕累托原则
-
彼得原理
-
克尔赫霍夫原理
-
林纳斯定律
-
摩尔定律
-
沃斯定律
-
九十九法则
-
Knuth的优化原理
-
诺维格定律
墨菲定律 (Murphy's Law)
或许是所有的定律中最广为人知的,因为它不仅仅适用于软件开发领域。
凡是可能出错的事就一定会出错。
衍生定律:说脏话是唯一一门程序员用得都很流畅的语言。
推论:计算机会按照你写出来的方式运行,而不是你臆想出来的。
防御性编程、版本控制、测试驱动开发、模型驱动开发等等都是预防墨菲定律很好的做法。
布鲁克斯法则(Brook's Law)
大多数开发人员都会经历过布鲁克斯定律:
向一个延期的项目增加人手只会让它延期得更加厉害
如果一个项目进展落后了,仅仅增加人力很有可能会带来灾难性的后果。
相反,提高编程效率、审查软件开发方法和技术架构是否合理,几乎总是会比增加人力带来更好的效果。如果没有,这可能意味着霍夫施塔特定律在起作用。
霍夫斯塔特定律 (Hofstadter's Law)
霍夫斯塔特定律是由道格拉· 霍夫斯塔特(Douglas Hofstadter) 提出,并且以他的名字来命名的。
不要将这个定律与《生活大爆炸》中的伦纳德·霍夫斯塔特混为一谈。即使他的话对你们一些人或许有用。
这个定律是这么说的:
事情总是要花费比你预想更长的时间,即使你把霍夫斯塔特定律也考虑在内。
这条定律的递归性反映出,即使付出最大的努力,也知道任务是复杂的,去精确地估算它依然是非常难的,所以要给估算留一个缓冲区出来。
康威定律 (Conway's Law)
软件的任何一部分都反应了创建它的组织结构
或者更清楚一点:
组织形式等同其设计的系统架构
许多组织都根据他们的技能来划分团队。因此会有前端开发、后端开发和数据库开发组成的团队。这会导致某人想要修改一个不属于自己领域的东西会很难。
最好是按照有边界的上下文(bounded context)来规划团队,并且越来越多的组织者也正在这么做。像微服务这样的架构围绕服务边界而不是孤立的技术体系划分来组织他们的团队。
康威定律带来的具体的实践建议就是:你想要什么样的系统设计,就架构什么样的团队,这会带来事半功倍的效果。
伯斯塔尔定律(Postel's Law)
又称健壮性法则(Robustness principle)
发送时要保守,接收时要大方
Jon Postel 最初认为正是这个原则让TCP协议的实现很健壮。一些人认为这正是 HTML 很成功的原因,也有一些人认为这正是 HTML 很失败的原因。(因为HTML可以写得不那么严格,但是浏览器依然可以解析它)
帕累托法则 (Pareto Principle)
又称80/20法则(The 80-20 rule)
对于许多现象来说,有 80% 的后果都是 20% 的原因造成的。
在软件开发中的体现是: 代码中80%的错误都是由代码中的20%引起的。
另外,公司80%的工作是由20%的员工完成的。问题是你并不总是清楚谁是那20%。
彼得原则(The Peter Principle)
该原则还是比较打击人的,特别是你碰巧正在经历的话。
在等级制度中,每个员工都倾向于提升到他无法胜任的等级
在各种组织中,由于习惯于对在某个等级上称职的人员进行晋升提拔,因而雇员总是趋向于被晋升到其不称职的地位。
一旦组织中的相当部分人员被推到了其不称职的级别,就会造成组织的人浮于事,效率低下,导致平庸者出人头地,发展停滞。
柯克霍夫原则(Kerchkhoff's Principle)
在密码学中,即使一个系统中的所有东西都是公开的(**除外),该系统也应当是安全的。
这就是非对称加密的主要原则。
林纳斯定律 (Linus's Law)
以Linux之父林纳斯·托瓦兹(Linus Torvalds)的名字命名,该定律表述为:
众目睽睽之下,一切 bug 都无所遁形
这个定律出自著名的文集《大教堂与集市》,这个文集对比了两种不同的开源软件开发模型。
- 大教堂模型,每个软件发行版都伴有源代码,但是仅限于软件开发人员查看。
- 集市模型,以互联网为媒介,代码开发的过程完全暴露在大众的视野下。
被公开审查、测试的代码越多,各种形式的错误就能更快地被发现。
摩尔定律 (Moore's Law)
每一美元所能买到的电脑性能,将每隔24个月翻一番。
最流行的版本是:
集成电路上可容纳的元器件的数目,约每隔18个月便会增加一倍。
或
计算机的处理性能每隔两年翻一倍。
沃斯定律
软件变慢的速度比硬件变快的速度快。
以摩尔定律为例!
90-90法则 (Ninety-ninety rule)
前90%的代码要花费90%的开发时间,剩余的10%的代码要再花费90%的开发时间。
如此真实。有谁不同意这一点?
克努特优化原则 (Knuth's optimization principle)
不成熟的优化是万恶之源。
先把代码写出来,定位瓶颈所在,然后优化它。
诺维格定律 (Norvig's Law)
当公司的市场份额超过50%之后,就不能再翻番了。
在一个市场占主导地位的公司必须不断开拓新财源,才能长盛不衰。
墨菲定律
任何事物都没有表面看起来那么简单。
所有的事都会比你预计的时间长。
可能出错的事总会出错。
如果你担心某种情况发生,那么他就更有可能发生。
在设计系统时,需要多考虑墨菲定律
康威定律详细介绍
用通俗的说法就是:组织形式等同系统设计。
这里的系统按原作者的意思并不局限于软件系统。据说这篇文章最初投的哈佛商业评论,结果程序员屌丝的文章不入商业人士的法眼,无情被拒,康威就投到了一个编程相关的杂志,所以被误解为是针对软件开发的。最初这篇文章显然不敢自称定律(law),只是描述了作者自己的发现和总结。后来,在Brooks Law著名的人月神话中,引用这个论点,并将其“吹捧”成了现在我们熟知“康威定律”。
Mike从他的角度归纳这篇论文中的其他一些核心观点,如下:
- 第一定律:Communication dictates design(组织沟通方式会通过系统设计表达出来)
- 第二定律:There is never enough time to do something right, but there is always enough time to do it over(时间再多一件事情也不可能做的完美,但总有时间做完一件事情)
- 第三定律:There is a homomorphism from the linear graph of a system to the linear graph of its design organization(线型系统和线型组织架构间有潜在的异质同态特性)
- 第四定律: The structures of large systems tend to disintegrate during development, qualitatively more so than with small systems(大的系统组织总是比小系统更倾向于分解)
人是复杂社会动物
第一定律:Communication dictates design(组织沟通方式会通过系统设计表达出来)
组织的沟通和系统设计之间的紧密联系,在很多别的领域有类似的阐述。对于复杂的系统,聊设计就离不开聊人与人的沟通,解决好人与人的沟通问题,才能有一个好的系统设计。相信几乎每个程序员都读过的《人月神话》(1975年,感觉都是老古董了,经典的就是经得起时间考验)里面许多观点都和这句话有异曲同工之妙。
比如《人月神话》中最著名的一句话就是
Adding manpower to a late software project makes it later --Fred Brooks, (1975)
Boss们都听到了吗?为了赶进度加程序员就像用水去灭油锅里的火一样(无奈大家还是前赴后继)。
为什么?人月神话也给出了很简洁的答案:沟通成本 = n(n-1)/2,沟通成本随着项目或者组织的人员增加呈指数级增长。是的,项目管理这个算法的复杂度是O(n^2)。举个例子
-
5个人的项目组,需要沟通的渠道是 5*(5–1)/2 = 10
-
15个人的项目组,需要沟通的渠道是15*(15–1)/2 = 105
-
50个人的项目组,需要沟通的渠道是50*(50–1)/2 = 1,225
-
150个人的项目组,需要沟通的渠道是150*(150–1)/2 = 11,175
所以知道为什么互联网创业公司都这么小了吧,必须小啊,不然等CEO和所有人讲一遍创业的想法后,风投的钱都烧完了。
Mike还举了一个非常有意思的理论,叫“Dunbar Number”,这是一个叫Dunbar(废话)生物学家在1992年最早提出来的。最初,他发现灵长类的大脑容量和其对应的族群大小有一定关联,进而推断出人类的大脑能维系的关系的一些有趣估计。举例来说
-
亲密(intimate)朋友: 5
-
信任(trusted)朋友: 15
-
酒肉(close)朋友: 35
-
照面(casual)朋友: 150
是不是和上面的沟通成本的数字很貌似有关联?是的,我们的大脑智力只能支持我们维系这么多的关系。(大家都知道这不是程序猿擅长的领域,在开发团队里,这个值应该更小,估计和猿差不多 -_-凸 )
沟通的问题,会带来系统设计的问题,进而影响整个系统的开发效率和最终产品结果。
一口气吃不成胖子,先搞定能搞定的
第二定律:There is never enough time to do something right, but there is always enough time to do it over(时间再多一件事情也不可能做的完美,但总有时间做完一件事情) Eric Hollnagel是敏捷开发社区的泰斗之一,在他《Efficiency-Effectiveness Trade Offs》 一书中解释了类似的论点。
Problem too complicated? Ignore details.
Not enough resources?Give up features.
--Eric Hollnagel (2009)
系统越做越复杂,功能越来越多,外部市场的竞争越来越剧烈,投资人的期待越来越高。但人的智力是有上限的,即使再牛逼的人,融到钱再多也不一定招到足够多合适的人。对于一个巨复杂的系统,我们永远无法考虑周全。Eric认为,这个时候最好的解决办法竟然是——“破罐子破摔”。
其实我们在日常开发中也经常碰到。产品经理的需求太复杂了?适当忽略一些细节,先抓主线。产品经理的需求太多了?放弃一些功能。
据说Eric被一家航空公司请去做安全咨询顾问,复杂保证飞机飞行系统的稳定性和安全性。Eric认为做到安全有两种方式:
-
常规的安全指的是尽可能多的发现并消除错误的部分,达到绝对安全,这是理想。
-
另一种则是弹性安全,即使发生错误,只要及时恢复,也能正常工作,这是现实。
对于飞机这样的复杂系统,再牛逼的人也无法考虑到漏洞的方方面面,所以Eric建议放弃打造完美系统的想法,而是通过不断的试飞,发现问题,确保问题发生时,系统能自动复原即可,而不追求飞行系统的绝对正确和安全。
下面的图很好的解释了这个过程:
听着很耳熟不是吗?这不就是 持续集成 和敏捷开发吗?的确就是。另一方面,这和互联网公司维护的分布式系统的弹性设计也是一个道理。对于一个分布式系统,我们几乎永远不可能找到并修复所有的bug,单元测试覆盖1000%也没有用,错误流淌在分布式系统的血液里。解决方法不是消灭这些问题,而是容忍这些问题,在问题发生时,能自动回复,微服务组成的系统,每一个微服务都可能挂掉,这是常态,我们只有有足够的冗余和备份即可。即所谓的 弹性设计(Resilience) 或者叫高可用设计(High Availability)。
种瓜得瓜,做独立自治的字系统减少沟通成本
第三定律:There is a homomorphism from the linear graph of a system to the linear graph of its design organization(线型系统和线型组织架构间有潜在的异质同态特性)
这是康威第一定律组织和设计间内在关系的一个具体应用。更直白的说,你想要什么样的系统,就搭建什么样的团队。如果你的团队分成前端团队,Java后台开发团队,DBA团队,运维团队,你的系统就会长成下面的样子:
相反,如果你的系统是按照业务边界划分的,大家按照一个业务目标去把自己的模块做出小系统,小产品的话,你的大系统就会长成下面的样子,即微服务的架构
微服务的理念团队间应该是 inter-operate, not integrate 。inter-operate是定义好系统的边界和接口,在一个团队内全栈,让团队自治,原因就是因为如果团队按照这样的方式组建,将沟通的成本维持在系统内部,每个子系统就会更加内聚,彼此的依赖耦合能变弱,跨系统的沟通成本也就能降低。
合久必分,分而治之
第四定律: The structures of large systems tend to disintegrate during development, qualitatively more so than with small systems(大的系统组织总是比小系统更倾向于分解)
前面说了,人是复杂的社会动物,人与人的通过非常复杂。但是当我们面对复杂系统时,又往往只能通过增加人力来解决。这时,我们的组织一般是如何解决这个沟通问题的呢?Divide and conquer,分而治之。大家看看自己的公司的组织,是不是一个一线经理一般都是管理15个人以下的?二线经理再管理更少的一线?三线再管理更少的二线,以此类推。(这里完全没有暗示开发经理比程序猿更难管理)
所以,一个大的组织因为沟通成本/管理问题,总为被拆分成一个个小团队。
- 创业的想法太好了,反正风投钱多,多招点程序猿
- 人多管不过来啊,找几个经理帮我管,我管经理
- 最后, 康威定律 告诉我们组织沟通的方式会在系统设计上有所表达,每个经理都被赋予一定的职责去做大系统的某一小部分,他们和大系统便有了沟通的边界,所以大的系统也会因此被拆分成一个个小团队负责的小系统(微服务是一种好的模式)
康威定律如何解释微服务的合理性
了解了康威定律是什么,再来看看他如何在半个世纪前就奠定了微服务架构的理论基础。
-
人与人的沟通是非常复杂的,一个人的沟通精力是有限的,所以当问题太复杂需要很多人解决的时候,我们需要做拆分组织来达成对沟通效率的管理
-
组织内人与人的沟通方式决定了他们参与的系统设计,管理者可以通过不同的拆分方式带来不同的团队间沟通方式,从而影响系统设计
-
如果子系统是内聚的,和外部的沟通边界是明确的,能降低沟通成本,对应的设计也会更合理高效
-
复杂的系统需要通过容错弹性的方式持续优化,不要指望一个大而全的设计或架构,好的架构和设计都是慢慢迭代出来的
带来的具体的实践建议是:
-
我们要用一切手段提升沟通效率,比如slack,github,wiki。能2个人讲清楚的事情,就不要拉更多人,每个人每个系统都有明确的分工,出了问题知道马上找谁,避免踢皮球的问题。
-
通过MVP的方式来设计系统,通过不断的迭代来验证优化,系统应该是弹性设计的。
-
你想要什么样的系统设计,就架构什么样的团队,能扁平化就扁平化。最好按业务来划分团队,这样能让团队自然的自治内聚,明确的业务边界会减少和外部的沟通成本,每个小团队都对自己的模块的整个生命周期负责,没有边界不清,没有无效的扯皮,inter-operate, not integrate。
-
做小而美的团队,人多会带来沟通的成本,让效率下降。亚马逊的Bezos有个逗趣的比喻,如果2个披萨不够一个团队吃的,那么这个团队就太大了。事实上一般一个互联网公司小产品的团队差不多就是7,8人左右(包含前后端测试交互用研等,可能身兼数职)。
再对应下衡量微服务的标准,我们很容易会发现他们之间的密切关系:
-
分布式服务组成的系统
-
按照业务而不是技术来划分组织
-
做有生命的产品而不是项目
-
Smart endpoints and dumb pipes(我的理解是强服务个体和弱通信)
-
自动化运维(DevOps)
-
容错
-
快速演化
写在最后
这就是我喜欢的“定律”, 他们都有自己的故事和背景。作为软件开发人员你必须熟悉他们。最后2个定律是笔者细化和整理的。