如何写好函数?
短小
函数到底要多长
每个程序每个函数只有两行、三行或者四行。每个函数都一目了然。每个函数都只说明一件事。而且,每隔函数都依序把你带到下一个函数。这就是函数应该达到的短小程度。
代码块和缩进
if语句、else语句、while语句等,其中的代码块应该只有一行。该行应该是一个函数调用。这样不能保持函数短小,而且,因为块内调用的函数拥有较具有说明性的名称,从而增加了文档上的价值。
这也意味着函数不应该大到足以容纳嵌套结构。所以,函数的缩进层级不应该多于一层或两层。当然这也的函数易于阅读和理解。
只做一件事
函数应该做一件事。做好这件事。只做这件事。
如果函数只是做了该函数名下统一抽象层上的步骤,则函数还是只做了一件事。所以判断函数是否不止做了一件事,还有一个方法,==就是看是否能再拆除一个函数,该函数不仅只是单纯地重新诠释其实现==。
只做一件事的函数无法合理的切分为多个区段。
每个函数一个抽象层级
==要确保函数只做一件事,函数中的语句都要在同一抽象层级上。==
函数中混杂不同的抽象层级,往往让人迷惑。读者可能无法判断某个表达式是基础概念还是细节。
自顶向下读代码: 向下原则
每个函数后面都跟着位于下一抽象层级的函数,这样一来,在查看函数列表时,就能根据抽象层级向下阅读,这就叫向下规则。
switch 语句
switch的几个问题。太长,当类型复杂起来时,会更长。其次,不止做了一件事。第三,违反了单一权责原则,因为有好几个修改它的理由。第四,违反了开放闭合原则,因为每次添加新类型时,就必须修改之。
解决方法,对于switch语句,如果只出现一次,用于创建多态对象,而且隐藏在某个继承关系中,在系统其它部分看不到。
使用描述性的名称
testableHtml改为SetupTeardownIncluderender; isTestable或includeSetupAndTeardownPages,
长的函数名具有描述性,要比描述性的长注释好。可以使用眸中约定,让函数名称中的多个单词更容易阅读,然后使用这些单词给函数取个能说清其功能的名称。
模块名用名词,而函数名用动词描述。
函数参数
最理想的参数数量是零,其次是一个,再次是两个。除非有足够的理由才能用三个以上参数。
一元函数的普遍形式
一元函数即单个参数的函数,大体上分为两种:
- 操作该参数,将其输出
- 事件,有输入参数而无输出参数,程序将函数看作是一个事件,使用参数修改系统状态
标识参数
将布尔值作为参数用于标识是不值得推荐的做法,如果真要这么做, 应当把函数拆分成两个不带标识参数的函数。
二元函数
拥有两个参数比拥有一个参数的函数更复杂难懂,可以利用一些机制转换成一元函数。
三元函数
三个参数的函数,排序、琢磨、忽略的问题都会成倍体现。
无副作用
函数承诺只做一件事,但有时,会对自己类中的变量做出未能预期的改动,或是对全局变量造成了影响。
这种函数不能以简单的命名让人误解,并且也违法了一个函数只做一件事的规则。
输出参数
应该避免使用输出参数,如果函数必须修改某种状态,就修改所属对象的状态吧
分隔指令与询问
函数要么做什么事,要么回答什么事,但两者不可兼得。函数应该修改某对象状态或是返回该对象的有关信息。两样都干会导致混乱。
把指令和询问拆分成两个函数
如何在实践中写好函数
一开始都冗长而复杂,有太多的缩进和嵌套循环。有过长的参数列表,名称随意取的,也会有重复代码。
然后打磨这些代码,分解函数、修改名称、消除重复。缩短和安置方法,有时候还拆散类。同时保持测试通过。
最后,遵循本章的规则,组装好这些函数。
小结
==大师级程序员把系统当做故事来讲,而不是当做程序来写==。
SetupTeardownIncluder程序