3 函数
3.1
3.1.1.短小:函数的第一规则是要短小。第二条规则是还要更短小。
程序中每个函数都只有两行、三行或四行长。每个函数都一目了然。每个函数都只说一件事。而且,每个函数都依序把你带到下一个函数。这就是函数应该达到的短小程度
3.1.2.if 语句、else 语句、while 语句
其中的代码块应该只有一行。该行大抵应该是一个函数调用语句。
3.2 只做一件事
函数应该做一件事。做好这件事。只做这一件事。
要判断函数是否不止做了一件事,还有一个方法,就是看是否能再拆出一个函数,该
函数不仅只是单纯地重新诠释其实现.
只做一件事的函数无法被合理地切分为多个区段。
3.3 每个函数一个抽象层级
要确保函数只做一件事,函数中的语句都要在同一抽象层级上。
里面有 getHtml( )等位于较高抽象层的概念,也有 String pagePathName =
PathParser.render(pagePath)等位于中间抽象层的概念,还有.append("\n")等位于相当低的抽象层的概念。
函数中混杂不同抽象层级,往往让人迷惑。读者可能无法判断某个表达式是基础概念还是细节。
3.3.1 自顶向下读代码:向下规则
3.5 使用描述性的名称
3.6 函数参数
最理想的参数数量是零(零参数函数),其次是一(单参数函数),再次是二(双参数函数),应尽量避免三(三参数函数)。有足够特殊的理由才能用三个以上参数(多参数函数)—所以无论如何也不要这么做。
参数不易对付。它们带有太多概念性。
相较于没有参数,只有一个输入参数算是第二好的做法。
3.6.1 一元函数的普遍形式
3.6.3 二元函数
有两个参数的函数要比一元函数难懂。例如,writeField(name)比 writeField(outputStream, name) 好懂。
3.6.4 三元函数
有三个参数的函数要比二元函数难懂得多。排序、琢磨、忽略的问题都会加倍体现。
3.6.5 参数对象
如果函数看来需要两个、三个或三个以上参数,就说明其中一些参数应该封装为类了。
例如,下面两个声明的差别:
Circle makeC ircle(double x, double y, double radius);
Circle makeC ircle(Point center, double radius);
3.6.7 动词与关键字
给函数取个好名字,能较好地解释函数的意图,以及参数的顺序和意图。对于一元函数,函数和参数应当形成一种非常良好的动词/名词对形式。例如,write(name)就相当令人认同。
3.8 分隔指令与询问
函数要么做什么事,要么回答什么事,但二者不可得兼。函数应该修改某对象的状态,或是返回该对象的有关信息。两样都干常会导致混乱。
3.9 使用异常替代返回错误码
3.9.1 抽离 Try/Catch 代码块
Try/catch 代码块丑陋不堪。它们搞乱了代码结构,把错误处理与正常流程混为一谈。最好把 try 和 catch 代码块的主体部分抽离出来,另外形成函数。
3.10 别重复自己
4 注释
注释的恰当用法是弥补我们在用代码无法表达意图是遭遇的失败。注意,我用来“失败“一次。我是说真的。我们总无法找到不用注释就能表达自我的方法,所以总要有注释,这并不值得庆贺。
程序员应当负责将注释保持在可维护、有关联、精确的高度。我同意这一说法。但我更主张把力气用着写清楚代码上,直接保证无须编写注释。不准确的注释要比没注释坏的多。它们满口胡言。它们预期的东西永不能实现。它们设定了无需也不应再遵循的旧规则。
1.注释不能美化糟糕的代码:
写注释的常见动机之一是糟糕的代码的存在。我们编写一个模块,发现它令人困扰、乱七八糟,我们知道,它烂透了。我们告诉自己:”喔,最好写点注释“ 不!最好是吧代码弄干净!
带有少量注释的整洁而有表达力的代码,要比带有大量注释的零散而复杂的代码像样得多。与其花时间编写解释你搞出的糟糕的代码的注释,不如花时间清洁那段糟糕的代码。
2.警示:
用于警告其他程序员会出现某种后果的注释也是有用的。例如,下面的注释解释了为什么要关闭某个特定的测试用例:
// Don't run unless you have some time to kill
public void testWithReallyBigFile()
{
writeLinesToFile(100000000);
response.setBody(testFile);
String responseString = output.toString();
assertSubString("Content-Length: 10000000",responseString);
assertTrue(bytesSent>100000000);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
3.废话注释:
有时,你会看到纯然是废话的注释。它们对于显然之事喋喋不休,毫无新意。例如:
/**
* Default constructor.
* /
protected AnnualDateRule() {
}
- 1
- 2
- 3
- 4
- 5
又或者:
/** The day of the month. */
private int dayOfMonth;
- 1
- 2
这类注释废话连篇,我们都学会了视而不见,读代码时,眼光不会停留在它们上面。最终当代码修改之后,这类注释就变成了谎言一堆。
用整理代码的决心替代创造废话的冲动吧。你会发现自己成为更优秀、更快乐的程序员。
4.括号后面的注释:
有时,程序员会在括号后面放置特殊的注释,代码如下:
尽管这对于含有深度嵌套结构的长函数可能有意义,但只会给我们更愿意编写的短小、封装的函数带来混乱,如果你发现自己想标记右括号,其实更应该做的是缩短函数。