Godsend Project Management #3: Programming as a Team

In this entry I will be discussing the way we approached teamwork in the code team, task distribution and supporting each other.

Distributing tasks

At first, we identified that we need to implement the character controls and the dash mechanic, the collectibles, exit, player death and the different types of platforms. In true agile fashion, we had a discussion about who would like to do what, so that everyone’s as happy as possible with what they’re working on (which should boost productivity as well I think).

I suggested that I could work on the character controls, since I have similar experience already when working on a game called Sailing in a Parking Lot (Mindaugas Kadzys, 2015). I wouldn’t call character controllers my strength area, as the aforementioned game had abysmal controls. However, I had a ground to learn from already when implementing controls again. Character controls are tricky to implement well and it’s crucial for any platformer to have them as solid as possible. I am happy that I took on myself to work on them, as my previous experience did indeed allow me to avoid previous mistakes and the character controls as they exist now are appreciated by the team as “good” (needless to say, I can’t judge them positively myself, as I have way too much personal opinion in this matter).

Radu worked on the Exit, Collectibles and Player Death, and he seemed to handle the task quite well. Alvaro worked on the different types of platforms, which later turned out to be dependent on the player controller code, as a travelator needs to affect the player directly, for example.

This was not good, as it turned out that we are working on inter-dependent tasks and his progress was dependent on mine, which in turn slows down development. This could have been avoided by giving the tasks some more thought and fleshing them out further before jumping to implementation, and I think it’s one of the things we should really learn from going forward. Furthermore, Alvaro had to familiarise himself with my character controller code, which slowed down development even further, and I can’t help but think I could have implemented these features quicker just because of the fact that I knew my code already.

Supporting team members

Since Alvaro took quite a long time to get the different types of platforms working, I thought I should stop taking on new tasks and support him more instead. This way we could share the knowledge that we have accumulated about the physics engine and the framework in general and potentially solve the problem more effectively. I spent time sitting next to his computer and trying to make progress collectively (or, as this is sometimes called, Pair Programing). This worked out well and we were able to finish the platforms together, as I could guide him through my character controller, as well as explain the implications of making changes to the character velocities, etc in the current implementation.

Furthermore, since it took quite a bit of time for Alvaro to finish the task, I feel like his enthusiasm could have dropped for what he was doing, slowly getting replaced by frustration. Since tasks like travelators and moving platforms rely on the character controller, I think we could have at least had a discussion about whether he would like to work on something else, something more appealing to him and that way boost his productivity, while I could have taken over the remainder of the platform task and glued in what he had already implemented with my character controller code.

I am unsure if this would benefit the game, but I feel like a discussion would have at least made things clearer about what Alvaro’s opinion on the task was, which leads me to the next important subject.

Communication and sharing knowledge

I think we made a bit of a mistake in the way we worked together, as I think we lacked communication. When learning a new framework/engine, members will learn at different rates and will discover different ways to do things, as well as different features of the engine. The way we approached learning was highly individual, and everyone ended up struggling with similar problems and learning similar things individually.

While I do appreciate the Brain, Book, Buddy, Boss methodology of figuring things out, I do feel that sometimes it’s better to switch Book and Buddy around, especially if everyone in the team is learning the same things at the same time. So I think that instead of tackling a problem on our own, we should have first asked each other if anyone else has encountered it before. This would have lead to quick problem resolution and, as the saying goes, explaining stuff you know to others makes you learn yourself as well. At early stages in the project, I think it would have saved time if we did this and we should aim to communicate more moving forward, as it increases the programming strength of the whole team.

Bugs, bugs, bugs

The final topic to discuss in this entry is fixing bugs. These appeared frequently, as we were all rushing towards completing features and because testing was expensive in terms of time.

The time cost came from the fact that we did not have a level editor at this stage, so testing out a feature against all other features and interactions required manual set-up in the code. This got very time consuming to do, and we mostly tested for the current level set-up that we had. The negative effect of that was a lot of bugs appearing when we started to re-structure for our white-box level, since the layout on the screen changed drastically.

On one hand, such an approach does not scale well, as we implement features without knowing whether they actually work well enough. On the other hand, this saved huge amounts of time, since we discovered a host of bugs at once, and since we did not labour over creating elaborate test situations. We will still need to create these situations in the future, but it will be cheaper to do then, since we will have an easier way to set these up.

We approached fixing bugs with some more Pair Programming (Wikipedia, 2006) as well. The reason for this was that we decided to put a halt on development to actively eliminate as many existing bugs as we found (we also fixed bugs individually up to this point, but the whitebox level re-design exposed a good quantity immediately). In other words, our build lacked stability, and it did not make sense to implement new features before stabilising the build. Another reason to do it on a single screen was in order to avoid creating more bugs: one person’s fix can imply a bug on the other person’s fix. We wanted to avoid this cycle.

This would probably not work on a larger development team, as it would become wasteful to have a big team sitting in front of one screen, but it worked really well for the three of us. We had the full implementation knowledge between us, and we had two extra pairs of eyes in front of each of our written code. We managed to fix a lot of the bugs in just a day by applying this principle. I think it worked really well at this early stage when the code base is not too big yet, and when our knowledge base differs due to the nature of different problems we encountered individually.

Once this knowledge base equals out and the code base grows, we might have too much testing to do and might not be able to replicate the success of this approach, but I think we should at least consider doing it again if the situation is favourable. In an ideal scenario, we will all be confident enough to fix bugs individually and test sufficiently effectively and quickly to push out patches ourselves. In a non-ideal scenario, I think this is just as good of an approach to stabilising the build from the current experience we have had.