前两天重构一段祖传代码,我花了整整三个小时才理解原作者的意图。那一刻我突然意识到一个问题:我们写了那么多”优雅”的代码,究竟是写给机器看的,还是写给人看的?
我见过太多这样的场景:面试时候选人炫耀自己用了多少高级特性,代码评审时有人因为用了最新的语法糖而沾沾自喜。但当我问他们”这段代码三个月后你还能看懂吗”,大多数人都沉默了。
好代码的标准,从来不是技术栈有多新,而是——未来读这段代码的人,能否在最短时间内理解它的意图。
聪明但难以维护的代码#
我曾经维护过一段”神级”业务代码,那是前同事的巅峰之作。用一句话概括就是:能用一行代码解决的事,绝不写两行。
具体表现是什么样子呢?
变量名是单个字母,a、b、c、x、y、z不够用了就用aa、ab。函数名?没有函数名,直接一行流把所有逻辑串在一起。注释?不存在的,代码即文档。异常处理?catch住就吞掉,连日志都不打。业务逻辑?嵌套七八层回调,每层都有不同的状态判断。
你问我怎么读懂?我只能 debugger 一步步跟踪,看到数据怎么流转,在某个节点突然发现”哦,原来这里是算折扣的”。但下次遇到类似需求,我还得再 debug 一遍。
这种代码的”聪明”之处在于,它展示了对语言特性的熟练掌握。但代价是,任何人,包括三个月后的自己,都需要花大量时间才能理解。维护成本极高,修改风险极大。
聪明但难懂的代码 - 当时看懂,过后迷茫
简单但清晰的代码#
与之形成鲜明对比的,是我见过的一些”笨拙”但清晰的代码。
什么样的?
变量名是完整的英文单词,calculateDiscount、userOrderList、paymentStatus,看名字就知道这是什么。函数名清晰表达意图,validateInput、processUserRegistration、sendNotificationNotification,一个函数只做一件事。关键逻辑有注释,但不是那种”注释一下这行在干什么”的废话注释,而是”为什么要这样做”的业务意图说明。异常处理会记录日志,会区分不同类型的错误并给出有意义的错误信息。
这样的代码,初看时可能觉得”怎么写这么多行”——因为它把每个步骤都拆开了。但当你需要修改时,你会发现极其顺畅:改价格就去价格相关的函数,找用户逻辑就去用户模块,一切都有迹可循。
我接手过一个项目,代码量比之前的”神级”代码多了一倍,但维护难度降低了十倍。新人入职两周就能上手改需求,而之前那个项目,三个月能独立改需求就已经是高手了。
简单但清晰的代码 - 一目了然,经久耐用
可读性才是真正的技术#
有人会说:可读性谁不知道?问题是业务紧急,哪有时间写那么”优雅”?
这其实是个误解。真正影响开发效率的,不是写代码的时间,而是读代码和改代码的时间。一段写得很”聪明”的代码,可能十分钟就写完了,但后续维护可能花上几十个小时。而一段”笨拙”但清晰的代码,当时可能多花了五分钟,但后续每次维护都能节省时间。
长期来看,可读性才是真正的效率。
而且,你会发现一个有趣的现象:真正的大牛,写出来的代码往往都很”简单”。不是因为他们不会用高级特性,而是他们知道——代码是给人看的,不是给机器看的。机器只关心能不能跑,人关心的是能不能维护。
Kent Beck 说过一句话我很认同:“任何人都能写出机器能看懂的代码,但只有优秀的程序员才能写出人能看懂的代码。“
怎么在日常工作中提高代码可读性?#
说了一堆道理,给一个实用的建议吧:下次当你写完一段代码,问自己一个问题——“如果三个月后的我完全忘记了这段代码,看完需要多久才能理解?”
如果答案是”需要很久”,那就花五分钟做个优化:
- 变量名要自解释 :不要用 result、temp、data,用 meaningfulName
- 函数名要表达意图 :不是 doProcess,而是 validateAndSaveUserOrder
- 长函数要拆分 :超过 30 行就可以考虑拆了
- 加有意义的注释 :解释为什么,而不是解释是什么
- 复杂逻辑要分层 :把”怎么做”和”做什么”分开
代码是写一次,读一百次的。让自己成为一个”让未来的自己感激的人”,这才是真正的高级。
最后送大家一句话共勉:最好的代码,是让团队里最菜的同事都能看懂的代码。那才是真正的高手境界。