每次都需等待 15 秒,才能看到代码错在哪里
2014 年,我以一名实习生的身份加入了 FIFA 团队,对于当时的我来说,3A 游戏开发完全是一个陌生的新世界。我记得当我看到我的电脑有 16 个 CPU 核心时,十分惊讶。我还记得,当时我按照说明进行了设置,并得知第一次构建需要 30 分钟的准备时间。不过,据说之后的增量构建会快很多。
虽然增量构建确实快了许多,但每修改一行代码仍然需要花费 10 秒来编译。当时的我还是一名 C++ 开发新手,犯的语法错误数量很多。每次修改完代码,都需要等待 15 秒,才能看到究竟哪里错了。
修改三行代码确实需要一整天的时间
我会在等待期间找一些别的事情做,比如上网查资料,修改其他代码,或者检查邮件等。因此,难免会分心,往往一个不小心就过了几分钟,才想起来检查编译状态。
然而,编译只是第一步。接下来,我还需要打包应用程序,并部署到我使用的游戏机。最初,我使用的是 PS Vita、Nintendo 3DS 和 Nintendo Wii,这就又需要花费半分多钟才能完成游戏的加载。接着,我需要启动游戏,找到我负责的游戏区域,然后才能看到代码的修改结果。
当时我负责的是竞技逻辑部分。为了测试前后变化,我需要在生涯模式中进行至少几个赛季,才能测试自己的修改。
所以,不是开玩笑,修改三行代码确实需要一整天的时间,才能知道是否可以正常工作。
调试工具
后来,我开始使用较新的游戏机,并开始接触 testbed。这些 testbed 不过是一些精简的游戏包,仅包含特定的代码,目的是缩减迭代时间。在找到生涯模式的 testbed 后,我几乎再也没有运行过整个游戏。这个 testbed 可以在几秒内构建完毕,而且还包含各类调试功能。testbed 可以在 PC 机上运行,因此可以大幅提高效率。
在发现这款工具后,我非常激动!但我发现周围的很多人都不知道如何使用这个工具。他们只是按照原有的方式启动完整的游戏,手动找到所需的位置,然后测试代码的变更。很快,我就熟练地掌握了 testbed,并添加了很多新功能,大幅地减轻了开发新功能的负担。
不过,偶尔我还是需要运行完整的游戏,但这个 testbed 提供了很多便利性,我能够在 testbed 上快速实验,然后看看代码的运行。此外,我还能够借助 testbed 快速解决实际的问题。
单元测试
后来,我又换了一个团队。我发现,这个团队已经全面实施了单元测试。虽然当时我有一些单元测试的经验,但从未在游戏开发中使用过。
我简单地学习了代码、不同的测试,以及如何运行我们的游戏。我发现,实际上测试包只包含我们团队负责的特定游戏部分。第一次构建大概需要 10 秒,之后的增量构建可能不到 1 秒。
这个数字对我的工作有非常重要的影响——因为编译和测试能在不到 1 秒的时间内完成,所以我就可以专注于一项任务了。编译和逻辑错误是不可避免的。但是,当我可以快速发现错误并重新编译时,整个工作状态就变得流畅起来,再也不会磕磕绊绊了。
我第一次享受到在工作中编写代码的乐趣:重构和移动大块代码非常简单,修改别人的代码也非常容易,并且我的修改不会导致整个游戏崩溃。因此,修改代码的焦虑也就是消失了。
我着手重写竞技模式的逻辑,并添加了单元测试。单元测试基本可以覆盖各种各样的边缘情况。在最终离开公司的时候,我感觉很放心,因为我的代码拥有自己的检查系统。原本我需要花费大量时间确认的错误如今已经被编写到了测试规范中。
总结
回顾这段工作经历,我心怀感激。在这个项目中,我亲身感受到长期的工程计划为开发人员的日常工作提供的便利。在某些时候,必须有人站出来说:“测试这些代码变更需要花费很长时间,难道我们就没有更好的方法了吗?”这也是我们每天都应该思考的问题。