最近在学习如何重构代码,在此记录一些重构代码的技术和方法。
代码应当易于理解,代码的写法应当使别人理解它所需的时间最小化。
表面层次的改进
选择更好的名字,写好的注释,整洁的代码格式
把信息装进名字里
- 选择专业的词,可以使用同义词词典。
单词 | 更多选择 |
---|---|
send | deliver, dispatch, announce, distribute, route |
find | search, extract, locate, recover |
start | launch, create, begin, open |
make | create, set up, build, generate, compose, add, new |
- 避免使用tmp,retval这样泛泛的名字。
除非有好的理由,除了用在变量值交换的时候,其他时候最好用变量的具体含义起名字。在多层嵌套的for循环中,使用前缀比直接使用i, j, k能有效的防止出错。例如:
1 | for(int i=0; i < clubs.size(); ++i) { |
用具体的名字代替抽象的名字
例如:—run_locally,目的是使用本地的数据库,应该改为—use_local_database为名字附带更多信息
有关变量的重要信息可以加入变量名中。例如string id存储的是16进制的ID,那么可以改名为hex_id。带单位的值
如果变量是一个度量的话,最好把名字带上单位。例如变量尾部追加ms代表毫秒。变量的长度
作用域小的标识符可以使用短的名字,作用域大的标识符名字要包含更多的信息。首字母缩略词和缩写
如果缩写不能让新成员看懂,那么就不要用缩写。常见的有string -> str。丢掉没有用的单词
例如ConverToString可以改为ToString。
使用不会误解的名字
有些名字会被理解成其他的含义,例如:BIG_LIMIT=10,可以理解成<10,也可以理解成<=10。容易带来歧义。
使用min,max来表示包含的极限。在要限制的东西前面加上max或者min。
使用first,last来表示包含的范围。
使用begin,end来表示包含/排除的范围。
对于bool值,前面加上is,has,can,should这样的词可以把bool值变得更加明确。不要使用反义名字,名字表示肯定意思。例如:不要使用bool disable_ssl=false,使用bool use_ssl=false。
使用与含义相匹配的名字。例如:对于get函数,期望的复杂度是O(1),如果复杂的是O(n)则会影响使用。
审美
三条基本原则:
- 使用一致的布局,让读者很快就习惯这种风格。
- 让相似的代码看上去相似。
- 把相关的代码行分组,形成代码块。
- 重新安排换行来保持一致和紧凑
1 | public class PerformanceTest { |
上面的代码把注释复制了三遍,占用了过多的纵向空间。通过下面的写法可以写的更加紧凑。
1 | public class PerformanceTest { |
把声明按块组织起来,例如:构造函数,析构函数放在一起,request,post方法放在一起。
把代码分成段落,用空行按逻辑分隔,并写法一致。
注释
- 好的代码自带解释性,起好的函数名能够自己解释清楚。
- 记录思想,例如:注释教会读者一些东西,防止做无谓的优化。解释代码为什么写的不整洁。
- 加入TODO,FIXME等标签来记录代码的瑕疵。
- 给常量加注释,解释常量可以告诉读者为什么这么用。例如:0.72是经过尝试的最好的参数。
- 站在读者的角度,把读者想要提问的地方加上注释。
什么地方不需要注释:能够代码本身推断的事实;用来粉饰烂代码的拐杖。
应该记录的想法包括:对于代码为什么写成这样而不是那样的理由;代码中的缺陷;常量背后的故事,为什么是这个值。
站在读者的立场上思考:预料到读者的问题;为意料之外的代码加上注释;在文件/类级别上使用“全局观”注释来解释所有部分是如何一起工作的;用注释来总结代码块,是的这不要迷失在细节上。