I have one month to make an MMO: Sprint 4
Sprint 3 is the first sprint I’ve overrun, failing to achieve all of the sprint’s goals.
But, that’s ok! Software development is always hard to anticipate, and it’s more important to reflect on why it overran versus the plan to learn from it and avoid it in the future than it is to blame yourself (or others) about not reaching goals.
Let’s have a look at the journey so far
Sprints 1, 2, and 3 are marked.
Sprint 3 Retrospective
An overview of sprint 3’s tasks were:
- Get dialogues done (not completed)
- Get NPCs/mobs done (completed!)
- Dial back the work hours a bit (kind of?)
NPCs and mobs were completed successfully I can now define NPCs and mobs on the map editor, and they’ll be automatically puppeted by the server. It’s now a case of adding behaviour code, and add graphical assets for them as I develop the game more.
Dialogues were unfortunately not yet completed. I spent a a lot of time… probably too much time building a tool, spending over 14 hours on a day I was supposed to take off. The result was that I didn’t have the energy to work the subsequent day. If I had to analyse my thought process at the time, it was that I wanted to complete this tool on my day off so that I could return to regular planned work the next day. But of course, working 14 hours and then crashing out was counter-productive to that aim.
I think there’s a few things that happened here that’s worth talking about. Firstly, getting sidetracked with a cool but irrelevant task is something that happens to us developers a lot. It’s cool. You want to work on it.
But, pursuing those task to the extent of not being able to do the planned work the next day obviously has a big negative impact on the plans. On the one hand, I can argue that this is a pretty casual project and I should be more lenient on the plans. On the other hand, saying so would be hypocritical since I’m a believer that you should be disciplined in completing the tasks that you made a commitment to doing, even if it was a commitment to yourself. Saying “it was fun and I got distracted” is an excuse for poor self-discipline.
However, that’s not to say that I should have deprived myself of the opportunity to do interesting things. In retrospect, what I should have done is set aside more time to do it. Had I just given my self 2 days off, I’d have been able to spread those 14 hours over two days, and not be so tired afterwards. Though this too is a slippery slope, as I can’t guarantee that even with 2 days I would have managed that time or scope properly.
In any case, there are lessons to be learned here about being sidetracked. A lesson that embarrassingly I’ve failed on several occasions to learn from throughout my career, and this episode has demonstrated again that it’s something I’m still liable to do. I would like to think that I’ve improved over the years, and particularly when there are higher-stakes or other people depending on me that I make the right choices. I think I’ve successfully done that, but it’s hard to say whether I’m remembering correctly or I’ve tricked myself into thinking all my past actions were justified (self-delusion and excuse-making are certainly things I want to look out for, naturally as an optimist, I think I tend to gloss over the negative aspects of everything more than I should).
There aren’t any rules that say each sprint should focus on only one thing. It’s actually rarely the case that tasks happen to fit into a sprint exactly. It has been that way for my planning, but it’s been more of a case of me deliberately scoping the game down to fit into sprints as a method of preventing overscoping.
So while I could continue with the previous plans and slot the unfinished task into the sprint, instead what I’m going to do is take this opportunity to do some re-planning, and swap the plans for Sprints 4 and 5 around, so that I take the time now to do some graphical upgrades and address some technical debt.
I’m allowing the two tasks for Sprint 4 to be squeezed slightly by having to complete the unfinished dialogue system. But I’m deeming this ok since this task was always about tying up loose ends, and in itself had no hard goals.
There is no such thing as the perfect piece of code. We constantly make compromises between speed of development, quality of code, and the number of features we can add. I can best sum this up in the form of a Venn diagram:
If you develop quickly, and you want high-quality and bug free code, then the only way it’s achievable is if you reduce the number of features. This is appropriate for small projects only that have limited scope.
If you want high quality code and lots of features, then the only way it’s achievable is by putting a lot of time into it. A lot of personal projects tend to fall into this category, and there’s significant downsides to spending a lot of time on code — your motivation, time, and energy are limited resources, and if you don’t jealously guard and select what you spend those resources on, you will run out and not finish the project. What’s more, it becomes a vicious feedback cycle of loosing confidence because you don’t finish, which saps your motivation even more.
If you focus on features and development speed, you get code that lacks robustness or is buggy. The product might be usable, but has the liability of breaking easily, and potentially in unexpected ways. It may also be difficult to extend or improve because of a lack of forethought, and modularity. Focusing on these two prioritisations however, has somewhat of the reverse effect of the above: it is motivating to see a project come together quickly.
In the commercial software world, you can use this to quickly put together demos to show customers, and collect feedback on how people use the product. In the games industry, it’s similar, you can playtesters testing your game and providing feedback that you can use to further plan development.
It’s almost desirable to develop software in this way because the feedback could lead to drastic changes to the software, and throwing out a lot of old code that isn’t needed any more or wasn’t suitable for purpose. While it sounds like wasted effort to throw away code, it’s important to remember that the original code was what got you to this stage in the first place. It was merely a stepping stone which helped you gain the knowledge of where to go next. Without that code, you’d still be wondering whether this was the right path, and you risk finding out only after spending too much time on it that you were going in the wrong direction.
The downside is of course, your code will be buggy. But, that can be managed. This is where the concept of “technical debt” comes in. It means that you’re doing the project on borrowed time — you’ve deliberately taken coding shortcuts that you know aren’t necessarily the best idea for code quality, knowing that later you’d need to pay this back by spending the time to fix things. But, as mentioned above, fixing the problems later rather than immediately has the distinct benefit of having hindsight in what areas of your code need the most attention, and what bits of code you figured out you didn’t need anyway and therefore don’t need to pay back the time to fix it. This hindsight is a lot easier and more reliable a guide on what bits of code time should be spent on fixing, than having the foresight into predicting exactly what code or features need to be written.
Technical debt is only a bad thing if it is not managed. You’ll just continue building buggy and unstable code, to the point where you are spending more time hacking around hacks and fixing things that break than you are adding new features. But with setting some time aside to address it, allowing a bit of technical debt enables getting results sooner, and therefore being better informed about which areas of the code you should go back to and refactor.
To that end, while developing whenever I think of a feature that I’ll probably need but aren’t going to sit down and develop, I’ll note them down on Pivotal in the “Icebox”, a special area for this kind of thing
In addition to this, smaller areas that need to be refactored simply have a TODO comment in the code that I can do project-wide searches for. In Atom, it also shows up thanks to the linter settings. I get a yellow highlight on the line, as well as keeping track of it in the linter pane at the bottom of the screen.
So I’ll be spending Sprint 4 finishing the dialogue system, and then addressing some of these items, and also upgrading the art and doing a bit of world building so that the game isn’t restricted to the same tiny desert camp area that I’ve been screenshotting over and over again.