軟體設計

KISS 原則:把程式碼寫得簡單,真正的意義是什麼

開發時,有時會莫名覺得程式碼寫得越複雜,才代表自己越厲害。

閱讀 4 分鐘
KISS 原則:把程式碼寫得簡單,真正的意義是什麼 封面圖

開發時,有時會莫名覺得程式碼寫得越複雜,才代表自己越厲害。

大量套用設計模式、堆疊抽象化層,還會想著「之後可能需要擴充」,先把介面挖好。

但幾年後重新開啟那份程式碼,才發現真正受苦的是未來的自己。

今天來聊聊站在另一端的原則:KISS。

先說結論,KISS 是「Keep It Simple, Stupid」的縮寫。直譯大概是「保持簡單,笨蛋」。

這是一種設計理念:系統不是做得複雜時運作得最好,而是維持簡單時才最可靠。


KISS 原則是從哪裡來的?

這句話原本並不是軟體術語。

一般認為這句話是 1960 年代由美國洛克希德公司的航空工程師 Kelly Johnson 提出的。他設計了著名的 U-2 與 SR-71 Blackbird 偵察機。

據說 Kelly Johnson 對團隊提出了這樣的要求。

打造一架在戰鬥情況下,普通維修人員只用基本工具就能修理的飛機。

無論設計多麼出色,如果無法在現場修理,就沒有意義。

這種精神後來延伸到軟體領域。程式碼再怎麼巧妙,如果同事無法閱讀並修正,就稱不上好程式碼。

順帶一提,「Stupid」不是在叫開發者笨,而是更接近「簡單到連任何人都能理解」的語氣。


程式碼中 KISS 被破壞的時刻

說起來容易,但在實際程式碼中會是什麼樣子?以下分享幾種我常見的模式。

1. 看起來很厲害的一行程式碼

// 這樣寫看起來很聰明
let result = arr.reduce([Int: Item]()) { $0.merging([$1.id: $1]) { _, new in new } }

// 這樣更容易閱讀
var result = [Int: Item]()
for item in arr {
    result[item.id] = item
}

上面的程式碼雖然很短,但第一次看到的人得盯著看很久。下面的程式碼則任誰都能在 3 秒內理解。

2. 根本用不到的擴充性

例如只做一個按鈕,卻連 Factory Pattern 和 Strategy Pattern 都搬出來。這是因為擔心「之後按鈕種類變多怎麼辦?」但那個「之後」大多不會到來。

3. 條件判斷迷宮

if 裡面放 if,裡面又放另一個 if。只要巢狀三層,腦中的堆疊就快爆了。這時只要用 early return 展開,程式碼就會簡單許多。

複雜程式碼與簡單程式碼,6 個月後就會看出差異
複雜程式碼與簡單程式碼,6 個月後就會看出差異

遵守 KISS 的 3 個實戰標準

所以我寫程式碼時,會以這三點作為標準。

標準 問題
說明測試 我能在 1 分鐘內向座位旁的同事說明這段程式碼嗎?
未來測試 6 個月後的我看到它,也能立刻理解嗎?
必要性測試 這段程式碼是因為現在就需要才加入,還是因為覺得某天可能會用到才加入?

只要其中一項回答「不行」,我就會重新思考是否有更簡單的方法。

尤其第三點很重要,這也與 YAGNI(You Aren’t Gonna Need It)原則相通。KISS 和 YAGNI 基本上總是成套運作。


簡單和隨便做是不一樣的

這裡有一點不能誤會。

KISS 不是「不用思考,隨便寫」的意思,反而正好相反。

把事情變複雜很容易,因為只要把想到的東西全部加上去就好。要做到簡單卻很難,因為必須仔細思考該刪掉什麼。

Pascal 曾在信中留下這句名言。

因為沒有時間寫得更短,所以我寫得很長。

程式碼也是一樣。簡單的程式碼不是隨便做出的結果,而是努力去除複雜性的成果。

簡單,是不斷刪減的成果
簡單,是不斷刪減的成果

總結

KISS 原則總結如下。

  • 程式碼被閱讀的時間遠比撰寫的時間長。請為閱讀它的人,把程式碼寫得簡單。
  • 不要加入現在不需要的擴充性。你擔心的情況,實際發生的機率比想像中低得多。
  • 簡單不是能力不足,而是能力的證明。

最近在程式碼審查中,我好像最常留下「這段不能再簡單一點嗎?」這個評論。不可思議的是,光靠這個問題,就能同時減少錯誤和審查時間。

你的程式碼,座位旁的同事能在 1 分鐘內理解嗎?今天不妨問問自己。

延伸閱讀