编写可读代码的艺术

当我们看到写得很漂亮的代码时,会很受启发。好代码会告很明确告诉你它在做什么。使用它会很有趣,并且会鼓励你把自己的代码写得更好。该书旨在帮助你把代码写得更好。该书的关键思想是代码应该写得容易理解。确切地说,使别人用最短的时间理解你的代码。每一章都会深入编程的某个方面来讨论如何使代码更容易理解。 该书分为四个部分:

  • 表面层次上的改进:命名、注释以及审美——可以用于代码库每一行的小提示。
  • 简化循环和逻辑:在程序中定义循环、逻辑和变量,从而使得代码更容易理解。
  • 重新组织你的代码:在更高层次上组织大的代码块以及在功能层次上解决问题的方法。
  • 精选话题:把“易于理解”的思想应用于测试以及大数据结构代码的例子。

前言

第 1 章 代码应当易于理解

代码的写法应当使别人理解它的时间最小化。

第一部分 表面层次上的改进

第 2 章 把信息装到名字里

本章唯一的主题是:把信息塞入名学中。这句话的含意是,读者仅通过读到名学就可以获得大量信息。下面是讨论过的几个小提示:

  • 使用专业的单词一一例如,不用Get,而用Fetch或者Download可能会更好,这由上
    下文决定。
  • 避免空泛的名字,像tmpretval,除非使用它们有特殊的理由。
  • 使用具体的名字来更细致地描述事物-—ServerCanstart()这个名字就比CanListenOnPort 更不清楚。
  • 给变名带上重要的细节——例如,在值为毫秒的变量后面加上ms,或者在还需要转义的,未处理的变量前面加上raw_
  • 为作用域大的名学采用更长的名字——不要用让人费解的一个或两个学母的名字来命名在几屏之间都可见的变量。对于只存在于几行之间的变量用短一点的名字更好。
  • 有目的地使用大小写、下划线等一一例如,你可以在类成员和局部变量后面加上_来区分它们。

How to Write Meaningful Variable Names? | Writing Clean Code

第 3 章 不会误解的名字

不会误解的名字是最好的名字一一阅读你代码的人应该理解你的本意,并且不会有其他的理解。遗憾的是,很多英语单词在用来编程时是多义性的,例如filterlengthlimit

在你决定使用一个名字以前,要吹毛求症一点,来想象一下你的名字会被误解成什么。最好的名字是不会误解的。

当要定义一个值的上限或下限时,maxmin是很好的前缀。对于包含的范围,firstlast是好的选择。对于包含/排除范围,beginend是最好的选择,因为它们最常用。

当为布尔值命名时,使用ishas这样的词来明确表示它是个布尔值,避免使用反义的词(例如disable_ssl)。

要小心用户对特定词的期望。例如,用户会期望get()或者size()是轻量的方法。

第 4 章 审美

大家都愿意读有美感的代码。通过把代码用一致的、有意义的方式“格式化”,可以把代码变得更容易读,并且可以读得更快。

下面是讨论过的一些具体技巧:

  • 如果多个代码块做相似的事情,尝试让它们有同样的剪影。
  • 把代码按“列”对齐可以让代码更容易浏览。
  • 如果在一段代码中提到 A、B 和 C,那么不要在另一段中说 B、C 和 A。选择一个有意义的顺序,并始终用这样的顺序。
  • 用空行来把大块代码分成逻辑上的“段落”。

第 5 章 该写什么样的注释

注释的目的是帮助读者了解作者在写代码时已经知道的那些事情。本章介绍了如何发现所有的并不那么明显的信息块并且把它们写下来。

什么地方不需要注释:

  • 能从代码本身中迅速地推断的事实。
  • 用来粉饰烂代码(例如蹩脚的函数名)的“拐杖式注释”一一应该把代码改好。

你应该记录下来的想法包括:

  • 对于为什么代码写成这样而不是那样的内在理由(“指导性批注”)。
  • 代码中的缺陷,使用像 TODO:或者 XXX:这样的标记。
  • 常量背后的故事,为什么是这个值。

站在读者的立场上思考:

  • 预料到代码中哪些部分会让读者说:“啊?”并且给它们加上注释。
  • 为普通读者意料之外的行为加上注释。
  • 在文件/类的级别上使用“全局观”注释来解释所有的部分是如何一起工作的。
  • 用注释来总结代码块,使读者不致迷失在细节中。

第 6 章 写出言简意赅的注释

本章是关于如何把更多的信息装入更小的空间里。下面是一些具体的提示:

  • 当像“it”和“this”这样的代词可能指代多个事物时,避免使用它们。
  • 尽量精确地描述函数的行为。
  • 在注释中用精心挑选的输入/输出例子进行说明。
  • 声明代码的高层次意图,而非明显的细节。
  • 用嵌入的注释(如Function(/*arg=*/..))来解释难以理解的函数参数。
  • 用含义丰富的词来使注释简洁。

第二部分 简化循环和逻辑

第 7 章 把控制流变得易读

有几种方法可以让代码的控制流更易读。

在写一个比较时(while(bytes_expected>bytes_received)),把改变的值写在左边并且把更稳定的值写在右边更好一些(while(bytes_received<bytes_expected))。

你也可以重新排列if/else语句中的语句块。通常来讲,先处理正确的/简单的/有趣的情况。有时这些准则会冲突,但是当不冲突时,这是要遵循的经验法则。

某些编程结构,像三目运算符(:?)、do/while循环,以及goto经常会导致代码的可读
性变差。最好不要使用它们,因为总是有更整洁的代替方式。

嵌套的代码块需要更加集中精力去理解。每层新的嵌套都需要读者把更多的上下文“压入栈”。应该把它们改写成更加“线性”的代码来避免深嵌套。

通常来讲提早返回可以减少嵌套并让代码整洁。“保护语句”(在函数顶部处理简单的情况时)尤其有用。

第 8 章 拆分超长的表达式

很难思考巨大的表达式。本章给出了几种拆分表达式的方法,以便读者可以一段一段地消化。

一个简单的技术是引人“解释变量”来代表较长的子表达式。这种方式有三个好处:

  • 它把巨大的表达式拆成小段。
  • 它通过用简单的名字描述子表达式来让代码文档化。
  • 它帮助读者识别代码中的主要概念。

另一个技术是用德摩根定理来操作逻辑表达式一一这个技术有时可以把布尔表达式用更整洁的方式重写(例如if(!(a&&1b)变成if(!a//b))。

本章给出了一个,把一个复杂的逻辑条件拆分成小的语句的例子,就像"if(a<b)..."。实际上,在本章所有改进过的示例代码中,所有的 i 语句内都没有超过两个值。这是理想情况。可能不是总能做到这样一一有时需要把问题“反向”或者考虑目标的对立面。

最后,尽管本章是关于拆分独立的表达式的,同样,这些技术也常应用于大的代码块。所以,你可以在任何见到复杂逻辑的地方大胆地去拆分它们。

第 9 章 变量与可读性

本章是关于程序中的变量是如何快速累积而变得难以跟踪的。你可以通过减少变量的数量和让它们尽量“轻量级”来让代码更有可读性。具体有:

  • 减少变量,即那些妨碍的变量。我们给出了儿个例子来演示如何通过立刻处理结果来消除“中间结果”变量。
  • 减小每个变重的作用域,越小越好。把变量移到一个有最少代码可以看到它的地方。眼不见,心不烦。
  • 只写一次的变量更好。那些只设置一次值的变量(或者 const、final、常量)使得代码更容易理解

第三部分 重新组织代码

第 10 章 抽取不相关的子问题

对本章一个简单的总结就是“把一般代码和项目专有的代码分开”。其结果是,大部分代码都是一般代码。通过建立一大组库和辅铺助函数来解决一般可题,剩下的只是让你的程序与众不同的核心部分。

这个技巧有帮助的原因是它便程序员关注小而定文食好的向题,这些同题已经同项自的其他部分脱离。其结果是,对于这些子间题的解决方案倾同于更加完整和正确。你也可以在以后重用它们。

第 11 章 一次只做一件事

本章给出了一个组织代码的简单技巧:一次只做一件事情。

如果你有很难读的代码,尝试把它所做的所有任务列出来。其中一些任务可以很容易地变成单独的函数(或类)。其他的可以简单地成为一个函数中的逻辑“段落”。具体如何拆分这些任务没有它们已经分开这个事实那样重要。难的是要准确地描述你的程序所
做的所有这些小事情。

第 12 章 把想法变成代码

本章讨论了一些简单的技巧,用自然语言描述程序然后用这个描述来帮助你写出更自然的代码。这个技巧出人意料地简单,但很强大。

第 13 章 少写代码

本章是关于写越少代码越好的。每行新的代码都需要测试、写文档和维护。

第四部分 精选话题

第 14 章 测试与可读性

在测试代码中,可读性仍然很重要。如果测试的可读性很好,其结果是它们也会变得很容易写,因此大家会写更多的测试

请作者喝杯咖啡!
AndyFree96 支付宝支付宝
AndyFree96 微信微信
0%