應用軟體開發 7 宗罪
如何提高應用軟體開發的產出
--
以台灣來講,大概每一兩年,就會出現一兩則大公司發生災難級的軟體開發失敗的新聞,比方說,系統永遠上不了線之類的。實務上,不只是大公司、中小企業、即使是新創,在軟體開發遇到困難也是稀鬆平常的事。管理階層可能會認為,套用了某些方法論或是雇用了薪水很高的軟體開發人員,這些問題就可以得到控制。然而,在許多不同領域的實務往往是:「如果沒有探討發生問題的根源,就逕行套用一些『別人宣稱會有效的解決方案』,得到的成果往往有限。」畢竟,我們要如何確定,發表在媒體上的成功方法,技術成分大於公關成分呢?
在我的經驗,應用軟體開發流程裡常見的錯誤,至少有7項。不幸的事情是,這7項容易犯下的錯誤,不僅專案經理人不了解,管理階層不了解,連軟體開發人員也常常不了解。
7項應用軟體開發流程的錯誤
- 軟體規格書缺乏使用情境的資訊
- 軟體規格書缺乏對時間、事件、功能性驗証的描述
- 不合時宜的招募策略與分工方式
- 不知道該如何評估成效
- 過早的最佳化
- 分不清楚 simple 與 easy
- 盲從潮流、執著於教條
上述7項裡,1, 2 兩項屬於規畫階段的錯誤、3, 4 兩項屬於管理層面的錯誤、5, 6 兩項算是軟體工程的錯誤。最後一項錯誤有普遍性,無論是哪一個層級、哪一種專業,都很容易達成。
缺乏使用情境的資訊
我曾經被案主委託過一個軟體開發案,案主最初與我詳談的重點,全都放在使用者界面,他不斷地告訴我,使用者界面 (UI) 對他來說,超級重要,沒有好的 UI,團隊的工作是如何如何地受影響;之後的功能都可以日後再討論,先請我無論如何幫他把 UI 刻出來搭配一個簡易的 CRUD (create, read, update, delete) 功能。過了兩個月後,案主則告訴我,使用者界面不太重要,報表可以用 Excel 的格式下載即可。後來,我才理解,其實該專案最核心的價值創造部分,在於產出商業智慧 (Business Intelligence) 的報表。以這個案例來講,如果讓我重做一遍,軟體規格書最初描述的重點,自然是先放在最關鍵的報表部分。而我後來自己檢討,是我自己沒有想清楚,因為該案主就是 BI 團隊的負責人,
實務上,往往不是只靠與使用者交談,即可以取得使用情境的資訊。專注於聆聽於使用者的敘述,使用者常常傾向於訴說:『他們認為可行的解決方案,而非他們真實的使用情境。』
軟體規格書缺乏對時間、事件、功能性驗証的描述
客戶有時候會用不適用的工具,來試圖描述所需的軟體。我曾有一位客戶,總是指派他信任的下屬來寫規格書給我。這些規格書往往是用 PowerPoint 寫的,對使用者界面的部分,描述過多的實作細節,卻完全沒有描述遠比使用者介面更重要的:時間, 事件, 功能性驗証。我拿到規格書之後,看到許多的 UI 元件,UI 元件描述了它們該做什麼,卻沒有明確地講清楚先後次序與 UI 事件發生彼此的依賴關系,這就是缺乏時間與事件的描述。
再談一個缺乏「功能性驗証」的例子,我的一位會計師客戶請我設計一個 UI 元件,該元件的功能是:『提供一個選項,讓報表可以產出,最近一年的某財務資訊報表。』等到驗收軟體時刻,我們雙方才同時搞懂:『一年是 365 年這件事,只算是 75% 正確,因為閏年是 366 天。』
不合時宜的招募策略與分工方式
有一些中小企業認為,既然大公司招募軟體工程師考 codility 或是 leetcode ,我們也應該如此做,才能招募到能力優秀的軟體工程師。然而,大公司由於開出的薪資偏高,一旦有新職缺,應徵者相當多,所以先用白板考的方式,快速篩掉大量的應徵者,以集中有限的資源來面試剩下來高可能性的應徵者。中小企業如果沒有理解上述的方式是一種權宜之計,而單純地認為,善長白板考就等於專業能力,很可能會在招募上遇到許多挫折。
「不考演算法的話,如何確保工程師可以寫出效能夠好的程式?」曾經有客戶如此質疑我。
「在 ACM 比賽時,探討的效能著重於 Big O complexity 。然而,實務中應用軟體開發,需要探討的效能問題,十之八九不是 Big O 而是 IO 。」我如此地回答了他。
同樣的道理,軟體開發,大公司因為人手充足,總是設法組成 6、7 人的開發團隊,比方說,拆成前端、後端、專案管理、運維、測試等,這也不代表中小企業就應該仿效。實際上,在不過分犧牲軟體品質的前提之下,一人身兼多職,反而容易有高產出。將工作做精細地拆分,也許找人相對容易,作工也可以更加精細,另一方面,拆分地愈細,專業人士往往就離最終的產出愈遠,因為每個人都只專注於分割到自己手上的工作。拆分工作,妥善地協調,並得到有效的產出,這往往需要一種中小企業很容易缺乏的關鍵能力:管理。
不知道該如何評估成效
在『彼得原理』對於「不知道該如何評估成效」導致的狀況,有獨到的見解:不適任的主管在評估下屬時,是以下屬在工作投入 (input) 的程度來評估;因為該主管已經不適任了,所以他也不了解什麼是正確、應然的工作產出 (output)。
在我個人的經驗,就算是了解工作產出的主管,在評估成效時,常犯下的錯誤,則是片面評估、或是見樹不見林。片面評估是指:只評估了一個面向、而沒有評估所有必須評估的面向。比方說,只著重軟體準時交付,而忽略了長期而言是否可以迭代開發。
見樹不見林則是指:沒有把整個系統納入思考、沒有全局觀。以資訊安全為例,我曾看到一種情況,某些組織在委外軟體時,對於軟體要求一些 ISO 的認証。然而,該組織的員工卻極度缺乏資安觀念。於是,面對真正的駭客,使用基本的社交工程招式就可以騙取密碼。
曾經有一個客戶詢問我,「要如何可以提高軟體交付時程的能見度?」我反問了客戶一個問題,「貴公司在開發新的軟體功能時,是否會先設法達成 walking skeleton, 再繼續前進?」開發軟體的時程,總是有很多的不確定性,比方說,為了處理 A 資料格式,於是使用了 B 函式庫。每次引入一個新的函式庫,就等同於引入了一個新的不確定性。再加上本來處理業務邏輯也可能有一定程度的不確定性,不確定性逐步累加,準時交付就變成了一種量子現象。估時不準確,這是軟體開發的普遍現象,然而,成熟的軟體開發團隊會傾向於 fail fast and fail early ,讓不確定的因素,可以早期被發現,再重新估時。一旦完成了 walking skeleton ,至少因為引入函式庫或是與外界溝通造成的不確定性已經移除了。
過早的最佳化
有的軟體開發人員認為,所謂『過早的最佳化』只是指效能改進而言。只要效能改進等到系統完成再來做,就不會造成『過早的最佳化』。我則持另一種看法,我認為如果只需要達成 60分的應用卻採用了可以達成 95分的技術,都可以視為是『過早的最佳化』,比方說:
- 複雜的軟體架構,比方說: microservices、甚至是 kubernates
- 極致的使用者體驗,比方說:mobile application 或是 SPA (single page application)
- 過多的效能、可擴展性 (scalability),比方說:NoSQL 或是 IaaS
- 100 % 的測試覆蓋、複雜的型別系統
一旦做了過早的最佳化,相當於在只需要做到 60 分的項目上,不停地投注 95 分的心力,軟體開發自然快不起來。
分不清楚 simple 與 easy
在軟體工程的老生常談是要把系統做得簡單 (simple)。然而,簡單 (simple) 與容易 (easy) 這兩個概念實在是非常容易混淆。也因此,實務上,很多工程師做到了 容易,卻以為自己達成的是簡單。easy 是軟體開發者對難度的感受,這個因人而異,而且常常跟熟悉、熟練度有關。simple 則是指系統內部,是否有相對清楚、不交錯的依賴關系。easy 是一種主觀的感受,而 simple 則是一種客觀的性質。
以常見的 OTLP 應用來舉例:
- 直接手寫 SQL,這是 simple 卻不 easy 的解決方案
- 透過 ORM (Object Relational Mapping) 之類的工具來產生 SQL ,則是 easy 但是不 simple 的解決方案。
對於不喜歡寫 SQL、對 SQL 不熟悉的開發者,ORM 可以讓這些軟體開發者在不甚了解 SQL 的前提之下,在系統初期的階段,快速地前進,這會讓開發者覺得非常的 easy 。然而,透過 ORM 產生的 SQL 查詢 ,卻常會在一些特定的案例會產生效能低下的查詢。於是,採用了 ORM 之後,造成的結果是,要用 ORM 來建構正確可用的系統,至少必須依賴於四件事:
- 軟體開發者對 ORM 的了解
- 軟體開發者對 SQL 的了解
- 軟體開發者對 ORM 相對少見例外的充分了解
- 軟體開發者對 ORM 難以處理例外發生時,該怎麼處理的充分了解
最糟的事情莫過於,即使如此,如果系統持續演進,系統很可能還會更加複雜。一次又一次為了解決 ORM 不足之處上加上的補丁設計,又會再一次地成為新的依賴。
盲從潮流、執著於教條
盲從潮流,有時候跟大公司強大的行銷能力頗有關系。
比方說,像大公司想要新創公司都用 IaaS (Infrastructure as a Service) 的雲端服務,二話不說,就先送新創小公司一兩年的免費額度。然而,問題出在,要妥善地使用 IaaS 往往比要使用 PaaS (Platform as a Service) 需要更多的運維人力,對於新創小公司來講,省了一兩年的雲端伺服器費用,往往是付出數倍的運維管理成本。
另一種情況,大公司想要推廣自家的某某技術來強化自己在人才招募上的優勢,比方說,某種程式語言,於是就讓一些 IT 媒體做一些專訪,美其名為專訪,實則為置入性行銷。於是,媒體大力報導的軟體技術每年不停地更替,像是永無休止一般。軟體工程師與需要招募軟體工程師的雇主,也容易誤認為,採用新的技術棧就是創新能力的表現,因而雙方都不停地追趕新的技術棧。但是,採用這些技術棧真的就可以提高生產力嗎?
該怎麼避免這些錯誤?
每個軟體開發團隊的任務特性不同,不會有一種方法適用於各種團隊。要避免上述的 7 項錯誤,需要在採用某一特定的工作方法之前,先仔細地思考任務的應用情境,與某一工作方法是否相契合。
對於新創公司、中小企業、又或是交付時程極為緊迫的軟體開發團隊而言,通常可以滿足下列的假設:
- 客戶的需求常常變動、使用者常常難以在最初把需求徹底地講清楚
- 使用者介面的極致體驗、軟體運行的效能、軟體是否容錯這些事的重要性,低於軟體的準時交付與正確性。
如果上述兩項假設都滿足的話,我通常建議客戶採用下列的技術棧與方法論,來做一般 (OLTP) 應用軟體開發的預設選項 (default option)。這些技術棧與方法論,保守地評估,已足以解決 90% 的應用情境。
- 軟體規格採用 event modeling method
- 評估成效採用 the four key metrics
- 前端採用 htmx
- 後端採用 Clojure
- 資料庫採用 Postgres 或是 XTDB (如果需要時間迴溯與 bitemporality 的功能的話,可以考慮 XTDB)
- 分散式的應用,採用 Actor-based 的方式來開發,而非 Microservices
又或者是,你也可以考慮連絡我?