生命中的一天
原作:Noel Llopis
翻译:King
2006年2月5日
转载请注明作者和出处,如有商业用途请联系作者kingcrimson at tom.com本文第一次发表在《游戏开发者》杂志的2005年就业指南上。
High Moon Studios 是游戏行业中一个不平凡的公司。我们的全部开发过程都使用了敏捷开发方法。特别是我的团队,同时使用了Scrum(一种敏捷管理方式)和极限编程(一种敏捷开发方式)。这意味着我们要配对编程,测试驱动开发,以及一切有争议的实践。我期望在未来几年内,这些实践将会变的更加寻常。
我领导着研发组(R&D),我们的首要职责是为不同项目的团队提供技术支持。如今,这意味着按他们的步伐找出大量中间件,再选择符合要求的去使用。但这也需要我们去干一些苦活,为引擎和工具编写大量代码。
记住这一点,然后随我来经历一个典型的工作日。
8:10 AM
我像往常一样,骑车去上班。尽管我是只早起的鸟儿,但我们的一个程序员Jim还是比我要早到几分钟,并且已经坐在办公桌前了。
我快速的接收了一下电子邮件。同时我注意到PCLint在昨晚检查我们代码库时捕获了几个小的warning。我很快解决了它们,并把代码签入。
8:20 AM
今天是周二,我们两周的迭代会在周五结束。一个迭代由一段固定时间组成(我们团队通常是两周)。在这期间,团队要根据客户描述的需求交付一组可使用的功能。客户(在这里是指公司内部其他团队)提出需求,并赋予它们优先权。之后我的团队会把这些需求拆分成若干任务,并估计多长时间能够完成它们(任务会在1到8小时之间变化)。
我和Jim来到了“战争室”(这间屋子的墙上贴着所有对应用户需求的任务卡片),并选择了一个任务“混合ragdoll和动画”。这个任务来自于用户需求“把一个刚体扔到角色身上,能看到撞击反应”。这个任务早先估计能3小时完成,但是现在我们认识到ragdoll系统比我们预想的有一点复杂。于是我们重新估计了任务时间,定为4小时。
8:23 AM
在研发组的实验室中,除了我们自己的工作区域外,还专门设置了配对编程的位置。每个位置拥有两台显示器、两个键盘、两个鼠标、两把椅子,以及容纳两个人的空间。我们所有产品的代码都是由配对编程的程序员完成的。我和Jim随便挑了个位置,开始工作。
自从采用测试驱动方法进行开发后,我们首先会为要实现的内容编写一个简单的测试单元,之后再写完整的代码让测试通过。在这个任务中,我们为第一个测试单元编写了一个没有输入输出的混合对象(Blender Object)。之后我们编写了混合类(Blender Class),使测试通过。这只是一小步,但是方向是正确的。编写测试单元、测试、重构,这整个环节只需5到10分钟,并且我们反复的去重复这个环节。
8:39 AM
我们已经实现了一小部分功能,并且所有的代码都构建并测试完毕,于是我们把它签入到代码管理(source control)中。这种方式被称为持续迭代,要求程序员在代码管理的最新版本工程中工作,并在一天里多次签入自己的修改。
8:50 AM
其他的团队成员陆续加入工作,占据了配对编程的各个位置。接下来我们互相做了简短的沟通,明确我们各自的工作。
玩命工作……
9:37 AM
我无意中听到Joel和Gary在讨论他们如何测试一些需要更新物理模拟的东西。我正好在几天前做了这些,于是我加入他们的讨论。我发现他们要做的一些工作是我之前已经做过的,于是我帮他们找到我写的东西,他们改动一下就可以使用。
10:05 AM
一切都进展的很顺利。我们在早上就已经签入了四次。当一个二人组工作正常时,他们在一天中会签入20次或更多。照这个速度,我们比预先估计的四小时要提前完成。
10:14 AM
每天10点15分是我们的Scrum会议时间。我们全体聚集到战争室,准备开会。Scrum会议非常短,并且全体团队成员只需站着开会(成员8人,再加上制作人Brian)。我们在屋里快速的走来走去,并开始讨论目前的工作,让所有人都跟上进度。
10:23 AM
会议中,出现了一个如何去读取物理资源的问题。我们立即来到了配对编程区域,和与之相关的所有人展开讨论。我们在白板上画了一些简洁的UML图示,思考数据是如何传送的。在十分钟后,我们达成了一致意见,并返回各自区域继续工作。
11:15 AM
我们的混合(Blending)工作的很正常。所有的单元测试都通过了,尽管我们还没有把它用demo实现。因为还有一张任务卡需要一起来完成。我们马上把代码签入。这些代码显然还有少数几个地方可以改进,因为我们刚才集中在功能实现上,所以需要花些时间去重构。我们进行了大量的单元测试,所以我们确信重构不会导致任何bug。
11:56 AM
现在代码处在一个更好的状态中。我们把它签入,并等待了几分钟,直到构建服务器传送回报告,所有内容都构建完成并测试通过。在这段时间内,我们讨论了下一个任务如何进行。
12:05 PM
我们所有成员今天的工作进展齐头并进,所以我和几位团队成员约定在午饭时间去上网。如果不上网,我还可以去打篮球、骑车、跑步,甚至瑜伽。除此之外,还可以和High Moon工会的成员一起玩《激战》(Guild War)。
1:10 PM
我回到办公桌前,潦草吃了顿午饭,同时查看邮件(我在早上接收的,但因为一直在配对编程,没有时间查看)。我读了一封来自中间件开发商的邮件,关于我们早先的一个需求问题。我迅速发了回信。
1:25 PM
Sean来到我座位前。他正准备开始工作,但是上午与他配对的程序员被叫去处理Darkwatch的一些最后的问题。这个任务十分重要,优先级高于我们在做的任何任务。
Sean迅速向我讲解了他上午进行的工作,关于显示我们物理系统的内存使用状况。我记得他们在上午的Scrum会议上提到过。我上一周也在为物理系统工作,所以我对代码更熟悉一些。没过多久,我们对任务已经有了进展。
……玩命摇滚:)
2:07 PM
在编写几个测试单元并实现了一些功能后,我们准备把内存显示加入到demo程序中。几分钟后,我们在demo中显示了物理系统使用内存的状况,并且测试在加入和移除刚体时,能显示出高低变化。
但是出现了问题。当我们移除刚体时,内存使用没有显示降低。我们退出了demo,并且看到了一长串内存泄漏提示。我们首先签入了改动,然后跟踪内存泄露的代码。这很可能不是由我们写的代码引起的,但是我们整个团队遵照“代码共享”原则。这意味着每个成员都可以在任何时候修改其他成员的代码。
2:12 PM
构建停止了!构建服务器检测到构建失败,并通过一个系统托盘程序提示我们。我打开了最新的构建日志,看到release模式下一个单元测试失败了。这时,坐在我们旁边的Tyson说:“噢,我知道这是怎么回事。我正要去修改它呢。”不到半分钟,他完成了改动并签入代码。几分钟后,构建系统汇报构建通过,一切重返正常。
2:17 PM
我们找到了内存泄漏的地方,发生在一个引用计数的错误使用。我们先写了一个测试单元显示它的错误,然后在物理库中修复了它。我们签入了代码。
2:18 PM
我们来到战争室,取下了一个任务。这个任务是要在demo里通过一个GUI,显示出不同变量和函数的信息。我们登记了这个任务,开始下一步工作。
3:43 PM
我们一直在待在配对编程区。我们近乎疯狂的编写测试单元和代码,任务进展非常顺利。在上一个小时中,我们为这个任务签入了三次。
4:12 PM
另一对程序员在讨论如何处理一些特殊情况的错误信息。这是一个重要的问题,并且应该贯彻于所有代码。我们开始了快速的讨论,大多数团队成员都参与其中。五分钟后我们做出了决定,然后回到各自的工作中。
5:40 PM
我们进行了今天最后一次签入。我们几乎完成了这个任务,但是还差一点。尽管我们可以再花一小时去完成它,但是我俩都非常疲倦,并且思路已经不那么清晰,会犯一些错误。我们可以明天早上一来就继续完成它。接下来是重要的部分,我们是否可以成功签入。
我们团队有一个规矩,任何人在下班时,不能签入完就离开实验室。你必须等待构建服务器成功构建代码并且通过测试。我们保持短促的构建时间,所以只需要再等待4到5分钟。如果有任何地方崩溃,你就需要重新修复它。任何人没有借口在构建失败时离开。
在等待构建完成时,我查看了今天收件箱里积累的邮件。
5:44 PM
几分钟后,构建服务器传来成功的消息。今天是效率非常高的一天,照这个进度我们在周五就可以完成所有的用户需求。聚集了各自成果的demo也逐渐开始显得很酷。
敏捷开发,特别是配对编程的一个特征,就是让每一天都变得很紧凑。没有小的空闲去阅读邮件、浏览网页,或者发呆。我们在一个工作日里完成了很多工作。但是我们不能在一天里长时间保持这个节奏,所以按时收工回家是很重要的。这使我能有时间在家阅读技术书籍、构思不同的想法,或者做次要项目的一些工作,或和家人在一起,享受其他爱好。
我登上爱车,朝家的方向驶去,脸上洋溢着笑容。