代码整洁之道笔记(一)

文章目录

    • 一、有意义的命名
      • 1. 名副其实
      • 2. 避免误导
      • 3. 做有意义的区分
      • 4. 使用读的出来的名称
      • 5. 使用可搜索的名称
      • 6. 避免使用编码
      • 7. 类名
      • 8. 方法名
      • 9. 每个概念应该对应一个单词
      • 10. 不用双关语
      • 11. 使用解决方案领域名称,实在不行使用所涉及领域的名称
      • 12. 添加有意义的语境
    • 二、函数
      • 1. 短小
      • 2. 只做一件事
      • 3. 每个函数一个抽象层级
      • 4. switch语句
      • 5. 使用描述性的名称
      • 6. 函数参数
      • 7. 无副作用
      • 8. 指令和询问分离
      • 9. 使用异常替代返回错误码
      • 10. 别重复自己
      • 11. 怎么写出这样的代码?
    • 三、注释
      • 1. 注释不能美化糟糕的代码
      • 2. 用代码来阐述
      • 3. 好注释
      • 4. 坏注释

一、有意义的命名

1. 名副其实

名字能让人理解变量是用来做什么的,比如 daysSinceCreation比 d 用来表
示消逝的时间更好。

2. 避免误导

不用具有特殊含义的词语,比如list,除非它真的是个list
不用 l o

3. 做有意义的区分

不加没有作用的区分或者前缀后缀,比如money和moneyAmount没有区
别。

4. 使用读的出来的名称

不要瞎造词

5. 使用可搜索的名称

名称可以长,但要方便搜索,不要用e 等很短的,单字母名称 如 i只能用于
方法内变量,名称的长短应与其作用域大小相对应。

6. 避免使用编码

不需要加Hn phoneString等

7. 类名

类名和对象名应该是名词或名词短语,如Customer  WikiPage Account。
不应当是动词

8. 方法名

方法名应当是动词或动词短语,如postPayment save等,访问器和修改器
和断言应该加get set is
重载构造器时,应使用描述了参数的静态工厂方法名,如
Complex fulcurmPoint = Complex.FromRealNumber(23.0) 
好于
Complex fulcrumPoint = new Complex(23.0)

9. 每个概念应该对应一个单词

比如Controller Manager driver 同种类型的操作用一个专用术语就可以

10. 不用双关语

比如应该用append的地方用到了add

11. 使用解决方案领域名称,实在不行使用所涉及领域的名称

可以使用专业词语 比如JobQueue来命名,实在不行也可以用涉及到的问
题来命名。

12. 添加有意义的语境

比如firstName lastName street 尽量让语境内的变量在一个语境下面,并
能让别人知道这是在干什么,也能顺藤摸瓜猜出其他变量的含义

二、函数

1. 短小

函数不要太长,太长的代码块不要放进去,if while其中的代码块应该只有
一行,比如是一个函数调用语句。不要有太深的嵌套结构。

2. 只做一件事

只做一件事,做多件事的话可以拆分成多个函数,几十行最佳。做多件事
可以用上一个抽象层级包含起来。

3. 每个函数一个抽象层级

应该有一个自顶向下的代码阅读规则,细节和调用方不要放在一起,自顶
向下应该是一个树形结构,叶子节点应该在同一层上,上面都是对它的调
用。
其实这点很难做到,比如上面调用了一个函数,下面进行一个一行的操
作,不可能为这一行单独拆分成一个函数,所以我认为拆分原则还是要根
据代码的作用,比如这段代码要做一件事情,即使再短也最好拆分,如果
只是一个格式转换,那就没必要单独拆分。总之是为了代码的可读性。

4. switch语句

可以用来创建多态对象

5. 使用描述性的名称

为每个只做一件事的小函数取个好名字,函数越小,功能越集中。就越容
易起名字。不要害怕长名称,长而具有描述性的名称,比长注释要好。

6. 函数参数

• 最好的函数是无参
• 参数和函数名位于不同的抽象层级,给阅读代码带来困难,需要在阅读代
码时候去了解不重要的细节。
• 不要向函数内传标志参数,比如true false ,因为这会代表函数不止做了
一件事。而且要在上层和下层判断两次逻辑,为什么不统一判断一次呢
Eg:调用处:if() do(true) else do(false)
函数do:if(true) {}  else {}
这样逻辑就重复了,修改时也要一起修改。
• 二元参数如果是比较自然的,符合规律的,比如坐标(x,y),是可以接受
的,一定要按照顺序来。
• 参数对象,如果需要一堆参数,那就说明有些参数可以封装成类了。
Eg:makeCircle(double x, double y, double radius);
可以改成 makeCircle(Point center, double radius)

7. 无副作用

上面说到了函数只做一件事,并且在函数名中最好体现出函数要做什么
事,不要偷偷做了某件事,但是调用者不知道,这就是副作用。
最好就不要违反函数只做一件事的原则。

8. 指令和询问分离

不要一个函数既做某些事情,又要返回不相干的结果。
操作和查询应该是分开的。可以是先查询,在指令。

9. 使用异常替代返回错误码

• 如果函数会返回错误码的话,可能会导致深层嵌套结构,要求调用方必须
马上处理错误。
所以应该用异常来替代返回错误码,这样错误处理代码就能分离出来
• 抽离try/catch
Try/catch代码块内的内容会弄乱代码结构,因为catch里的内容其实不属于
主体代码,将错误处理和正常流程混为一谈,所以最好将其中的内容抽离
出来,
• 错误处理就是一件事
函数应该只做一件事,错误处理就是一件事,所以处理错误的函数不应该
在finally后面还有其他的东西
• Error.java错误类 导致依赖  不应该存在
错误码的存在,意味着某处有个类或者枚举,定义了所有的错误码
这意味着其他类都要引入这个错误类,并且枚举修改时,其他类都要重新
编译

而使用异常替代错误码,新的异常就可以从异常类中派生出来,无需重新编译,而且解除了依赖

10. 别重复自己

有的算法或代码块会在很多函数内出现,可能会比较小,也不容易发现。
这样代码会臃肿,而且算法改变时也需要修改四次,可能会导致忽略或忘
掉。如果写代码时发现需要copy一段代码,那么首先考虑能不能抽离为函
数。
消灭重复。

11. 怎么写出这样的代码?

首先要认识到,不可能在没写时就已经设计好代码的结构,所以开始就随
便写吧,先实现功能,不要在开始就被规则束缚,然后为每个函数配好单
元测试,这时就开始打磨代码吧,保证测试通过。

三、注释

1. 注释不能美化糟糕的代码

糟糕的代码需要写注释才能弄清楚,但是最好是把代码弄干净。带有少量
注释的整洁有表达力的代码比带有大量注释的零碎复杂的代码更有用。

2. 用代码来阐述

有时用代码就能解释意图,只需要创建一个描述与注释同一事物的注释即
可。
比如把一段判断封装为函数
// check if the employee is eligible for full benefite
If ((employee.flags & HOURLY_FLAY) && (employee.age > 65))

改为
 if(employee.isEligibleForFullBenefits)

3. 好注释

有哪些注释是必要有用的呢?
	a. 法律信息,这类一般放在头部
	b. 提供信息的注释,这种一般可以用更好的方法名代替
	c. 对意图的解释,比如有两种解决办法,使用了某一种的原因
	d. 阐释,比如有一段判断很复杂,但是目的很简单,但是最好是让返回
	值本身就足够清楚。但有时调用了外部库,自己不能修改,那就可以帮
	它加阐释。
	比如: a.compareTo(a) == 0 ; // a == a
	e. 警示,提示某段代码有何风险。
	f. TODO注释,但是这类要留出时间定期查看和删除。
	g. 放大,有些地方可能看起来不合理,为了避免被改掉,加一段代码提
	示它的重要性。
	h. 公共API中的javadoc

4. 坏注释

	a. 喃喃自语
	b. 多余的注释,简单的地方就不需要加注释。
	c. 误导性数值:不精确,错的。
	d. 循轨式注释
	e. 日志式注释,因为有了源代码控制系统,所以这类不需要加。
	f. 废话注释,也是很简单的函数就不需要加注释。
	g. 错误的
	h. 位置标记  比如 ///////////////////////////a///////
	i. 括号后边的注释,比如while  else
	j. 归属与署名,也因为有源代码控制系统,所以不需要加。
	k. 注释掉的代码,别人也不敢删,要删就删掉,源代码控制系统可以恢
	复。
	l. html注释,没有用。
	m. 信息过多

道理都明白,只是坚持下去很难,需要写代码的时候一直绷着弦,注意自己的代码规范。

你可能感兴趣的:(规范)