代码整洁之道-函数

来源:互联网 发布:朱苏力 知乎 编辑:程序博客网 时间:2024/06/05 07:56

代码整洁之道-函数

本文将讨论如何写好函数(来自《代码整洁之道》第3张-函数)

一、函数的编写规则

1.1 短小

**函数的第一规则是要短小,第二规则是还要更短小。**if、else、while语句等,其中的代码块应该只有一行;而每个函数的函数体最好只有2~4行那么长。所以,函数的缩进层级不该多于一层或两层。

(个人理解是,如果函数编写足够好,就算只有2~4行,也能知道这个函数做了什么,函数里面调用另一个函数的代码又会做什么。但这样看起来不会没有整体感吗?)

1.2 只做一件事

函数应该做一件事。做好这件事。只做这一件事。要判断函数是否不止做了一件事,就看是否能再拆出一个函数。

1.3 自顶向下读代码

好的代码拥有自顶向下的阅读顺序。我们想要这样读程序:程序就像是一系列TO起头的段落,每一段都描述当前抽象层级,并引用位于下一抽象层及的后续TO起头段落。

例子:
自顶向下读代码

1.4 switch语句

写出短小的switch语句很难,但我们总无法避开它,下面举一个例子,看看它的问题,和能改进的地方。

代码1

就变量的命名而言,这段代码做得还是很不错的。但它有几个问题,首先它太长了点;其次,它做了不止一件事;第三,它违反了单一权责原则,因为有好几个修改它的理由;第四,它违反了开放闭合原则,因为每增加一个新的类时,就必须修改它。

该问题的解决方案是switch语句埋到抽象工厂底下,不让任何人看到:
代码2

1.5 使用描述性的名称

别害怕长名称。别害怕花时间取名字,命名方式要保持一致。

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

1.6 函数参数

最理想的参数数量是零,其次是一,再其次是二,应尽量避免多参数(三以上)函数。因为参数不容易对付,它们带有太多概念性,每次调用函数时都要理解一遍。而且从测试的角度看,如果参数多于两个,测试覆盖所有可能值得组合简直令人生畏。应该尽量利用一些机制将其转换成一元函数。

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

Circle makrCircle(double x, double y, double radius);Circle makrCircle(Point center, double radius);

1.7 输出参数

另外,要尽量避免使用输出参数,它比输入参数还要难以理解,我们习惯了信息通过参数输入函数,通过返回值从函数中输出,所以,输出参数往往令人苦恼之后才恍然大悟。如果函数要对输入参数进行转换操作,转换结果就该体现为返回值。

面向对象中可以使用this处理输出参数,比如:

appendFooter(s);str.appednFooter();

1.8 标识参数

标识参数丑陋不堪,向函数传入布尔值简直就是骇人听闻的做法。比如这个方法:render(true),对于读者来说简直完全摸不着头脑,卷动屏幕,看到render(Boolean isSuite)才或许有点帮助。这个函数应该一分为二renderForSuite()和renderForSingleTest()

1.9 动词和关键字

对于一元函数,函数和参数应当形成一种非常良好的动词/名词对形式。比如:write(name),更好的名称应该是writeField(name),这样我们就知道name是一个Field。

1.10 无副作用

函数承诺只做一件事,但还是会做其他被隐藏起来的事,有时会对自己类中的变量做出未能预期的改动。比如:

无副作用

这个副作用叫做时序性耦合——即要在特定时刻才允许被调用,否则会话数据就有可能沉默地丢失。解决办法是把函数命名为checkPasswordAndInitializeSession,虽然这违反了“只做一件事”的原则。

1.11 分隔指令与询问

比如:

if(set(“username”, “unclebob”))

这句代码很具有迷惑性,它问的是是否成功设置了,还是username的属性值之前已设置为unclebob了呢?

解决方法是把指令与询问分隔开来,防止混淆的发生:

if(attributeExists(“username”)){    setAttribute(“username”, “unclebob”);}

1.12 try/catch

Try/catch代码块丑陋不堪,它们搞乱了代码结构。最好把try/catch抽离出来,另外形成函数,如:

try/catch

改正:
try/catch

二、小结

1、函数的第一规则是要短小,第二规则是还要更短小。

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

3、好的代码拥有自顶向下的阅读顺序。

4、别害怕长名称;别害怕花时间取名字;命名方式要保持一致。

5、最理想的参数数量是零,其次是一,再其次是二,应尽量避免多参数(三以上)函数。如果有三个或三个以上的参数,应把其中一些参数封装为类。

6、尽量不要使用标识参数、输出参数。如果函数要对输入参数进行转换操作,转换结果就该体现为返回值。在面向对象中使用this处理输出参数。

7、对于一元函数,函数和参数应当形成一种非常良好的动词/名词对形式。

8、函数只做一件事,且无副作用地做一件事。如果有指令、询问语句,应该把它们分隔开来。

三、例子赏析

例子赏析
例子赏析
例子赏析
例子赏析

0 0
原创粉丝点击