主要解决的问题:
怎样让代码易于阅读和理解?怎样才能让函数表达其意图?该给函数赋予哪些属性,好让读者一看就明白函数是属于怎样的程序。
函数的第一规则是要短小。第二规则是还要更短小。
每个函数都只说一件事。
代码块和缩进
If语句、else语句、while语句等,其中的代码块应该只有一行。该行大抵应该是一个函数调用语句。函数的缩进层级不该多于一层或两层。
函数应该做一件事。做好这件事。只做一件事。
编写函数毕竟是为了把大一些的概念拆分为另一抽象层上的一系列的步骤。
要判断函数是否不止做了一件事,还有一个方法,就是看是否能再拆出一个函数,该函数不仅只是单纯地重新诠释其实现。
只做一件事的函数无法被合理的切分为多个区段。
要确保函数只做一件事,函数中的语句都要在同一抽象层级上。
向下规则:每个函数后面都跟着位于下一抽象层级的函数。这样一来,在查看函数列表时,就能循抽象层级向下阅读了。
确保每个switch都埋藏在较低的抽象层级,而且永远不会重复。通过多态实现这一点。
如果每个例程都让你感到深合己意,那就是整洁代码。
函数越短小,功能越集中,就越便于取个好名字。
别害怕长名称。长而具有描述性的名称,要比短而令人费解的名称好。
选择描述性的名称能理清你关于模块的设计思路,并帮你改进。
命名方式要保持一致。使用与模块名一脉相承的短语、名词和动词给函数命名。
最理想的参数数量是零,其次是一、再次是二、尽量避免三。有足够特殊的理由才能用三个以上参数。
输出参数比输入参数还要难以理解。读函数时,我们惯于认为信息通过参数输入函数,通过返回值从函数中输出。我们不太期望信息通过参数输出。(感觉武断,不过确实输出参数确实不好阅读。)
1、一元函数的普遍形式:问关于参数的问题,做判断。
操作该参数,将其转换为其他什么东西,再输出。
2、标识参数
标识参数丑陋不堪。向函数传入布尔值简直就是骇人听闻的做法。这样做,方法签名立即变得复杂起来,大声宣布函数不止做一件事。
3、二元函数
有两个参数的函数要比一元函数难懂。
4、三元函数
有三个参数的函数要比二元函数难懂得多。排序、琢磨、忽略的问题都会加倍体现。
5、参数对象
如果函数看来需要两个、三个或三个以上参数,就说明其中一些参数应该封装为类了。
6、参数列表。
感觉没什么用。
7、动词和关键字
给函数取个好名字,能较好地解释函数的意图,以及参数的顺序和意图。
函数承诺只做一件事,但还是会做其他被藏起来的事。有时,他会对自己类中的变量做出未能预期的改动,有时,它会把变量搞成向函数传递的参数或是系统全局变量。无论哪种情况,都是具有破坏性的,会导致古怪的时序性耦合及顺序依赖。
避免使用输出参数。如果函数必须要修改某种状态,就修改所属对象的状态吧。
函数要么做什么事,要么回答什么事,但二者不可得兼。函数应该修改某对象的状态,或是返回该对象的有关信息。两样都干常会导致混乱。
使用异常替代返回错误码,错误处理代码就能从主路径代码中分离出来,得到简化。
1、抽离try/catch代码块。
把try和catch代码块的主体部分抽离出来,另外形成函数。(封装的太多了吧。)
2、错误处理就是一件事。
函数应该只做一件事,错误处理就是一件事。因此,处理错误的函数不该做其他事。这就意味着如果关键字try在某个函数中存在,它就该是这个函数的第一个单词,而且在catch/finally代码块后面不该有其他内容。
3、取消依赖磁铁。
如果定义错误码,几乎所有的类都得导入和使用它,当Error枚举修改时,所有的这些类都需要重新编译和部署。这对Error类造成了负面压力。使用异常替代错误码,新异常就可以从异常类派生出来,无需重新编译和重新部署。
函数的出现就是为了消除重复的,如果发现有两处使用一个算法,封装成为一个函数吧。
初始实现功能,然后打磨它,分解函数、修改名称、消除重复。