代码应该容易让人理解
在过去的5年中,我们收集了许多“丑陋代码”的例子(其中大部分是我们自己写的),然后分析到底是什么使代码变丑陋,应用什么原则/技巧能把代码变好。最终我们注意到,所有的原则都源于一个主题:
代码应该容易让人理解。
我们相信这是你在写代码时你能用到的最重要的一条指导原则。通过这本书,我们将向你展示如何把这个原则应用到你日常编程的方方面面中。但在开始之前,我们先详细阐述一下该原则,并证明为什么它那么重要。
什么使代码”变好“
很多程序员(包括作者)在做设计决定时是基于直觉。我们都知道如下代码:
for (Node* node = list->head; node != NULL; node = node->next) Print(node->data);
比下面的代码要好:
Node* node = list->head; if (node == NULL) return; while (node->next != NULL) { Print(node->data); node = node->next; } if (node != NULL) Print(node->data);
(即使两段代码做的是一样的事)。
但很多时候, 做决定不是那么容易的。例如,这段代码:
return exponent >= 0 ? mantissa * (1 << exponent) : mantissa / (1 << -exponent);比如下的更好或更坏:
if (exponent >= 0) { return mantissa * (1 << exponent); } else { return mantissa / (1 << -exponent); }
第一个版本的代码更紧凑,而第二个版本的代码没第一个的吓人。
那个标准更重要?一般来说,你是如何决定用那种方式去编程?
可读性的基本原理
通过研究很多这样的代码,我们得到了一个结论,就是代码易读性是一个比其他所有的原则都要重要原则。我们觉得他是如此重要把这个原则命为”可读性基本原理“。
代码写出来应能最小化他人的理解时间。
这句话什么意思?就如字面所述,就是找一个你的同事,测量他看你的代码开始到完全理解的时间,这个“直到完全理解时间”就是这个理论标准所说的你要最小化的时间。
并且,我们对所说的“理解”这个词,要求是非常高的。他人能够
完全理解你的代码,意味着他们能够修改,定位bug,并理解这段代码是如何与你的其他代码交互的。
现在,你可能想,“谁管他人里不理解?我是唯一使用这个代码的人!”即使你是一个个人项目,达到那个目标仍然是值得的。那个“他人”很可能就是6个月的你,那时你对你的代码已经不是那么熟悉了。而你永远不知道——有人会加入到你的项目中,或你那“随时要扔的代码”会被其他项目使用。
越少越好?
通常来说,用越少的代码解决一个问题越好。阅读2000行的代码花的时间比阅读5000行要少。
但是少不总是比较好!很多时候有一行表达式像:
assert((!(bucket = FindBucket(key))) || !bucket.IsOccupied());
理解起来花的时间要比两行代码多:
bucket = FindBucket(key); if (bucket != NULL) assert(!bucket.IsOccupied());
同样,注释能使你理解代码更快,但是它也增加了代码量:
// Fast version of "hash = (65599 * hash) + c" hash = (hash << 6) + (hash << 16) - hash + c;
因此,少写些代码是一个好的目标,但最小化理解时间是个更好的目标。
“最小化理解时间”是否与其他原则冲突?
你可能会想“其他原则呢,如让代码更有效率,或者有好的架构, 或更容易测试等等。难道这些原则不会与让代码更容易理解这个原则冲冲突么?”
我们发现这些其他原则根本不会出现冲突。即使在高度优化的代码里,仍然有许多方法使代码高度可读。并且让你的代码容易被理解经常会引致好的架构和变得容易测试。
困难的部分
当然,时刻想着一个虚拟的局外人是否能容易的理解你的代码需要额外的工作。这要求在你编码的时候打开一部分你之前从未使用的大脑。
但一旦你采用这个目标(像我们一样),我们能肯定你会变成一个更好的程序员,更少的bug,对你的工作更自豪,写的代码所有周围的人都喜欢使用。所以,让我们开啥吧……