软件开发中的定律和经验总结

参考

和其他领域一样,在软件开发的世界中也有一些有趣而著名的定律,开发人员、管理人员还是架构师,都经常在会议或闲谈中提到他们,很多时候我们都只是点头附和,免得让人知道自己其实根本没听说过布鲁克斯(Brooks)、摩尔(Moore)或康威(Conway)这些大佬。

在这里,我把这些定律整理出来,分享给大家。

墨菲定律 (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%之后,就不能再翻番了。

在一个市场占主导地位的公司必须不断开拓新财源,才能长盛不衰。

项目永远不会结束

不要相信客户和产品经理以后不会改需了这类话。产品(项目)存在意义就是解决人的需求(市场),让更多的人使用它,人的需求是变化的(市场竞争),项目只要存在就会有需求改动和功能增加。但是不能任由产品乱来。类比,好多人会追问生命的意义,生命的意义就是好好活着,生命一旦不能生存就只有死亡没有什么意义。

破窗户效应

此理论认为环境中的不良现象如果被放任存在,会诱使人们仿效,甚至变本加厉。以一幢有少许破窗的建筑为例,如果那些窗不被修理好,可能将会有破坏者破坏更多的窗户。最终他们甚至会闯入建筑内,如果发现无人居住,也许就在那里定居或者纵火。一面墙,如果出现一些涂鸦没有被清洗掉,很快的,墙上就布满了乱七八糟不堪入目的东西;一条人行道有些许纸屑,不久后就会有更多垃圾,最终人们会视若理所当然地将垃圾顺手丢弃在地上。这个现象,就是犯罪心理学中的破窗效应。

在项目中,一旦开始松懈,出现了烂代码,最终项目的代码将会变烂。

曳光弹

曳光弹和常规子弹交错装在弹药带上,发射时会照亮弹道路线,如果曳光弹击中目标,那么常规子弹也会击中目标,比提前费力计算更可取,可以及时获得反馈。

类比软件开发,曳光弹适用于新项目。当你构建从未构建过的东西时,与枪手一样,你也没法在黑暗中击中目标。因为你的用户从未见过这样的系统,他们的需求可能会含糊不清。因为你在使用不熟悉的算法、技术、语言或库,你面对这当量未知的事物。同时因为完成项目需要时间,在很大程度上能够确知,你的工作环境将在你完成之前发生变化。

经典的作法是把系统定死,制作大量的文档,注意列出每项需求、确定所有未知因素。限定环境,预先进行大量计算。这种方式非常低效。因为永远有你考虑不到的情况。

注重实效的作法是使用曳光弹,我们要找到某种东西,让我们快速直观和可重复的从需求出发,满足最终系统的某个方面要求。曳光代码并非用过就扔的代码,你编写它是为了保留它。它只是功能不全,可以逐步完善达到最终目标。

曳光开发与项目永不会结束的理念是一致的:总有改动需要完成,总有功能需要增加。这是一个渐进的过程。曳光弹算一种敏捷开发方法。

曳光开发不一定命中目标达到想要的效果。

容灾

运行的项目一定要有容灾能力,服务,数据,文件 ,安全。不能抱有侥幸心理。

项目维护

接手旧项目时,不理解的代码,一定不要去乱碰。nginx配置也是一样的。你不知道它在哪里被用到了。不能抱有侥幸心理。