构筑测试体系
重构是很有价值的工具,但没人能保证重构完的代码就是对的,所以我们需要一套测试体系来避免滋生了新的BUG。
自测试代码的价值
编写代码的时间仅占所有时间中很少的一部分。
有些时间用来决定下一步干什么,有些时间花在设计上,但是,花费在调试上的时间是最多的。
我敢肯定,每一位读者一定都记得自己花数小时调试代码的经历——而且常常是通宵达旦。
每个程序员都能讲出一个为了修复一个 bug 花费了一整天(甚至更长时间)的故事。
修复 bug 通常是比较快的,但找出 bug 所在却是一场噩梦。当修复一个 bug 时,常常会引起另一个 bug,却在很久之后才会注意到它。那时,你又要花上大把时间去定位问题。
一个好的循环是:
1 | while(发现代码坏味道) |
这节的重点在怎么去快速自测试改动内容,作者给出“自测试代码”的解决方案,“类应该包含它们自己的测试代码。”
理想情况是每次改动完,把代码扔进神秘盒子,它将会判决你此次改动有没有触犯代码世界的法律。
神秘盒子其实是一套由测试代码组成的系统,他将一系列模拟输入传递到你的代码中,得到返回值后与正确答案进行比较,如果符合预期则通过,不符合则反馈不通过的测试项。
在游戏开发中,这套测试体系可能不是那么好用,它要求有可预测的输入以及能得到可判定对错的结果。而游戏中输入通常会比较多,角色控制输入、相机控制输入、UI交互输入等等。系统输出的结果也多种多样,特别是容易受到多个系统组合影响,比如角色移动会受输入、物理、地形关卡设计等等因素叠加得到角色的位置。
但在一些数值计算相关,也可以适当使用自测试框架(取决于对BUG的容错、测试代码的维护成本以及系统是否足够复杂)。比如人物血量计算、技能CD计算等等。
Unity中的单元测试
使用了NUnit框架 ,具体写法和书中提到的Assert断言类似。
1 | using NUnit.Framework; |
游戏开发中可以引入测试工具的地方
- AirTest+PerfDog,模拟玩家输入,观察结果是否符合预期以及结合性能检测工具检测有没有内存泄露。更多用于上线游戏的检测(纯UI游戏比较好用)
- 协议测试工具,测试能否通过发包来获取奖励
- UWA 的静态资源检查,检测资源是否冗余、设置是否符合项目规范
- 表检查工具,检查策划的配置是否有常见错误
介绍重构名录
本书剩余的篇幅是一份重构的名录,用于提示自己如何以安全且高效的方式进行重构。
重构的记录格式
- 首先是名称(name)。要建造一个重构词汇表,名称是很重要的。这个名称也就是我将在本书其他地方使用的名称。如今重构经常会有多个名字,所以我会同时列出常见的别名。
- 名称之后是一个简单的速写(sketch)。这部分可以帮助你更快找到你所需要的重构手法。
- 动机(motivation)为你介绍“为什么需要做这个重构”和“什么情况下不该做这个重构”。
- 做法(mechanics)简明扼要地一步一步介绍如何进行此重构。
- 范例(examples)以一个十分简单的例子说明此重构手法如何运作。
一个重构并非只有一套做法。本书中选择介绍这些做法,因为它们大多数时候都管用。等你经过练习获得更多重构经验,你可能会调整重构的做法,那完全没问题。只要牢记一点:小步前进,情况越复杂,步子就要越小。
挑选重构的依据
很常用的重构手法,并且值得给它们命名和详细的介绍:
- 其中一些做法很有意思,能帮助读者提高整体重构技能水平
- 另外一些则对于代码设计质量的提升效果显著