Working with Legacy Code
Developing a completely new project is pretty cool, but have you ever worked on a really old one? It can be very hard to navigate the legacy code, but the satisfaction of making it work and fixing it could be worth the effort.
“This code is horrible, it would be easier if we burned the project down and created a new one from scratch.”
Have you ever found yourself in a situation like this? You start a new job or join a new product team, and then you see all the bad code practices and think how much time you will need to implement a simple feature just so it can work without causing an insane amount of bugs? Your first thought is to imagine how much easier it would be to remake the project from scratch. But really, you can’t. Well, maybe you can, but is it worth the time and effort? Generally speaking, it’s just not reasonable business logic.
Well, I’d like to share with you a few tips and tricks I learned along the way to deal with these situations, but first let’s demystify why and how legacy code is made.
It all starts with an idea…
“I have an awesome idea for a game. How can I sell it to a company?”
Well, good luck. In reality, this is not something that you can expect. Small indie developers have their own ideas and are not really looking to outsource. Bigger companies work differently. They rely on game design, market research, core loops, prototyping, soft launching, AB testing, data research, analytics, tweaking… and a lot of other things.
Ideas are cool, but the execution of the same idea can vary from the best game in the world to the worst game ever. There is no formula that guarantees a game will be a 100% successful (at least to us, mortals). Therefore, you cannot know in advance if your idea is good or not. Companies don’t simply buy an idea just because you think it’s awesome and revolutionary.
So how do companies determine what is the best way to implement an idea?
We prototype and test, improve or scrap. Most successful studios develop new games under a small budget, and then pay the price later.
Have you ever made a game from scratch?
Imagine if you spend a year writing clean, perfect and scalable code that you want to frame on your wall and possibly introduce to your family and one day marry. And then it turns out the gameplay is lacking, the idea is not good, or just the timing is off for that type of game. Are you going to do it all over again?
When creating a prototype or an alpha version, you first want to find out if the game can be successful, and you want to know this as soon as possible.
You don’t think about what the game could look like in 5 years, because you don’t really know. You focus on making it interesting now. You will probably fail a few times. Maybe several times. Maybe it takes you 50 tries to actually create an awesome game.
But once you do, it’s already live. It already has a player base and you really want to give them more reason to continue playing. Then you implement a new feature here, a new offer there, and maybe introduce an expansion and a few other magical things happen. A year passes, and the game is already very different from what you first set out to create. Something you couldn’t possibly think of when you started your project. And then you patch things up. And suddenly you find your project mixing up frogs and old ladies (it’s a Serbian proverb, but your game might actually have a mix of that – I’m not judging your creativity).
How do you go from there?
Here’s what I recommend:
1. You need to be extra careful when making changes in the code. First, you need to understand what the changes in your code influence. Spending time on fixing bugs is always worse and takes more time than properly analyzing existing code. Just because the code is not written well, doesn’t mean it’s useless.
You create a way for the old lady to talk, but it somehow makes the frog legs twitch. Take your time to understand it’s nervous system before operating on its limbs.
2. You need QA for it to be tested properly. Developers tend to only test stuff they are currently working on, since it takes a lot of time to go through the whole game every time they implement something new. The more your game and codebase grows, the more time it takes to go through it all.
You make sure the old lady has a perfect British accent, but have you checked if your frogs can actually hear and understand her?
3. You can’t refactor everything at once. I do refactoring by creating a new system, and then switching old code into new bit by bit, in small chunks. When improving or fixing issues with an older feature—take the time to upgrade it to the better version as well.
You want a brand new mall, but your old lady really likes the local shop. Don’t demolish the shop and make her go to the mall, transfer the items from the shop one at a time.
4. Unclear code leads to ambiguity between developers working on the same project. We organize frequent code review meetings to share what, why and how we implemented something, and discuss what we all think is the best way to go about it. If we don’t have time to improve it immediately, at least we agree on how to do it in the future.
If you explain to others how the lady uses her voice, they won’t spend hours working on a new voice, when they already know how to make her sing.
5. Think about what’s the best way to do things for every scenario—should you refactor, should you create a new system, or should you just use the current system and improve it some other time? Communicate with your team about deadlines and issues, so everyone understands the benefits of each approach. Be ready to adapt instead of being blindly committed to your idea of perfectionism.
If the frog can jump high enough, do you really need it to jump further? If it’s enough for now, just let it be.
6. Leave the code better and cleaner than you found it. It doesn’t always have to be about big refactoring and drastic changes. Sometimes just leaving a few comments or even simple renaming will go a long way in making healthier code.
Just because the old lady can calculate a million things at once, doesn’t mean you should leave her to use all of her powers on a simple task. Optimize her logic so she can focus on other things in the future.
In the end, legacy code is not something that people want to make. Nobody starts a new project by saying they need 300 singletons to develop a great game. But in case you find yourself in such a situation, I hope these tips help you out.