ExplainThis 全端開發雙週報 #63 如何降低程式碼複雜度,讓程式更容易維護?
如何降低程式碼複雜度,讓程式更容易維護?
嗨~歡迎閱讀全端開發雙週報 #63 期
相信對多數軟體工程師來說,會希望自己的程式碼越寫越好。然而 「程式碼寫得好」是什麼意思呢? 要如何定義什麼是好什麼是不好? 畢竟如果沒有一個判斷準則,要如何知道自己的程式碼是越寫越好,還是越寫越糟糕呢?
關於這些問題,在業界中有不同的指標來協助衡量,其中一個指標是複雜度 (complexity)。從複雜度的角度切入,能夠達到同樣功能的程式碼,如果寫得越不複雜,就會讓未來讀該程式碼的讀者,越容易理解與維護,也會被說該程式碼寫得好。
對此,寫出低複雜度的軟體程式,對於每個軟體工程師來說,都是不可或缺的能力。在這期主題文,我們會來談軟體程式的複雜度是什麼,如何降低複雜度,讓程式更容易維護。
進入主題文前,由於最近在 ExplainThis 的 IG 上陸續有讀者詢問「E+ 成長計畫訂閱三期轉終身」的方案,這邊與讀者們分享,先前我們有提過,由於 E+ 內容已經累積到一定的量,在明年開始會調整方案與定價。
讀者們只要在 2025 年底前訂閱 (連結),都能以目前的訂閱價格,在連續訂閱三期後,自動轉成終身會員 (在滿第三期後,ExplainThis 將主動取消 Stripe 上的續訂,並將讀者的內容與社群等權限轉為終身)。
以上分享,接著讓我們進到這期的主題文吧!
如何降低程式碼複雜度,讓程式更容易維護?
當談到維護軟體程式的複雜度,談的會是該程式有多容易懂,以及有多容易改。
換句話說,假如今天有個新加入團隊的成員,在被交付某個新的功能開發時,發現原有的程式碼庫寫得讓人很難懂;或想改某段原有程式碼時,發現要有很大的改動才能改好,這兩種狀況都是程式的複雜度過高的表徵。
假如今天你要在一段程式碼寫得又臭又長 (例如俗稱的義大利麵程式碼 spaghetti code) 加上新功能,可能在處理程式碼時會覺得很崩潰,因為無法一眼看懂程式碼到底在做什麼。但假如同樣的功能,被用複雜度很低的方式寫,看到時反而可能會被用欣賞的角度稱讚。
複雜度是會累積的,因此如果在一開始輕忽,很可能會逐漸累積,到最後變得非常難維護,因此不能因小而不為,應該要在寫每一段程式碼時,都確保複雜度能被有效降低。
不過這時讀者們可能會問「該如何確保程式碼好讀、好改呢?」
讓程式碼更容易讀
會導致程式碼不容易讀,很常會因為需要過多先備知識,導致維護者的認知負擔過大。換句話說,如果需要的先備知識越多,就意味著程式碼造成開發者的認知負擔越高。
舉例來說,在用一台微波爐之前,要先去了解微波爐背後的物理原理,或是需要先了解微波爐在製造過程的細節,那麼多數人應該都不會知道該怎麼用一台微波爐。這就是所謂認知負擔過重。不過好在現代的微波爐設計簡單到小朋友都能夠輕易操作,這種讓操作者不須知道太多先備知識,可以說是好設計的典範。
同樣的道理,在設計程式時,如果設計得讓其他協作者,需要花很多時間去了解,那這時的複雜度就會是過高的。
舉例來說,假如今天後端開發給前端呼叫的 API,假如前端需要先 GET /api/posts/{postId} 拿文章基本資料。然後前端還要再拿著文章中的 commentId 去呼叫 GET /api/comments/{commentId} ,去拿到文章的留言。這種方式就會讓未來的維護者在維護時,處理 comment 的部分時還要先去了解相關的依賴關係,這就是難讀的表徵。
而現在的前後端開發,如果是走像上面這種 RESTful 的形式,可能會透過 BFF (Backend-for-Frontend) 這一層來處理掉,讓前端只需用呼叫一支 API 即可。又或者如果是用 GraphQL 的形式,也是可以讓前端簡單地呼叫一支 API,這樣就讓前端在串接 API 時的認知負擔會比較小。
讓程式碼好改
如果要讓程式碼好改,一個有效的方式是把程式碼寫得不會有「每次要改,就得要改一堆地方」。
舉例來說,像是下面這樣的寫法,如果要改顏色,要去三個頁面分別改:
// A 頁面中
<Button color=”#ff5050”/>
// B 頁面中
<Box backgroundColor=”#ff5050” />
// C 頁面中
<SnackBar color=”#ff5050” />
若要解決這個問題,可以把主題色抽出來,讓我們只需改一個地方,就能全都改:
// 定義好主題色,讓其他地方引用
// 之後只要改主題色,其他地方都會改,因此只需改一個地方即可
const primary = “#ff5050”
// A 頁面中
<Button color={primary}/>
// B 頁面中
<Box backgroundColor={primary} />
// C 頁面中
<SnackBar color={primary} />
這種把通用的東西抽出來,不只是用在變數,在處理類別、方法、函式時,這個做法都能讓改動變得更容易。
當然,除了上面這個簡單但有效的方法外,還有許多原則與技巧,可以用來協助寫出複雜度更低、更容易維護的程式碼。在下個月 E+ 成長計畫預計推出《如何寫出好維護的程式碼》線上課程,感興趣的讀者歡迎加入 E+ (連結),課程上線後可以第一時間觀看。
彩蛋
這週看到沉寂兩年沒有發影片的 Joma Tech,在睽違兩年後發了新影片 life of an AI startup founder/CEO (連結),內容既好笑又寫實,道出在新創公司不為人知的壓力。
在影片的最後,有這麼一段話「帶著幽默感,通常代表你會好起來;也代表大家會喜歡你。只要能一直保持下去,就還有希望」。
“A sense of humor is the best indicator that you will recover; it is often the best indicator that people will love you. Sustain that and you have hope.”
― Andrew Solomon
不只是在新創公司工作,在各個領域當軟體工程師,都免不了要面對壓力,工作不會總是順風順水。在面對不如意時,保持幽默感能讓自己在度過眼下的難關時不那麼苦悶。
本期推薦
這週在社群看到 Making Software 這個網站 (連結),在談軟體背後被抽象掉的實作,目前連載到第二篇文,但目錄上後續的內容也讓人期待。另外,不得不說這個網站做得真得很精緻,非常佩服該作者
最近 JavaScript 執行環境 Bun 出了《Behind The Scenes of Bun Install》 一文,從系統程式 (system programming) 的角度拆解如何優化效能,非常精彩 (連結)
Zed 是近期非常熱門的開源 IDE,該團隊上週寫了一篇《Hired Through GitHub: Part 1》 (連結);有別於先前我們分享過從求職者的角度「透過貢獻開源找到工作」的內容 (連結),Zed 是從公司的角度談哪類貢獻者,會讓公司想要聘用。如果有想透過這方式找工作,推薦一讀 。
先前在開源界小有名氣的 TkDodo 寫了《Deriving Client State from Server State》一文 (連結),談客戶端與伺服器端的狀態管理;這兩種狀態管理的區分與設計,是資深前端工程師在面試中,很常會被問的,推薦不熟的讀者一讀。
前陣子 Phil Eaton 分享了 《In response to a developer asking about systems》 一文,談他如何學習系統相關的知識,裡面談的點非常精闢 (連結)
Tesla 首席工程師 Colin Breck 今年給了《Predicting the Future of Distributed Systems》演講 (連結),談他對未來分散式系統的預測,整個演講深入淺出,值得一看
過去兩週我們有在社群分享一些免費的課程,包含CMU Database Group 免費又全面的資料庫相關課程 (連結),以及前 Netflix 工程師 ThePrimeagen 做的免費資料結構演算法課程 (連結)。對相關主題感興趣的讀者,可以參考

