测试私有方法 重构_重构与规范

511c91bf04ae02d9986cb9e67f0d1706.png

1.代码整洁

  1. 1.1. 有意义的命名
  2. 1.2. 函数
  3. 1.3. 注释
  4. 1.4. 数据,对象的反对称性
  5. 1.5. 错误处理
  6. 1.6. 类
  7. 1.7. 好的代码示范
  8. 2.重构
  9. 2.0.1. 重构的过程
  10. 2.0.2. 重构的原则
  11. 2.0.3. 什么情况下重构
  12. 2.0.4. 构筑测试体系
  13. 2.0.5. 重构手法目录

代码整洁规范
减少重复代码
提高表达力
提早构建简单抽象

代码整洁

有意义的命名

名副其实

  • 如果你需要注释来解释一个变量,那就说明它不是名副其实
  • 一旦发现有更好的命名,就要换掉旧的,要记住换花的时间是值得的

避免误导

  • 尽量少使用类型名,除非它真的是这个类型
  • 不要使用过于相似的名字

命名规范

  • 类名和对象是名词,方法是动词,注意get/set/is的前缀
  • 即每个抽象概念选一个词,DeviceManager和Protocal-Controller是一样的
  • 要保持前后术语规范。
  • 用常量代替原始数字(魔术数)
  • 不要在代码中重复写+1的边界条件,而是用变量进行封装
  • 函数的长短与其作用范围息息相关,所以for循环可以用i,j因为它们作用域很小

函数

函数要做到自己理解,而不是通过测试用例,这需要改进和重构简洁。

尽量短小

  • if/for/while中应该只有一行
  • 函数只做一件事,抽象层上应该是同一级别!
  • 函数的顺序,是自顶向下的规则,抽象到具体的顺序

参数

  • 参数最多不应该超过3个,如果参数多于3个的时候,就可以思考参数是否能构成一个类,参数过多的时候可以组合成字典传递
  • 参数不要传布尔值,应该将true/false分成两个函数,然后在布尔值的上一个抽象层直接做判断,而不是将其作为布尔值传递。(整数值,枚举元素等函数选择行为同理)
  • 参数不要传字面值,应传变量
  • 最好保证对象的拷贝性,统一拷贝而不是在原值上修改

返回值

  • 可以定义这样的规范,每个函数的返回值都叫result

处理异常

  • try/catch的每个功能都应该拆出成一个函数
  • 如果你用枚举类型来表示异常,那将意味着你会很不情愿修改它,使用异常代替错误码,新异常就可以从异常类中派生出来.

重复

  • 永远无法容忍重复代码,这意味着抽象的遗漏
  • 如果你发现死代码(永不执行的代码块),果断删除
  • 多个switch/ifelse,考虑多态

判断

  • if的条件如果过多,就要封一个函数,因为没有上下文是看不懂if的
  • 避免否定条件,尽量保持一致,不要带!,可以直接把!函数封成函数

静态

  • 如果一个函数不依赖其类的属性,都是依赖于参数,这时候该函数就应该声明为静态
  • 静态导入(就是单纯导入),而不是用继承的方式,这样别人不知道函数的来源

变量

个人喜欢在第一次需要使用变量的地方声明,而不是在顶部一口去声明

注释

尽量少写注释

  • 写注释意味着你的代码不够优雅,别人无法理解
  • 能用函数和变量拆解的时候就拆解,而不是用注释去描述
  • 你无法始终坚持维护你的注释,会出现各种问题
  • 不要注释代码,我们有优秀的代码管理器,无用的代码就删掉就可以了,它会保留的。

好的注释

  • 法律与版本信息
  • 某个决定背后的意图解释,便于后续别人的修改
  • TODO

如何写注释

  • 一旦写注释就要花时间写好注释,注释的角度尽量从别人的角度出来来想会有什么疑惑,而不是解决自己的疑惑
  • 不要尝试描述代码本身

数据,对象的反对称性

抽象

  • 隐藏实现并非在变量之间放上一层函数层,也不是单纯使用取值器和赋值器往外推,而是暴露抽象接口,以便于用户无需了解数据形式就可以操作数据。
  • 过程式代码便于添加函数(switch实现);对象类代码便于添加数据类型(多态实现)
  • DTO(data transfer object),豆结构,即只有赋值器和取值器操作的私有变量

错误处理

try-catch

  • try-catch: 一开始可以用exception捕捉,捕捉到之后要缩小到对应范围。
  • try的内容是一个原子事务,这一点要注意想清楚。

NULL值处理

  • 绝对不要返回Null值,否则别人检查null值会很麻烦,而且检查一多就会乱(可以内部直接抛出错误,也可以定义为空值就好)
  • 禁止参数传入Null值,否则你总不可能每个变量一个个检查null(如果实在没有办法就只能用断言assert检查一下吧,用if有时会太乱混淆)

短小

  • 类的名称要描述其权责而不能是一些模糊的词(Process,manger,super),而且描述该类职责的时候不应该出现if/and/or/but这些词语
  • 类的权责应该是单一的,尽量拆成多个短小类吧
  • 长的函数拆成小的函数的时候,参数是否要传,若是那为什么不把它们变成一个类,参数是它们的成员变量就好了。注意变的时候保持单一权责
  • 注意职责的分隔。如果当你新增一个功能可能会影响其他时,说明耦合过强

好的代码示范

书的附录记录了好的代码示范

# 优秀的缩减了代码的长度,在简单代码的情况下,简洁是第一要义。所以允许在前面return
public boolean addCustomer(Customer customer)
{
	if(this.customers.length == this.total) return false;

       customers[total++] = customer;
       return true;
}

重构

重构的过程

发生的时间:

  • 当你想要给程序添加一个新特性的时候。
  • 营地法则:保证你离开时的代码库一定比来时更健康。

第一步:

  • 确保即将修改的代码拥有一组可靠的测试。

第二步:

  • 从整个代码中分离出不同的关注点。
  • 提炼代码到新的函数,关注又那些变量会离开原本的作用域
  • 每走一步都需要测试一遍,保证不会出错

第三步:

  • 提炼出新的函数后首先关注变量改名
  • 关注函数的参数之间关系,是否真的需要传入

第四步:

  • 去除临时变量,用内联函数进行替代。(我不太喜欢,因为内联函数名字比较长)
  • 检查变量是否可以合并或去除。

第五步:

  • 检查循环,将不同的任务拆分,可以允许多个循环,如果重构引入性能损耗,先完成重构,再做性能优化。

第六步:

  • 拆分计算阶段与格式阶段,即输出的时候格式可能会经常需要变动,避免重复的代码,应定义一个对象的格式作为计算阶段与格式阶段的交互。

第七步:

  • 多态取代条件表达式,如switch等

注意事项

  • 为了简洁,在不会有太大变动的部分,可以采用一些不好的习惯。

重构的原则

  • 重构是一个个小步骤,不是在迭代阶段的最后才执行的事情。
  • 添加新功能时不应该修改已有代码,只管新功能,两顶帽子(重构和增加),每次只戴一顶
  • 重构的时机:在添加新功能之前;当你需要思考这段代码到底在做什么;不需要重构的时机:不会有改动的地方,可以被API隐藏
  • 面对遗留代码,不建议一股脑全部重构,更愿意随时重构相关代码,每碰到一块代码都保持营地法则。

什么情况下重构

结合重构的过程

  • 奇怪命名与重复代码
  • 过长的函数,当你感觉要注释的时候,就需要把这一部分提取到一个独立的函数中
  • 全局变量,全局变量要么是常量要么就提供get/set方法。
  • 可变数据(可以建立原则:如果更新一个数据结构,就返回一个全新的数据副本)
  • 发散式变化 ,即同一个模块需要根据不同的原因发生变化,就要考虑是否可以拆分
  • 数据泥团,许多参数都喜欢糅杂,所以要用类去为它瘦身(很常见,数据项会经常很多)
  • 纯数据类常常以为这行为被放在了错误的地方,只要把处理数据的行为搬移到纯数据类里,就可以使情况大大改善。

构筑测试体系

编写优良的测试程序,可以极大提高自我的编程速度,即使不进行重构也一样如此。

测试法则

  • 测试不是要把所有的错误找出来,所以你大可不必担忧繁杂的代码,而是让你更有自信的进行下一步。则保证核心主线功能正确
  • 不是再每次迭代结尾时增加测试,而是只要写好一点功能就添加它们
  • TDD测试驱动开发,为了添加这个功能,我需要写什么测试函数。
  • 注意测试代码中那些重用的对象,有可能不同测试函数之间产生干扰导致结果出错。
  • 每当你遇见一个bug,先写一个测试来清楚地复现它。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值