每名開(kāi)發(fā)人員都會(huì)遇到的 8 條編程法則(開(kāi)發(fā)編程是什么)
本文最初發(fā)布于 Level Up Coding。
多年來(lái),我觀察到了一些在工程過(guò)程中反復(fù)出現(xiàn)的基本模式和陷阱。有趣的是,它們與工程博客上無(wú)休止?fàn)幷摰脑掝}無(wú)關(guān)。例如,我不記得哪一次我的團(tuán)隊(duì)因?yàn)閷?duì) SOLID 原則理解不足而導(dǎo)致錯(cuò)過(guò)了交付期限。偶爾,我會(huì)遇到一條“法則”,它完美描述了我所經(jīng)歷的問(wèn)題。令人惱火的是,這些便利的工程定律卻往往在播客、有聲讀物和博客的邊角隱蔽處。所以我把它們整理成一個(gè)清單,其中列出了我最喜歡的 8 條編程法則,你肯定也會(huì)在現(xiàn)實(shí)生活中遇到它們。
1)墨菲第二定律
墨菲定律[1]是這個(gè)榜單上最著名、最廣為人知的定律,它通常被表述為:
“凡事只要可能出錯(cuò),那就一定會(huì)出錯(cuò)?!?/span>
不過(guò),真要說(shuō)觸及所有工程師痛處的還要數(shù)墨菲第二定律:
“任何解決方案都有自己的問(wèn)題“
或者,沒(méi)有什么事情像看起來(lái)那么簡(jiǎn)單[2]。墨菲第二定律雄辯地總結(jié)出了以下觀察結(jié)果:作為工程師,我們接觸的任何東西都會(huì)增加系統(tǒng)的風(fēng)險(xiǎn),因此,可以通過(guò)避免系統(tǒng)更改來(lái)降低風(fēng)險(xiǎn)。
運(yùn)用之道
隨著我成長(zhǎng)為一名成熟的工程師,我花在編程上的時(shí)間越來(lái)越少。事實(shí)上,我已經(jīng)慢慢地開(kāi)始認(rèn)為,編寫新代碼是一種系統(tǒng)性風(fēng)險(xiǎn);它增加了復(fù)雜性、可維護(hù)性,可能還有 Bug??紤]到墨菲定律,我有以下建議:
- 首選流程變革和供應(yīng)商軟件,而不是自主開(kāi)發(fā)的解決方案。
- 避免陷入快速解決方案陷阱,因?yàn)槟阋院蟛坏貌换剡^(guò)頭來(lái)改進(jìn)。第一次就把它做好。
- 測(cè)試。測(cè)試。測(cè)試。測(cè)試覆蓋率越高,應(yīng)用程序就越能適應(yīng)復(fù)雜的環(huán)境。
2)康威定律
1967 年,梅爾文·康威揭示了這樣一個(gè)道理[3]:
“設(shè)計(jì)系統(tǒng)的架構(gòu)受制于產(chǎn)生這些設(shè)計(jì)的組織的溝通結(jié)構(gòu)。”
或者,更直截了當(dāng)?shù)兀?/span>
“如果你讓 4 個(gè)小組開(kāi)發(fā)編譯器,那么你就會(huì)獲得 4 個(gè)編譯器?!?/span>
康威定律的影響很大,因?yàn)檐浖こ處煶31仨毰c分散在世界各地的同事一起構(gòu)建系統(tǒng)。例如,我在一家大型托管銀行工作的時(shí)候,曾參與開(kāi)發(fā)過(guò)一個(gè)有很多服務(wù)的交易系統(tǒng)。除了兩個(gè)服務(wù)之外,其余服務(wù)都是通過(guò)內(nèi)部消息總線進(jìn)行通信。然而,莫名其妙的,這兩個(gè)服務(wù)通過(guò)互聯(lián)網(wǎng)上的公共 API 進(jìn)行通信。
就像大腦功能作為子組件運(yùn)行一樣,任何時(shí)空上分散的勞動(dòng)力也是如此。
我接著發(fā)現(xiàn),通過(guò)互聯(lián)網(wǎng)進(jìn)行通信的服務(wù)是美國(guó)團(tuán)隊(duì)和印度團(tuán)隊(duì)唯一重疊的地方。系統(tǒng)架構(gòu)基本上是兩個(gè)半球:左邊是美國(guó)的微服務(wù),右邊是印度的服務(wù),它們之間有一個(gè)最小 API。從根本上說(shuō),這個(gè) API 就是大西洋。
運(yùn)用之道
在所有科技領(lǐng)域中,關(guān)于康威定律的補(bǔ)救措施,有一個(gè)最好的說(shuō)法是逆康威模式(Inverse Conway Maneuver)。換句話說(shuō),通過(guò)改進(jìn)團(tuán)隊(duì)和組織結(jié)構(gòu)來(lái)促成所需的架構(gòu)[4]。在這方面,亞馬遜的雙披薩團(tuán)隊(duì)可能算是最著名的例子了,故事是這樣的:
- 2001 年,Amazon.com 是一個(gè)緊耦合的大型單體,維護(hù)難度很大[5]。
- 該網(wǎng)站被重建為多個(gè)微服務(wù),每個(gè)微服務(wù)由一個(gè)專門的團(tuán)隊(duì)支持。因此,團(tuán)隊(duì)按照業(yè)務(wù)線(如購(gòu)物車、推薦、廣告)而不是技術(shù)線(如數(shù)據(jù)庫(kù)、QA、開(kāi)發(fā))進(jìn)行了重組。
- T 團(tuán)隊(duì)保持較小的規(guī)?!藛T數(shù)量以兩個(gè)披薩能讓團(tuán)隊(duì)所有人吃飽為限。公司和網(wǎng)站同時(shí)經(jīng)歷了一次重構(gòu)。
這很好,但你可能沒(méi)有能力開(kāi)展公司范圍的組織結(jié)構(gòu)大調(diào)整。不用擔(dān)心,有幾種方法可以讓你的組織,或者至少是你的團(tuán)隊(duì),擺脫康威定律:
- 最重要的工作應(yīng)該在時(shí)區(qū)重疊的時(shí)間內(nèi)完成。我并不是說(shuō)西海岸的同事要趕每天早上 6 點(diǎn)的接觸點(diǎn),但是真正關(guān)鍵的會(huì)議和結(jié)對(duì)開(kāi)發(fā)應(yīng)該安排在團(tuán)隊(duì)中大多數(shù)人都能參加的時(shí)間。
- 在招聘和組織工作中考慮到這種限制因素。雖然這很可能是你無(wú)法控制的,但你可以嘗試向你的經(jīng)理們傳達(dá)康威定律。
- 接受它。如果你所在的組織是分布式的,那么或許你們的系統(tǒng)也應(yīng)該是分布式的。避免與組織結(jié)構(gòu)不協(xié)調(diào)的系統(tǒng)架構(gòu)。
3)演示定律
也被稱為演示過(guò)程中的墨菲定律,它指出,無(wú)論你排練得多么好,無(wú)論你排練了多少次,你在演示時(shí)總是會(huì)出錯(cuò)!我在這里就不詳細(xì)說(shuō)明為什么會(huì)發(fā)生這種情況了——關(guān)于這一點(diǎn),請(qǐng)查閱資料[9-11] 。
如果這在世界一流工程師馬斯克身上會(huì)發(fā)生,那么在你身上也會(huì)發(fā)生(https://www.reddit.com/r/ProgrammerHumor/comments/e0bkok/universal_law_of_demos/)
運(yùn)用之道
接受演示經(jīng)常會(huì)不順利的事實(shí),做好防范:
- 做最低限度演示 —— 在可以傳達(dá)想法/應(yīng)用/功能的前提下,盡可能減少展示內(nèi)容。
- 實(shí)際的演示過(guò)程會(huì)比你預(yù)想的長(zhǎng)。
- 至少提前 20 分鐘到場(chǎng),打開(kāi)在線會(huì)議,準(zhǔn)備好 PPT。沒(méi)有什么比一屋子的工程師為如何打開(kāi)在線會(huì)議而爭(zhēng)論不休更令人厭惡的了。
- 準(zhǔn)備一個(gè)備份演示。想象一下,你即將展示一個(gè)新的網(wǎng)站,而在演示前 5 分鐘,AWS 出現(xiàn)了故障。你能在本地機(jī)器上運(yùn)行幾個(gè)頁(yè)面嗎?是否有一個(gè)部署在不同地區(qū)的低配環(huán)境等等……要為最壞的情況做好準(zhǔn)備。
- 小黃鴨調(diào)試法
由于演示從來(lái)都無(wú)法完全按計(jì)劃進(jìn)行,你實(shí)際上可以利用這一點(diǎn)來(lái)發(fā)揮自己的優(yōu)勢(shì)。如果有什么東西不能正常工作,如你的 IDE 出了問(wèn)題,你無(wú)法重現(xiàn)一個(gè)錯(cuò)誤,諸如此類。那么,你可以利用演示定律,試著把它展示給一個(gè)朋友。通常,在談?wù)撨@個(gè)問(wèn)題的時(shí)候,你會(huì)發(fā)現(xiàn)解決方案,或者問(wèn)題會(huì)神奇地消失。
4)格雷沙姆定律
格雷沙姆定律來(lái)自 19 世紀(jì)的經(jīng)濟(jì)學(xué),它指出:
“劣幣驅(qū)逐良幣” [6] ,或者更通俗地說(shuō)“壞的擠走好的”。
Ben Hosking 在[7]中對(duì)格雷沙姆定律在軟件工程中的應(yīng)用做了很好的描述,我把它簡(jiǎn)單地歸結(jié)為:
廉價(jià)的軟件實(shí)際上非常昂貴[8]。
你希望三者兼而有之,但實(shí)際上應(yīng)該把重點(diǎn)放在質(zhì)量(Godd)上(https://andrewcoppolino.com/blog/fast-good-cheap-pick-two/)
運(yùn)用之道
在理想世界里,每個(gè)項(xiàng)目都很快,很便宜,而且還做得很好。然而,在現(xiàn)實(shí)中,我們只能追求 3 項(xiàng)中的 2 項(xiàng),要明智地選擇。在某些情況下,我們不得不倉(cāng)促趕工,但根據(jù)格雷沙姆定律,“便宜”是一個(gè)謊言。那是技術(shù)債務(wù)。你應(yīng)該總是追求把事情做好。
5)計(jì)劃謬誤
在 DanIEl Kahneman 的《思考,快與慢》一書中[13],估計(jì)謬誤是指人類在提前計(jì)劃時(shí)表現(xiàn)出相當(dāng)大的樂(lè)觀偏差,導(dǎo)致對(duì)完成一項(xiàng)任務(wù)所需的時(shí)間估計(jì)不足。你可能經(jīng)常會(huì)碰到這種情況。例如,最近你是否有什么小差使原本打算用一個(gè)小時(shí)完成,最后卻讓你耗費(fèi)了半天時(shí)間?事實(shí)上,對(duì)于任何任務(wù)估計(jì),一般的建議是先將最初的估計(jì)翻倍甚至翻三倍,然后你才會(huì)對(duì)其實(shí)際完成時(shí)間有一個(gè)大致的認(rèn)識(shí)。
計(jì)劃謬誤的精彩描繪(https://medium.com/geekculture/how-the-planning-fallacy-trips-you-up-3248b7e3978e)
以下是計(jì)劃謬誤的幾個(gè)實(shí)際的例子[14]:
- 悉尼歌劇院原計(jì)劃于 1963 年完工。但事實(shí)是,它的縮小版在十年后的 1973 年才開(kāi)放。最初的成本估計(jì)為 700 萬(wàn)美元,但因?yàn)檠悠诔杀驹黾拥搅?1.02 億美元。
- 波士頓中央大道下的“大隧道”工程比計(jì)劃晚了 7 年才完成,預(yù)算為 28 億美元(1988 年),實(shí)際耗資 80.8 億美元。
- 加州高鐵仍在建設(shè)中,預(yù)計(jì)將超支數(shù)百億美元,與主要城市的連接被推遲到農(nóng)村段完成后。
運(yùn)用之道
- 對(duì)任何被認(rèn)為“應(yīng)該很快/很容易”的東西持懷疑態(tài)度。
- 在任何時(shí)候,在給出最后期限時(shí),務(wù)必謹(jǐn)慎地用試探性的問(wèn)題來(lái)回應(yīng)。例如,“如果 QA 團(tuán)隊(duì)在第一輪就碰到了 Bug,那么時(shí)間表會(huì)有什么變化?”像這樣的基本問(wèn)題可以幫助我們發(fā)現(xiàn)那些事后看來(lái)很明顯的誤區(qū)和盲區(qū)。
- 當(dāng)有疑問(wèn)時(shí),將估計(jì)加倍。當(dāng)應(yīng)別人要求進(jìn)行估計(jì)時(shí),至少要按最初估計(jì)的兩倍。有時(shí)候,我會(huì)按三倍,然后在對(duì)方的說(shuō)服下改為兩倍。
6)海勒姆定律
該定律是最近才提出來(lái)的,可以追溯到一名谷歌人的博客[12]。該定律指出:
當(dāng)一個(gè) API 有足夠多的用戶,
你在契約中承諾了什么并不重要:
系統(tǒng)中所有看得見(jiàn)的行為
都會(huì)有某個(gè)人依賴……
XKCD 漫畫就是最好的例證:
https://xkcd.com/1172/
運(yùn)用之道
與墨菲定律類似,你必須注意,人們會(huì)以你意想不到的方式使用系統(tǒng)。因此,必須盡量縮小其范圍。構(gòu)建一個(gè)讓用戶可以用兩種類似的方式做同一件事的 API?這會(huì)讓用戶感到困惑嗎?盡量讓接口一目了然、固執(zhí)己見(jiàn)、簡(jiǎn)單易用,以至于幼兒園的小朋友都能使用。
最近,我在設(shè)計(jì)一個(gè) API 時(shí)遇到了海勒姆定律描述的情況。簡(jiǎn)單起見(jiàn),假設(shè)它獲取一個(gè)用戶列表:
fetchUsers() -> {Allan Apple, Bill Banana, Chris Carrot …}
注意到用戶是有順序的了嗎?排序過(guò)程是隱式的,因?yàn)槭窃跀?shù)據(jù)庫(kù)中完成的,API 契約中沒(méi)有順序保證。然而,考慮到海勒姆定律,我意識(shí)到,最終會(huì)有人依賴于這個(gè)順序。因此,我在構(gòu)建時(shí)將它作為 API 契約的一個(gè)默認(rèn)參數(shù)fetchUsers(sort=True)。
7)帕累托法則
帕累托法則也被稱為收益遞減定律,或 80/20 原則,其適用范圍很廣。例如,根據(jù) 1989 年的估計(jì),世界上最富有的 20%的公民擁有世界上 80%的財(cái)富(多么奇怪)。或者,20%的工作場(chǎng)所危險(xiǎn)源導(dǎo)致了 80%的傷害。在軟件領(lǐng)域,這體現(xiàn)在幾個(gè)方面,我將直接引用維基百科的說(shuō)法,因?yàn)樗f(shuō)得很好:
在計(jì)算機(jī)科學(xué)中,帕累托法則可以應(yīng)用于優(yōu)化工作。例如,微軟公司指出,修復(fù)報(bào)告最多的錯(cuò)誤中的 20%,可以消除特定系統(tǒng)中相關(guān)錯(cuò)誤和崩潰的 80%。Lowell Arthur表示,“20%的代碼包含了 80%的錯(cuò)誤。找到它們,修復(fù)它們!" 人們還發(fā)現(xiàn),一般來(lái)說(shuō),一款軟件的 80%可以在分配的總時(shí)間的 20%內(nèi)寫完。反之,最難的 20%的代碼需要 80%的時(shí)間。通常,這個(gè)因素是軟件編碼中COCOMO估算的一部分。
運(yùn)用之道
要利用好帕累托法則,你可以采取以下措施:
- 先解決難題。
盡早將最棘手的工程挑戰(zhàn)暴露出來(lái)很重要。80%的工作可能都潛伏在這里。
- 避免鍍金,即過(guò)度設(shè)計(jì)。
一個(gè)很好的方法是承擔(dān)更多的責(zé)任,這將使你專注于最重要的挑戰(zhàn),而不是細(xì)節(jié)。
我并不是說(shuō)你應(yīng)該同時(shí)處理多項(xiàng)任務(wù),這通常很低效。我的意思是,不要在任何一項(xiàng)任務(wù)上花費(fèi)超過(guò)一周的時(shí)間。當(dāng)然,不是所有的任務(wù)都能在一周內(nèi)完成,這就是問(wèn)題的關(guān)鍵。如果給你的時(shí)間無(wú)限,你就會(huì)找活來(lái)干,這通常會(huì)導(dǎo)致鍍金。然而,如果知道你要把它交給一個(gè)隊(duì)友,那么你就必須確定什么最重要——也許只是創(chuàng)建一個(gè)包含 CRUD 方法的 REST API,或者僅僅是設(shè)置構(gòu)建管道。通過(guò)快速參與和退出,你將在多個(gè)項(xiàng)目中完成 80%的工作。當(dāng)你的同事花了整整一個(gè)月的時(shí)間把一件事情做到 100%的時(shí)候,你會(huì)把四件事情做到 80%,在某種意義上,你的生產(chǎn)力提高了大約 3 倍。我可以告訴你,當(dāng)我成為一名高級(jí)開(kāi)發(fā)人員時(shí),我在許多項(xiàng)目中做出了貢獻(xiàn),這比我在之前的工作中從頭到尾做一件事更有價(jià)值;在我看來(lái),寬度>深度。
8)泰斯勒定律
圖片來(lái)源:https://unsplash.com/photos/OopPIi_A428
又稱復(fù)雜性守恒定律,其思想是,每個(gè)系統(tǒng)都有一個(gè)固有的不可約減的復(fù)雜性,如果要處理它,要么系統(tǒng)變得更復(fù)雜,要么交由用戶來(lái)完成。Larry Tesler 認(rèn)為,最好是花點(diǎn)工程時(shí)間來(lái)改進(jìn)系統(tǒng),而不是指望用戶這么做。這是有道理的——如果你的應(yīng)用有一百萬(wàn)用戶,那么即使一個(gè)工程師花費(fèi)一個(gè)月的時(shí)間從一項(xiàng)操作中減掉了幾次點(diǎn)擊,就可以為百萬(wàn)用戶節(jié)省數(shù)百萬(wàn)次點(diǎn)擊。
在我自己的生活中,這種情況每天都在發(fā)生。當(dāng)我和谷歌家居說(shuō),打開(kāi)燈,改變它們的顏色。我必須給它兩個(gè)單獨(dú)的命令:
嘿,谷歌,把燈開(kāi)到 50%……(等待 5 秒)……嘿,谷歌,把燈調(diào)為白光。
當(dāng)然啦,在人工智能中支持復(fù)合命令難度很大,因此,用戶吸納了這種復(fù)雜性。
運(yùn)用之道
- 避免增加用戶負(fù)擔(dān)的解決方案;觀察用戶如何使用系統(tǒng),并設(shè)法發(fā)現(xiàn)不足。
- 總是選擇花更多的時(shí)間在“正確方法”上,而不是“快速方法”上,即格雷沙姆定律。
- 像用戶一樣思考——你愿意使用你正在構(gòu)建的功能嗎?
買 8 贈(zèng) 1——XY 問(wèn)題
這本身不是一條定律,但感覺(jué)應(yīng)該包括在內(nèi)。當(dāng)一個(gè)解決方案(Y)的提出沒(méi)有充分考慮實(shí)際問(wèn)題(X)的背景,就會(huì)導(dǎo)致更好的解決方案(Z)被忽視,浪費(fèi)精力??紤]一下這樣一個(gè)例子:
老板:“請(qǐng)加大這一頁(yè)的字體。”(建議解決方案 Y)
工程師:“好的?!?/span>
老板(第二天):“你能把它改回來(lái)嗎?用戶說(shuō)太大了?!?/span>
工程師:“好吧——我們一開(kāi)始為什么要改?”
老板:“我們的一個(gè)用戶用的是舊版本的 IE,字體渲染有問(wèn)題?!保?/span>真正的問(wèn)題 X)
工程師:“他就不能用 Chrome 嗎?”(備選方案 Z)
運(yùn)用之道
在上面的例子中,只要工程師問(wèn)幾個(gè)澄清式問(wèn)題,就可以避免浪費(fèi)精力。老板對(duì)解決方案(Y)的執(zhí)著使他看不到可能更好的解決方案(Z)。
在現(xiàn)實(shí)生活中,XY 問(wèn)題通常始于一些聽(tīng)起來(lái)可疑的事情。像“請(qǐng)把字體改大”這樣的請(qǐng)求不是一個(gè)問(wèn)題陳述,而是一個(gè)解決方案陳述。真正的問(wèn)題是“此頁(yè)面在舊的 IE 瀏覽器上顯示不正?!薄_z憾的是,有時(shí)候需要工程師來(lái)提取上下文信息,因?yàn)榻?jīng)常會(huì)缺少需求和工單。但好消息是,這通常并不難——只要說(shuō)“讓我們復(fù)盤下——我們要解決的問(wèn)題是什么”,99%的情況下你都能成功。
你是怎么想的?我漏掉了什么重要的東西嗎?我有什么地方理解的不對(duì)嗎?歡迎留言,以便我可以修改這篇文章。
相關(guān)連接
1. https://en.wikiquote.org/wiki/Murphy’s_law
2. https://www.angelo.edu/faculty/kboudrea/cheap/cheap3_murphy.htm#:~:text=Murphy's Second Law: Nothing is,the one to go wrong.
3. https://en.wikipedia.org/wiki/Conway’s_law
4. https://www.thoughtworks.com/en-us/radar/techniques/inverse-conway-maneuver
5. https://thenewstack.io/led-amazon-microservices-architecture/
6. https://www.britannica.com/topic/Greshams-law
7. https://itnext.io/greshams-law-why-bad-developers-push-out-good-developer-and-developers-create-low-quality-code-9b6a8d15bffb
8. https://dev.solita.fi/2020/06/16/cheap-software-is-expensive.html
9. https://wiki.c2.com/?DemoMeltdown
10. https://theappslab.com/2009/07/17/murphys-law-of-demos/
11. https://levelup.gitconnected.com/the-4-laws-of-the-software-demo-b74b79ca79e3?gi=5ec80c8efa29
12. https://www.hyrumslaw.com/
13. https://en.wikipedia.org/wiki/Thinking,_Fast_and_Slow