人月神話讀後心得

軟體工程其實是管理學

大學時讀過一遍,最近再讀一遍,發覺書中說的觀念仍然適用。工作經驗愈久,愈能認同書中所言。可能有些當時新穎的觀念,現在已被視為常識 (例如要用漸進式開發模型而不是瀑布模型)。也因為這樣,重看後其實沒學到什麼新東西,如同作者在《人月神話二十年後》自我調侃:

… 坐在我旁邊的那位陌生人正在看《人月神話》,而我一直在等,等看看他會不會有什麼反應,也許是一番話或某些表示。最後,飛機終於降落滑向了登機門,我不能再等了:
「這本書如何?你喜歡嗎?」
「哦!這裡頭講的都是我老早就知道的東西。」
我決定不作自我介紹了。

作者認為相較於其它技術,《人月神話》之所以能歷久不衰,主要是本書在討論人的問題,而不是技術問題。軟體開發的重點在於如何讓組織有效率地運作。以下分幾個方面整理心得。

系統設計的概念整體性 (conceptual integrity)

書中認為保有概念整體性是系統設計時最重要的原則,包含功能的使用介面和背後的軟體架構。多人的想法很難一致,也不易管理。因此,專制是必要的。

但在專制的背後,實作人員仍有很大的發揮空間。架構設計須獨立於實作: 架構師可以提供一種實作建議,但不能指定如何實作。舉例來說,架構師定了一個服務可以快速找出某個時間範圍內的資料。實作的人要用 binary tree、sorted array 都無所謂,只要符合規格即可。

此外,作者認為這種限制反而讓實作者更能發揮創意 (“Form is liberating”),因為他會專注在限定的範圍內構想,不會天馬行空。所以專制的結果是雙贏。我滿認同這點的。

架構師在定義規格時要很嚴謹,不只說明有那些規範,不在規範內的也要說清楚。像 C 語言沒有定義函式參數的運算式執行的順序,雖然給編譯器實作者有最佳化發揮的空間 (可以選擇平行執行各參數的運算式),但也增加潛在的問題,例如:

i = 0;
sum = add(i++, i++);

add() 收到的參數是 (0, 0), (0, 1), (1, 0) 的那一個呢?

實務上作者認為要同時有精確的正式定義 (接近數學式那樣)以及易於閱讀的 (散文式定義)。然後兩者選一個為主作為標準,何者為主皆可。

某項實作成果也可當作定義,缺點是會產生一些不好處理的定義。現實似乎比較多這類結果? 如果問我網頁正式的行為是什麼,相較於查閱 W3C 的規範,我可能會以 Chrome 的實作表現為主。若 Chrome 不小心寫了某種 bug,網頁開發者廣為使用,日後這 bug 變成規格,反而不能修正了。

題外話,就我自己的除錯經驗來看,含有明確設計概念的模組,比較不易出錯。即使出錯,也容易預期正確的行為是什麼,知道該往那個方向修正。反之,東拼西湊完成的模組,只有剛好滿足目前已知的問題,看不出整體的概念。出現新問題時,很難判斷什麼才是正確的行為,產生副作用後也不知該繼續修正新的副作用,還是要改用其它設計。

產品規格設計

作者提及要維護產品的概念整體性,必須定義使用者群的行為。有了預期使用者的特徵,才好分析某項設計是否合理。還有需要更改設計時,怎麼改才會更符合目標。比方說手機上的應用程式是否需要單手操作?若這是必須在家裡坐好聚心會神玩的重度遊戲,那單手操作並非必要。若是目標族群多在通勤時加減使用,單手操作是必要的。

作者堅信架構設計師必須去猜目標使用者群的行為,錯誤而明確遠比模糊不清好。因為這樣才有明確的討論。若討論的結果必須驗證特定使用者行為,這時就有足夠理由花費更多成本取得更精確的使用者行為。

團隊組成

作者提倡「外科手術團隊」。以一人為主,其他人輔助處理一個小專案。公司再切成多個團隊處理各個專案。這個作法可因少數人的決策兼顧概念整體性,且減少溝通而提升全員生產力。

團隊之間是樹狀結構是不可免的結果,這樣才能有明確的更高決策單位。但溝通仍是網狀的,因此需要特別組織補足樹狀結構溝通不足的問題。

每個專案都有管理者或技術總監,有三種可行的搭配方法:

  • 一人兼任兩者,但很少會這樣。一來這樣的人少,二來這兩份工作都需要大量時間,即使有這樣的能力,時間也不夠用。
  • 管理者為主,充份授權給技術總監發揮。
  • 技術總監為主,管理者幫忙處理雜事。

管理者最重要的工作是溝通而非做決定。

組織文化

高階管理者需要讓所有人了解和認同組織文化。以我們公司舉例的話,一個常被提及的規則是「做的人最大」。這樣可以維持專案的概念整體性,不會變成一群人意見妥協的四不像。而且獨裁很有效率,每個人都有獨裁的機會 (聽起來很公平!),就看主事者是誰。

為了實踐這點,老闆可以接受許多他認為「正確」的作法不被採納,讓做的人完全發揮。例如使用者介面,從我入公司到現在六年間,老闆的提案不斷被打槍,至今沒有被實作出來,身體力行這點很了不起 (不斷找機會試圖翻盤也很有毅力),因此大家也很能認同和實踐此點。

為避免這樣的文化被濫用,找進來的人要符合公司的文化,不合文化即使能力再好也不適用。一但找進來的人符合文化,其實需要的管理很少,組織自然運作得很有效率。

打造易於改變的組織

作者認為軟體會不斷地變動,組織也因此需要不斷地改變。長遠來說,要打造一個富有彈性利於改變的組織。這比設計利於改變的系統還難。像 Google (還有我現在待的公司) 著重在招收一般性 (通才) 的軟體工程師,這樣無論專案內容如何變化,公司員工都能應付。不用擔心因為方向轉變而需要處理特定專長的員工。例如公司不開發 Android app 後,專職 Android 開發的員工該改做什麼?他們願意接受嗎?還是要全員資遣?

但是缺少特定專長的員工也需要多些時間熟悉特定領域的知識。對於不斷改變的小型新創公司來說,一方面需要搶時間,另一方面也會不斷地改變方向。感覺還是需要有些取捨。多數通才加上少數專才應該是不錯的平衡。

漸近式開發模型

由上而下寫好主程式,然後讓各模組放入空的實作,再一步步由上而下實作內容。一直保持一個可以運行的系統。這樣可以提早測試,完成多少測多少。提早發現問題,提早處理。

這在現今已是常識,不過我剛出社會工作時,還會疑惑要由下而上還是上而下開發。現在已忘了當時疑惑的點,在這裡留個記錄。

在作者的年代還沒有 TDD (Test Driven Development) ,不知過個十年,TDD 是否也會成為常識,被認定是更好的開發模型?我滿喜歡 TDD 的理念,不過實務上怎麼做最有效率,還沒拿準作法。或許架構師在制定架構時將可測性列入主要指標,是實行的必要條件。

重用既有的軟體模組

書中有大量篇幅討論為什麼往後十年內找不到 10x 生產力的方法。然後轉而討論在這樣的前提下,要如何減少開發時間?答案是: 盡可能重用軟體模組。

書裡提到的是購買商用的軟體模組,不過那是 1995 的時代。如今 open source 盛行,更容易重用軟體模組。作者提到軟體重用的關鍵是介面明確易於重覆使用且開發成本高,像數學計算模組是典型的例子。對照到 open source 的話,openssl 或 ffmpeg 都是廣為使用的函式庫,沒有人會想自己重寫 TLS 連線或是影音格式解壓縮演算法。

如今要能更快地完成品質更好的軟體,熟悉使用 open source 是一大關鍵。舉例來說,開發軟體難免會需要處理 Unicode。比起自己了解 UTF-X 的規格細節然後實作,使用 ICU 才是正解。或是參考 Chromium 的作法,可以取得更易於使用的介面。

Brooks法則的例外

(更新於2018/12)

Brooks法則:向進度落後的項目中增加人手,只會使項目更加落後。

這大致上是對的,因為增加人手會增加溝通成本,還有短期訓練成本,都會佔用既有團隊的時間。

但是這裡有個隱含的前提:既有團隊比新加入人手更熟悉開發中的項目。當加入的人手擁有既有團隊需要且缺乏特定領域的知識時,增加人手會有幫助。例如 :Web 服務後期壓力測試 database 效能有問題。向外找 database 專家協助會有幫助。其它像是產品規劃、軟體開發流程也是如此,關鍵在於既有團隊在這方面有多欠缺,加入的人手有多專業。