軟體開發中的著名定律
軟體開發中的著名定律
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個定律是筆者細化和整理的。