High Moon Studios is an unusual company in the games industry. We’re applying agile methodologies for all of our development. My team in particular is using both Scrum (an agile management methodology) and Extreme Programming (an agile engineering methodology). And yes, that means we’re doing pair programming, test-driven development, and all the other often controversial practices. I expect that in a few years, these practices will be a lot more common than they are today.
This article was first published in the 2005 Career Guide issue of Game Developer Magazine.
I lead the R&D team here, and my team’s primary responsibility is to come up with the technology that game teams use for different projects. Nowadays, that means putting a lot of middleware programs through their paces and choosing the ones that suit our needs. But it also means getting down and dirty and writing a lot of code for our engine and tools.
With that in mind, come on and follow me through a typical workday.
I roll in to work on my bicycle like I do every day. Even though I’m an early bird, Jim, a programmer in my team, arrived a few minutes earlier and is already at his desk.
I quickly catch up with my email. I also notice that the PCLint pass on our codebase last night caught a couple of minor warnings, so I quickly fix those and check them in.
Today is Tuesday and our two-week iteration ends on Friday. An iteration consists of a fixed period (usually two weeks in our case) during which the team commits to deliver a set of functionality described through customer stories. The customer (in our case the other internal teams in our company) creates and prioritizes a set of stories. My team then breaks down those stories into tasks and estimates how long they will take to complete (tasks vary between 1 and 8 hours).
Jim and I walk over to the “war room” (the room with all the task cards corresponding to user stories pinned to the wall) and we choose the task that reads “Blend ragdoll and animation,” which is part of the user story listed as “Throwing a rigid body at a character and seeing a hit reaction.” The task was originally estimated at 3 hours, but now that we know that the ragdoll system is a bit more complicated than we thought, we re-estimate it at 4 hours.
In addition to our own personal desk areas, we have pair-programming stations in the R&D lab, with two monitors, two keyboards, two mice, two chairs, and plenty of room for two people. All production code is written by pairs of programmers. We grab a station and start working on the task.
Since we’re using test-driven development, we first write a very simple unit test for what we want to do, and only then write the code to make it pass. In this case, our first test checks that we create a blender object without inputs and that it produces no output. Then we write the blender class and make the test pass. It’s a tiny step, but it’s a step in the right direction. The whole cycle of write test, write code to make test pass, refactor, takes only 5-10 minutes, and we do it over and over.
We have implemented a small amount of functionality, and all the code builds and all tests pass, so we check it in source control. This is called continuous integration, and it requires that programmers work on the latest version in source control and check in their own changes many times throughout the day.
Other people from the team roll in, grab other pair programming stations, and start going at it. On their way in we have a quick chat and find out what we’re all working on.
I overhear Joel and Gary discussing how they’re going to test something that requires updating the physics simulations. I just did that a couple of days ago so I jump in the discussion. It turns out they need to do something that is almost the same as what I already did, so I point them to what I wrote and they will modify it to suit their needs.
Things are moving along very nicely. We’ve checked in four times already this morning. When a pair gets really going, they might check in as many as 20 or more times in a single day. At this rate we might be done sooner than the four hours we had estimated.
We have the daily Scrum meeting at 10:15, so we head over to the war room. Scrum meetings are very short, standup meetings with the whole team (eight people plus Brian, our producer). We quickly go around the room discussing what people are doing to get everybody up to speed.
During the meeting the topic of how we’re loading physics assets came up. So we return to the pair programming area and have a quick discussion with everybody involved. We draw some quick UML charts on a whiteboard, think about how the data is going to be passed around, and after ten minutes we reach an agreement and go back to work on our tasks.
We got the blending working correctly. All the unit tests pass, although we haven’t implemented it in the demo yet. There’s another task card for that. We check the code in right away. The code definitely can stand to improve in a few places because we were just concentrating on getting things working, so we spend some time refactoring. We have lots of unit tests, so we’re confident our refactoring isn’t introducing any bugs.
The code is now in a much better state. We check it in and wait a few minutes for the build server to report that everything built correctly and all tests passed. During that time we talk about what the next task should be.
We have nice shoulder-high surf today, so I’m going out surfing at lunch with several of my teammates. If it’s not surfing, it’s a basketball game, cycling, running, or even yoga. If all else fails, there’s always a game of Guild Wars with the rest of the High Moon clan.
Back at my desk I eat a quick lunch while I catch up on my email (which I haven’t read since this morning because I’ve been at the pair programming station). I read an email from a middleware developer in response to one of our queries earlier in the day and fire back a quick response.
Sean stops by my desk. He’s ready to go back to work, but the programmer he was pairing with in the morning got pulled to work on some last-minute issues with Darkwatch, which is about to go gold and has priority over anything we’re doing.
Sean quickly brings me up to speed on what they had been working on that morning, which was to display the exact memory usage for our physics system. I remember them mentioning that in this morning’s Scrum meeting. I also worked on the physics system last week, so I’m pretty familiar with the code. In a couple of minutes we’re already making progress.
After writing several unit tests and implementing some functionality, we’re ready to add the memory display to the demo program. A couple of minutes later, we have a display in the demo indicating how much memory the physics system is using, and we see it go up and down as we add and remove rigid bodies from the demo.
But something is wrong. When we remove rigid bodies, the memory doesn’t come down to the same level it was before. We exit the demo and we see a long memory leak dump. First things first, we check in our changes, and then we dive in and look for the code that is leaking memory. It’s probably not caused by the code we just wrote, but we have “collective code ownership,” which means that everybody is expected to fix anything that needs fixing anywhere.
The build just broke! The build server detected a failed build and notified us through a system tray application. I bring up the latest build log and I see that one of the unit tests failed in release mode. Tyson, who is sitting at the station next to ours, says “Oh yeah, I know what that is. I’ll fix it right now.” In less than 30 seconds he makes the change, and checks it in. A few minutes later, the build system reports a passing build and everything is back to normal.
We found the memory leak. It was a misuse of reference counting. We first wrote a unit test that showed it failing, and then we fixed in the physics library. We check in our code.
We go to the war room and grab the next task. This one has to do with being able to expose different variables and functions on the demo to tweak them through a GUI. We sign up for the task and start working on it.
We’re totally in the zone. We’ve been writing tests and code like crazy and this task is going really well. We’ve done three check-ins for this task alone in the last hour.
Another pair is discussing how to handle errors for some particular case. This is an important topic and it should be done consistently across all the code, so we have a quick discussion about it involving most of the team. Five minutes later we’ve made a decision and we all resume working on what we were doing before.
We do our last check in for the day. We’re almost done with the task, but not quite there yet. Even though we could stay another hour and try to finish it, we’re both quite tired by now and we’re starting to not think as clearly and make some mistakes. We can wrap this up tomorrow morning as soon as we get in. The important part is that we got to a state where we could check in.
We have a rule that says nobody can check in code and leave. You have to wait for the build server to build the code successfully and pass all the tests. We keep build times short, so that usually means hanging around an extra 4-5 minutes. If anything breaks, you need to fix it or revert what you did, but there’s no excuse to leave with a broken build.
While I’m waiting for the build server to finish, I check the pile of email that accumulated in my inbox during the day.
After a few minutes we get the green go ahead from the build server. Today was a pretty productive day, and at this pace we will definitely complete all the user stories by Friday. The demo we’re putting together is also starting to look very cool.
One of the things that agile development, and especially pair programming, does is to make each day very intense. There are no little breaks to read email, check a web site, or just goof around. We get a lot accomplished in a work day, but we can’t keep that pace for a long time, so it’s important to call it quits and go home. That leaves me with time at home to read technical books, prototype different ideas, or work on side projects in addition to unwinding, spending time with my family, and enjoying other hobbies.
I hop on my bike and head home with a big smile on my face.