I wish I could give a hug to the me of a year ago.
When you’ve been working on a large codebase for a long time, it’s common to forget bits of it. You create a mental model which represents approximately what a class or a file or a function does, and then throw away your memory of how the inside of the class actually works, to make mental space for other things.
This is a normal practice, as a programmer. (Probably in other disciplines as well, but I can only speak to life as a programmer.)
As a programmer, you’re often told that you should be writing comments in your code, to remind yourself of what the code is intended to do. The whole point of writing code comments is to record the knowledge that’s currently in your head, so you can dump it out, but still quickly get it back when you look at the code again later on. (Or so that a different programmer can understand what you were doing and why). A quick explanatory note can save a huge amount of time.
Usually these comments are just a quick jotted note here or there; something which captures the rationale for why the code is doing something, or walking through the steps that are about to happen, to give a broader overview of what’s going on.
MMORPG Tycoon 2’s code (excluding the game engine) currently consists of about 120,000 lines of code across more than 1,000 source code files. There are about 22,000 lines of comment, which is far less than most folks would recommend for a codebase of this size. Mea culpa!
But sometimes, a comment goes above and beyond that. Today, I stumbled over a note which I left for myself more than a year ago, apparently guessing that I’d need it someday.
Here’s the comment, in its entirety, taken from the top of the file
// ============================================================================ // IMPORTANT NOTE // ============================================================================ // // Hi, Trevor! :D // // If you ("I") are reading this file, it's probably because you want to create // an array of object pointers, where those object links get saved/restored, // and are trying to figure out how to do that, and this file looks like the most // likely file to find something that would do that, based upon its file name. // // The bad news is that the code in this file doesn't work for that! // // The GOOD news is that you don't need to use the code in this file! I have a class // 'vsObjectLinkArray' which does exactly what you want, and which obeys the 'object' // interface, so you can just use it with the regular 'vsDeclareObjectProperty' // macro; no need for a custom macro and support classes, like the ones at // the bottom of this file! // // So rejoice! It's all possible and easy. :D
This is an amazingly fantastic comment (if I do say so myself). It’s in a very rarely used bit of the codebase, and I apparently anticipated the reasons I might someday open the file again in the future, and then right at the top of the file:
- Told me that this file didn’t provide the functionality I was presumably looking for.
- Told me where I could find the functionality that I presumably actually wanted.
This sort of comment never gets written! I don’t think I’ve ever encountered such a helpful comment before, in my two decades in the game industry. I don’t remember writing this comment, and as I read it, I went from being bemused by the greeting I apparently wrote to myself, to being surprised that the comment knew exactly what I wanted to do and that this file wouldn’t provide that ability, and then downright astonished that it also pointed me to the code which would actually accomplish what I wanted.
So.. thank you, past me!
As a result of this comment, I got my feature implemented in just a few minutes, instead of taking an hour or more to figure out how to accomplish what I needed to do!
In the MMORPG Tycoon 2 codebase, an “object” is anything which gets saved and restored. A simulated player is an “object”, as is the whole system which manages simulated players. As is the map. As are all of your game editing tools, and so on. Most things in the game are “objects”, so that they can be stored in a saved game. (For the programmers in the audience, this is all a part of my C++ Reflection library, which handles saving and loading most game data, including saved game data)
What I had been searching for was a way to store an array of references to objects, when those objects are stored somewhere else inside a save game file.
For example, a player might store a reference to the world region they’re inside, but they wouldn’t actually store the world region inside themselves. They do store their weapon objects and their health objects inside themselves, but only store a reference (a ‘link’) to the region they’re inside, since many players will be inside a single region, whereas no two players share the same health object.
In the game engine, I call that reference to a shared, external object an “Object Link”. It’s common for me to use those for isolated values (such as “what region is this player in”), but it’s unusual for me to want an array of them.
I knew there was a way to do it somewhere in the game engine, but I couldn’t
remember how. So I went looking in a file which looked like it might provide
VS_PropertyObjectLinkArray.h. A file with that name
probably provides an array of object links, right?
As it happens, no, it doesn’t. But apparently me-from-the-past was prescient enough to know that someday I might go looking for that specific feature in that specific file, and left a big signpost right at the top of it, pointing me to where I could find the functionality I actually wanted.
I’m going to try to write this style of code comment again in the future; anticipating why the reader is looking at a particular piece of code, and trying to tell them what they actually want to know, in addition to documenting what’s going on in the specific piece of code.
Maybe another me-from-the-future will stumble over it and be helped, again!