开发时,有时会莫名觉得代码写得越复杂,才越显得自己厉害。
大量加入设计模式,层层堆叠抽象层,还会想着“以后可能需要扩展”,提前把接口挖好。
但几年后重新打开那份代码,你会发现真正受苦的是未来的自己。
今天我们来聊聊站在另一端的原则:KISS。
先说结论,KISS 是“Keep It Simple, Stupid”的缩写。直译大概就是“保持简单,笨蛋”。
这是一种设计理念:系统不是做得复杂时运行得最好,而是保持简单时才运行得最好。
KISS 原则是从哪里来的?
这句话原本并不是软件术语。
普遍认为,这句话是 20 世纪 60 年代由美国洛克希德公司的航空工程师 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. 永远用不到的可扩展性
比如只创建一个按钮,却连工厂模式和策略模式都用上。原因是担心“以后按钮类型增加怎么办?”。但这个“以后”大多数时候并不会到来。
3. 条件语句迷宫
if 里面套 if,里面又套一个 if。只嵌套三层,脑内栈就快要溢出了。这时只要用 early return 展开代码,就能让它大幅简化。
遵守 KISS 的 3 个实战标准
所以我写代码时,会用这三点作为标准。
| 标准 | 问题 |
|---|---|
| 说明测试 | 我能在 1 分钟内向旁边的同事解释这段代码吗? |
| 未来测试 | 6 个月后的我看到它,也能马上理解吗? |
| 必要性测试 | 这段代码是因为现在就需要才加入的,还是因为觉得以后可能会用到才加入的? |
只要有一项回答“不能”,我就会重新思考是否存在更简单的方法。
尤其是第三点很重要,它也符合 YAGNI(You Aren’t Gonna Need It)原则。KISS 和 YAGNI 基本上总是成套运作。
简单和粗制滥造不是一回事
这里有一点不能误解。
KISS 并不是“不要思考,随便写”的意思,恰恰相反。
把事情变复杂很容易,因为只要把想到的东西全部加上去就行。把事情变简单却很难,因为必须认真思考该删掉什么。
Pascal 曾在信中留下过一句名言。
因为没有时间写得更短,所以我写得很长。
代码也是一样。简单代码不是敷衍的结果,而是努力去除复杂性的成果。
总结
KISS 原则总结如下。
- 代码被阅读的时间远比编写的时间长。请为阅读代码的人,把代码写得简单。
- 不要加入当前不需要的可扩展性。你担心的情况,实际发生的概率比想象中低得多。
- 简单不是能力不足,而是能力的证明。
最近做代码评审时,我好像最常留下的评论就是:“这段代码不能再简单一点吗?”不可思议的是,仅仅这个问题就能同时减少 bug 和评审时间。
你的代码,旁边的同事能在 1 分钟内理解吗?今天不妨问问自己。

