開發時,有時會莫名覺得程式碼寫得越複雜,才代表自己越厲害。
大量套用設計模式、堆疊抽象化層,還會想著「之後可能需要擴充」,先把介面挖好。
但幾年後重新開啟那份程式碼,才發現真正受苦的是未來的自己。
今天來聊聊站在另一端的原則: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 展開,程式碼就會簡單許多。
遵守 KISS 的 3 個實戰標準
所以我寫程式碼時,會以這三點作為標準。
| 標準 | 問題 |
|---|---|
| 說明測試 | 我能在 1 分鐘內向座位旁的同事說明這段程式碼嗎? |
| 未來測試 | 6 個月後的我看到它,也能立刻理解嗎? |
| 必要性測試 | 這段程式碼是因為現在就需要才加入,還是因為覺得某天可能會用到才加入? |
只要其中一項回答「不行」,我就會重新思考是否有更簡單的方法。
尤其第三點很重要,這也與 YAGNI(You Aren’t Gonna Need It)原則相通。KISS 和 YAGNI 基本上總是成套運作。
簡單和隨便做是不一樣的
這裡有一點不能誤會。
KISS 不是「不用思考,隨便寫」的意思,反而正好相反。
把事情變複雜很容易,因為只要把想到的東西全部加上去就好。要做到簡單卻很難,因為必須仔細思考該刪掉什麼。
Pascal 曾在信中留下這句名言。
因為沒有時間寫得更短,所以我寫得很長。
程式碼也是一樣。簡單的程式碼不是隨便做出的結果,而是努力去除複雜性的成果。
總結
KISS 原則總結如下。
- 程式碼被閱讀的時間遠比撰寫的時間長。請為閱讀它的人,把程式碼寫得簡單。
- 不要加入現在不需要的擴充性。你擔心的情況,實際發生的機率比想像中低得多。
- 簡單不是能力不足,而是能力的證明。
最近在程式碼審查中,我好像最常留下「這段不能再簡單一點嗎?」這個評論。不可思議的是,光靠這個問題,就能同時減少錯誤和審查時間。
你的程式碼,座位旁的同事能在 1 分鐘內理解嗎?今天不妨問問自己。

