首頁>技術>

Jeremy InfoQ

作者 | Jeremy Mikkola

譯者 | 王者

策劃 | 萬佳

軟體開發為什麼如此之難?本文認為這種困難與程式語言無關,因為現代的程式語言已經足夠好了。那麼,原因到底是什麼?

有一種觀點認為,使用更好的程式語言就會讓軟體開發變得更容易、更高效。在彙編或 Fortran 時代,這種觀點無疑是對的。然而,現代的程式語言已經足夠好了,目前的主要困難和改進機會出現在其他方面。程式設計仍然很難,但導致這種困難的原因卻與所使用的程式語言無關。

1安達爾定律

當你有一系列需要完成的連續性任務時,安達爾定律就會發揮作用。安達爾定律告訴我們,透過加快其中的一個任務來加快整個系列任務的速度是有硬性限制的。

例如,燒開水需要 10 分鐘,然後煮義大利麵也需要 10 分鐘。即使你能夠找到一種可以更快把水燒開的方法,你做一頓飯的時間也絕對不會少於煮義大利麵所需的 10 分鐘。

一般的公式是這樣的,如果某項任務的總時間佔比是 p,那麼你永遠都無法獲得大於 1/(1-p) 的加速。假設任務的一部分佔用了 90% 的時間,那麼 p=0.90,將這個部分最佳化到零時間,將使整個工作速度提高 1/(1-0.90)=10 倍。

安達爾定律的關鍵點在於,你所能獲得的加速受到了你所最佳化部分的大小限制。

程式設計之所以困難,原因有很多。為了簡單起見,我們可以把困難的事情想象成必須按順序完成的任務。畢竟,人類並不擅長多工處理。在任意一個時刻,你要麼在使用構建工具,要麼在閱讀文件,要麼在編寫程式碼或者參加會議。你一次只能應對一項任務,所以安達爾定律大致適用。如果你設法將構建時間降到零,那麼專案的完成時間也只會短一點點。你的效率仍然受限於完成專案所需的其他事項。

過去,把一個程式翻譯成計算機可以執行的東西是非常困難的。很久以前,需要先將程式轉成 1 和 0,然後再一個一個地輸入到計算機。我不知道這需要花費多少時間,但為了便於討論,我們假設需要佔用 90% 的時間。這意味著,如果有一種更好的方式來告訴計算機該做什麼(比如 Python),那麼程式設計效率將提高 10 倍。

現在,我們有了更好的程式語言,可以花更少的時間告訴計算機該做什麼,生產力得到提升。將程式轉成程式碼不再需要 90% 的時間,現在只需要 10% 的時間。這意味著我們可以從中獲得的最大改變是 1.11 倍,這比以前可以獲得的加速少 81 倍!

這是因為軟體開發其餘的 90% 任務都是困難的任務,一個更好的程式語言不會讓它們變得更容易。

2如何做到“沒朋友”

我的意思是,程式設計的難度與程式語言無關。為了理解其中的原因,我們先假設不需要操心與計算機相關的東西,你只需要告訴你的朋友要做些什麼。你不能作弊,不能讓他們依賴常識性的東西,你必須替他們做出所有的決定。

你的朋友需要知道所有可能出現的情況,有大量的小細節需要處理,例如使用者不能在購物車中輸入負數個產品。使用者可能會嘗試做出所有可能的行為,會發生各種可能的事情,例如包裹在運輸過程中弄丟了,你會發現有大量的邊界情況需要告訴你的朋友。

向你的朋友解釋這一切是很困難的。首先,你需要了解與專案相關的所有現實世界的細節 (產品可能缺貨,可能有折扣,等等)。其次,你需要做出程式在各種可能的情況下應該做什麼的決定。第三,你需要以一種你的朋友能夠理解的方式與他們交流。這意味著你需要組織好你的想法,讓它們易於理解。如果你寫過文章或部落格,你就會知道傳達大量的資訊並不是一件容易的事情!

請注意,到目前為止,這些任務都還沒有涉及計算機,當然也就不涉及程式語言。瞭解現實世界,瞭解程式應該做什麼,以及如何組織這些想法,這些都是非常困難的任務。

3描述與規範

這裡有一個容易就掉進去的陷阱,人們很容易忽略描述與規範之間的區別。例如,當你做出一個描述 (“一輛紅色的汽車”),你可以測試一個東西是否符合這個描述 (“是的,它是紅色的,但它不是一輛汽車”),但這不足以告訴你如何製造一輛汽車,因為製造汽車需要製造汽車的規範。

創造出一樣東西需要做很多決定。如果你把每一個決定的結果都寫下來,就有了一個(未組織的)規範。開發程式需要你做出這些決定,所以僅僅進行描述是不夠的——你需要一個規範。當你做出一個描述 (“它需要把檔案列出來”),認為它就是一個規範,卻忽略了你還需要做出其他無數個細小的決定 (“它應該以什麼順序列出檔案?它們應該按照自己的路線走下去嗎?”)。

當你要開始寫一個程式時,你不得不面對這樣的現實,即你的規範實際上只是描述而已。電腦不會接受類似“畫一個矩形”這樣的描述,它需要知道矩形應該出現在螢幕的什麼地方,應該多大,應該是什麼顏色的。將想法變成程式碼,你還需要做出很多決定,而做出這些決定需要付出很大的努力。人們傾向於將這種努力歸咎於程式語言,卻不願承認這樣一個簡單的事實:僅給出描述是很難得到規範的。

4回到計算機上來

開發軟體不僅僅是理解要做什麼並將其轉化為程式碼。計算機本身存在一些問題,這些問題也需要程式來解決。程式要能夠在硬體和網路上快速執行,可能需要處理機器故障,而工具和協議的複雜性帶來了更多問題。這些問題並非是在向計算機解釋應該做什麼的過程中造成的,它們都是原本就需要做出解釋的事情。

你需要在腦子裡“執行”部分程式。有時候,邏輯就像聽故事一樣容易理解,但有時候,事件順序和狀態跟蹤複雜到無法放在腦子裡。獲得執行正確的程式——或者糾正它們不正確的行為——需要了解程式在各種情況下的狀態。

寫程式碼可以將你對程式的想法具體化,但程式不會保持一成不變。你會發現 bug,想要新的特性,需要改變現有的行為。一個解決方案在一開始可能行得通,但這並不意味著它將一直是可行的。最終,你需要花時間去預測未來,去收拾爛攤子,你會不可避免地發現自己並沒有“千里眼”。

5康威定律

如果你自己不寫程式,就需要和其他人一起工作,這帶來了一系列全新挑戰。

所有參與專案的人都必須以某種方式組織起來,每個人都有自己的工作要做。你不希望人們互相妨礙,所以必須分工。合理的分工要求你對程式的結構有很好的理解,這個時候康威定律就發揮作用了。

如果你有多個團隊,事情就會變得更加困難。每個團隊都有不同的目標,因此會針對不同的事情進行最佳化。對其他團隊有利的決定可能會阻礙你完成工作。瞭解其他人的立場,並找到一個好的妥協方案,這是一項艱難的任務,但你必須完成。

在大專案中,不可能有哪個團隊(更不用說哪個人)能瞭解所有的東西,但你仍然需要弄清楚如何設計系統的各個部分,並讓這些部分相互配合,這比你自己做出整個設計要困難得多。

6“打破”定律

我們可以嘗試找到安達爾定律無法發揮作用的地方。如果個體任務的速度不是完全獨立的——如果你可以透過最佳化一個任務來加快另一個任務——那麼就有可能找到對你有幫助的解決方案。

更好的程式語言和開發環境可能是我們可以加以利用的地方。如果程式可以由更少的人來開發——比如說兩個人,而不是一個團隊,或者一個團隊,而不是一個部門——那就可以大大地減少組織方面的開銷。如果你自己實現介面所有的程式碼,就不需要透過開會來決定如何設計介面。效率的提升不僅會降低編寫程式碼的成本,還會改變工作的形式,從而降低其他任務的成本。也就是說,這裡的限制變成了你可以在這條路上走多遠,因為一個程式設計師不可能把所有跟實現業務相關的東西都裝進腦子裡。

迭代速度是另一個可以加以利用的槓桿。為了開發一個程式,你需要了解這個領域的問題和需要做出哪些決定。為了完成這些任務,你需要把收集到的所有細節都裝到腦子裡,然後形成一個心理模型。這是一種可行的方法,但可能不是最有效的方法。另一種方法是基於某些明顯的細節建立一個小的心理模型,然後根據這個模型建立一個小程式來測試這些想法是否符合現實,並根據反饋進行迭代,每次都創建出更豐富和更準確的模型。這似乎更適合人們實際的學習方式。為了讓這種方法奏效,你需要能夠快速測試想法並獲得反饋。理想的狀態是,在你完成輸入後,新程式碼就可以開始執行。透過改變開發環境來實現更快的迭代週期,將使開發人員從第一種方法轉到第二種方法,幫助他們更好地理解問題。

一種表達能力更強的程式語言是否能有效地提高生產力,對於這一點我並不是特別樂觀。我希望的是能有更好的開發環境。如果我們有更好的工具來理解現有的程式碼,有更快的開發迭代週期,繁瑣的工作變得更少,就可能會改變軟體的開發方式,並以一種複合而非遞減的方式給我們帶來回報。

8
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • TypeScript 使用var宣告變數