There you are! You, yes you! Been tasked with a new feature or a change, to the code or a script, to be done by yesterday, haven’t you?
Yes, yes, I know your pain. You’ll be wading through oddly named files, containing briefly labeled identifiers for elements in an obscure relation, and maybe a sprinkle of outdated documentation or commenting to help losing your way. Maybe you’ll be trying to patch in your tasked change, secretly cursing your predecessors’ names for their sloppiness, perhaps the commissioner’s demand to implement something that was clearly not in the scope of the contract, all the time looking at the ever-growing list of bugs (they breed while you’re not looking, you’re sure of that).
Wait, before you light the candles around the pentacle, let me challenge you.
It should just work?
“Muttley, do something!”
– Dick Dastardly
Make minimal changes, briefly check it doesn’t crash, conjure an explanation for your changes for the buddy check, submit with a meaningful description, build machine is green, task done, next!
Sounds familiar? If it is, chances are, not knowing, you added entropy to the system. Made it more obscure, difficult to maintain and refactor. Created harder bugs. Killed performance bit by bit, not with one gunshot but thousands of needle pricks, one per check-in. If you’re really lucky, you created some race condition. You increased the project’s technical debt.
I know it’s true, I’ve done it myself time and time again, until I finally learned these words of wisdom:
Leave it better than you found it
“I never pick up an item without thinking of how I might improve it.”
– Thomas A. Edison
Whenever someone has to make a change, some of the time is lost to understand the context. Your changes are not final either, not even if you’re going gold, therefore my suggestion is: make changes so that the process goes faster for the following times.
In doing your task, you’ve opened a few files; scanned through a few functions; read some lines, followed the flow or execution; wrote new code, perchance creating new class variables or using global ones. Unless you know the code by heart and you were the only one working on it in the last weeks, this process can range from tens of minutes to days (!!).
Were the files and classes names appropriate and what you expected, were they easy to reach, or did you struggle to remember what their names were? It doesn’t take long to rename a file and possibly the contained classes, with a decent tool.
Were the interfaces easy to understand and follow? Were the functions minimal and in charge of only one task? Incremental changes tend to make a mess; it doesn’t take long to rename a function, split it into (more) atomic tasks, and refactor common pieces of code to eliminate duplication. Easier to test, easier to read, and to follow! Oh, and please eliminate those long unused class members, it smells of bit rot in here.
Was the code self-commenting, was the spelling correct? Rename the methods and variables to make it so; create auxiliary functions to help readability. Machine time is cheap, human time isn’t, so use that compiler optimization and make it easy for you and your fellows to read. And if someone wrote “local” instead of “locale”, fix it! Grammar and spelling count, especially if you have non-native speakers on the team.
Are there hard-coded values? Extract them, parametrize. Maybe even make that an exposed variable and save yourself the pain of having to change the code when the designer itself can do it. Designers love the ability to experiment with game parameters, and it’s a great way to aid the creative process – more on this in another article!
Were the comments relevant, helpful and up to date? You’re in a unique position to know if they were, because you just used them. Fix them if need be, integrate the parts where you had to spend some effort understanding the inner workings. Consider rewriting the code to be self-commenting (and test accordingly if you do), or at least fix the names!
Are the original assumptions still valid? It made plenty of sense to use bubble sorting when the specs said there would be never more than 20 elements, but now you’re using many a thousand per frame. Maybe a refactoring is inappropriate at this time, but you can make a note to someone to double check and profile.
Is the code readable and visually coherent? Whatever the writing style of choice, it always should be followed for optimal reading results. Put spaces and indenting in the code you’re reading as you read it, and next time it’ll be already nice and tidy.
Are there any warnings in the code you’re touching? Address them before moving forward. Warnings are there to inform you there’s something fishy going on and when you have a thousand warnings nobody’s going to notice one more… until it bites as a bug and robs you of a day’s worth of work to track it down. And it does.
If you’ve been tracking a bug, have you made your test cases and assertions better, so that next time you won’t have to wade through the jungle to find the problem? Have you gone and fixed the root of the problem, or just threw a bug-festering bandage in way after the problem is generated? There’s always a “why” for a bug, and working around it “where” it shows itself isn’t going to fix it, not in the long term, especially not if there’s multithreading involved.
“But I don’t have time to fix the world”, I hear you scream. Oh dear, that sounds awful. Luckily, there is a way out.
A penny invested is a dollar saved
“The only valid measurement of code quality: WTFs/minute”
– Thom Holwerda
Say you’ve spent an hour understanding the context of your original task (an hour!). If you just stick to the job, anyone coming to the code after you (or yourself, after a few weeks) will have to spend pretty much the same amount of time, usually worse, to be able to do anything with it. That includes new features, tweaks, and most important, bugs (tons of them, the hordes!).
By making the code more readable, you’re investing in the future of the project. You’re making code changes easier, less risky. You’re making the general mood better, as you and your colleagues won’t have to curse and swear to understand what’s happening. You’re learning about writing good code bit by bit, without special courses or classes. You’re also teaching the juniors a new way of going forward, of caring about the project, of writing readable code. You’re taking good care of the project, and this does not go unnoticed.
(This clearly does not apply to everything. Throwaway code and quick scripts must not apply. Tools, sometimes. Game code, often. Be sensible, be incremental.)
The magic moment for me was when the team I was part of realized that, by cleaning as we went, we were actually ending up ahead of milestones with no major bugs, and a reusable code base; I’ve surprised myself wondering if I had understood the meaning of “(just) works” in the first place.
I wish the same to you.