函数
-
短小:20行最佳
-
只做一件事:函数缩短为只在一个抽象层级。看是否能再拆出一个函数。
-
每个函数一个抽象层级:要确保函数只做一件事,函数中的语句都要在同一个抽象层级上。函数中混杂不同抽象层级,往往让人迷惑,读者可能无法判断某个表达式是基础概念还是细节,一旦细节与基础概念混杂,更多的细节就会在函数中纠结起来。
自顶向下读代码:向下规则。让代码读起来像是一系列自顶向下的TO起头段落是保持抽象层级协调一致的有效技巧。
-
switch语句:避免违反单一权责原则与开放闭合原则,尽量少修改,可用解决方案是将switch语句埋到抽象工厂底下,不让任何人看到。
-
使用描述性的名称:函数越短小、功能越集中,就越便于取个好名字(简洁明了)。长而具有描述性的名称,要比短而令人费解的名称好。命名方式要保持一致,使用与模块名一脉相承的短语、名词和动词给函数命名。
-
函数参数:最理想的参数数量是零,其次是一,再次是而,应尽量避免三,有足够特殊的理由才能用三个以上参数。
标识参数丑陋不堪,向函数传入布尔值简直就是骇人听闻的做法。可将传入标识的函数一份为二。
如果函数看来需要两个、三个或者以上参数,就说明其中一些参数应该封装为类了。
对于一元函数,函数和参数应当形成一种非常良好的动词/名词对形式。例如,write(name),可改为writeField,告诉我们name是一个field。使用这种形式,我们把参数的名称编码成函数,大大减轻了记忆参数顺序的负担。如assertEqual 改为assertExpectedEqualsActual(expected,actual)。
-
无副作用:函数承若只做一件事,但还是会做其他被藏起来的事:对所属类中的变量(有状态变量)做出未能预期的改动,把变量搞成函数传递的参数或是系统全局变量,会导致古怪的时序性耦合及顺序依赖。此时函数需要重命名加上副作用事件名,防止出现令人迷惑的情况。
-
输出参数:参数多数会被自然而然地看作是函数的输入。例如appdFooter(s);会让人产生迷惑,s是输入参数还是输出参数?花时间看函数签名public void appendFooter(StringBuffer report) ;在面向对象语言中最好是这样调用appendFooter:report.appendFooter();普遍而言,应避免使用输出参数。如果函数必须要修改某种状态,就修改所属对象的状态。
-
抽离Try/catch代码块:最好把try和catch代码块的主体部分抽离出来,另外形成函数。
-
别重复自己:重复会导致代码因此而臃肿,算法需要修改时麻烦且易出错。