如何编写简洁的代码?

3,550 阅读6分钟

引言

学习来源:《Clean Code》 [美] Robert C.Martin。

这是本人的学习笔记,现在大部分写代码的时候已经对这些规则和概念有了一个清晰的认识,希望大家有机会也能看一看《Clean Code》这本书,总结出属于自己需要的规则。

一.有意义的命名

1.名副其实

int d;//消逝的时间,以日计
int elapsedTimeInDays;

2.避免误导

别用accountList来指称一组账号,除非它真的是List类型。提防使用不同之处较小的名称。误导性名称最可怕的例子,是用小写字母“l”和大写字母“O”作为变量名。因为他们看起来实在太像数字“零”和“壹”。如以下代码:
int a=l;
if(O==l)
  a=O1;
else
 l=01;

3.做有意义的区分

废话是另一种没意义的区分。例如你有一个Product类和一个ProductInfo类,这两个名称虽然不同,意思却毫无区别。

4.使用读的出来的名称

像生成时间戳 这个变量应该是 generationTimestamp 而不是 genymdhms . 

5.使用可搜索的名称

尽量避免使用单字母和数字作为常量名称,因为它们通常很难在一大段代码中被准确的搜索出来。作者认为 单字母名称 仅用于短方法中的本地变量。名称长短应与其作用域大小相对应。

6.避免使用编码

把类型和作用域编进名称里面,徒然增加了解码的负担。典型的如:
  1. 成员前缀(没必要使用前缀来标明成员变量,应当把类和函数做的足够小,消除对成员前缀的需要)如下代码:
public class Part{
  String description;
  void setDescription(String description){
    this.description=description;
  }
}

7.避免思维映射

不要让读者在脑中把你的名称翻译为他们熟知的名称。这种问题经常出现在选择是使用问题领域术语还是解决方案术语时。

8.类名

类名应该是名词或名词短语,例如 Customer、WikiPage、Account 和 AddressParser,避免使用 Manager、Processor、Data或者Info这样的类名。

类名不应当是动词。

9.方法名

方法名应当是动词或动词短语,如 postPayment、deletePage 或save。

10.每个概念对应一个词

给每个抽象概念选一个词,并且一以贯之。例如,使用fetch、retrieve和 get 来给在多个类中的同种方法命名。

11.使用解决方案领域名称

记住,只有程序员才会读你的代码。所以,尽管使用那些计算机科学术语、算法名、模式名、数学术语吧。依据问题所涉领域来命名可不算是聪明的做法。

12.使用源自所涉问题领域的名称

如果不能使用解决方案领域名称来命名,就采用所涉问题领域的名称,至少负责维护代码的程序员可以去请教该领域专家。

13.添加有意义的语境

让你的代码读起来是连贯的,是在同一语境的。能明确的知道,这些类,函数是某个结构的一部分。这需要通过良好命名的类,函数和命名空间来形成有意义的语境。

14.不要添加没用的语境

只要短名称足够清楚,就比长名称好,不要一昧的追求长名称,从而造成很多不必要的语境。给人以困扰。

二.函数

1.第一规则:短小

if语句、else语句、while语句等,其中的代码块应该只有一行。函数的缩进层级不应该多于一层或两层。

2.只做一件事

函数应该只做一件事,做好这一件事。

3.每个函数一个抽象层级

自顶向下读代码:向下原则。

4.使用描述性的名称

长而具有描述性的名称,要比短而令人费解的名称好。
长而具有描述性的名称,要比描述性的长注释好。

5.函数参数

参数数量尽可能的少,最好的是零参数函数,其次是一(单参数函数),再次是二(双参数函数),应尽量避免三(三参数函数)。

5.1 标识参数

应当尽量避免标识参数,避免向函数传入布尔值。

5.2 三元函数

写三元函数之前一定要深思熟虑,是否有必须写三个参数的必要性。

5.3 参数对象

如果函数需要两个,三个或三个以上的参数,就说明其中一些参数应该封装为类了。

5.4 动词与关键字

对于一元函数,函数和参数应当形成一种非常良好的动词/名词对形式。
例如:write(name),或者更好的名称:writeField(name)。
例如:assertEqual改成assertExpectedEqualsActual(expected,actual)。

5.5 错误处理

  • 使用异常代替返回错误码
  • 抽离Try / Catch 代码块
  • 函数应该只做一件事,错误处理就是一件事。因此,错误处理的函数不该做其他事。

5.6 别重复自己

不要编写重复性的函数。

5.7 结构化编程

Edsger Dijkstra的结构化编程规则。

三.注释

关于注释的问题,首先我们应该明确的是能用代码阐述的就不要写注释,避免误导。也就是代码可读性非常高,几乎可以不用注释,这需要良好的命名习惯来形成。另外,注释并不能够美化你写的糟糕的代码。与其有时间写注释,不如花时间优化你的代码。如果我们在必须写注释的情况下,需要明确的知道自己想要写的是好注释还是坏注释。

好注释

法律信息(例如版权及著作声明)

提供信息的注释(例如解释某个抽象方法的返回值,当然更好的是在方法名中体现,从而省略注释)

对意图的解释(对某些看起来与常理不符合的代码解释你的意图,如 sleep 函数)

警示(警告执行后会出现某些后果的代码)

TODO 注释(告诉其他人这里还有个未完成的工作,以及将来完成后应该是怎么样的)

坏注释

多余的注释

日志式注释(记录每次的修改日志,目前在源代码管理非常完善的今天,日志式注释应该被废弃了)

注释掉的代码(不要直接注释掉代码!无用则请删除,注释而不是删除会让其他人误以为这段代码仍有用处)

归属与署名(通过源代码管理,署名也是可以被废弃的)

括号后面的注释(不要在括号后面写注释)

信息过多(别在注释中添加无关紧要的信息)


PDF资源

这里是书籍的PDF版本(中英文版本均有),从网上搜集而来。

百度云:链接: https://pan.baidu.com/s/1FRjifuXzEeJcayDUtDmCXA 提取码: h3rs 

不过还是希望大家能尽量支持正版哈,纸质书看起来比较有感觉~。