Excuse Me, You Call This Clear Source Code?

Two years back, someone asked me to review some Inform 7 code and make some bugfixes. I opened the source in question, updated it to the latest version of Inform, cracked my knuckles, and loaded up the bug list.

I read the first bug.

I stared at the source code.

I looked at the bug again.

I looked back at the source.

Then I said a few choice phrases in the kind of language I don’t use in front of my father. Because no matter how readable the code was, I had no idea what was causing this bug or how to go about safely fixing it.

I wouldn’t be so hard on the coder, except that she was me.

Why I didn’t comment (and why I should have)

When Caelyn and I were writing One Eye Open, I didn’t comment my code. At all. Inform 7 looked like English, so I figured I didn’t need to. Besides, no one was ever going to look at it except me and Caelyn, and I was the primary coder.

When you’re in the thick of a project, you understand how everything fits together, and it’s even better if you’re coding solo. You know the design, large scale and small, and you understand the logic driving that design. In essence, the code is commented – but for you, and only you. The comments are living in your head, and if you’re the only one working on it, then you don’t need to explain your code to anyone else.

But Future You might have an opinion or two about that decision. Future Me certainly did.

My code specialty is kludging. If all I have is a hammer, then I can use it as a screwdriver, a lever, a s’more stick, a ruler, a bottle opener, a panini press, or whatever else the job calls for, and I’ll get the project done… somehow. But my hammer-centric results aren’t as pretty as the results of using the proper tools.

Caelyn and I released One Eye Open in 2010. I’d worked with Inform 7 before, but OEO was my first full game, so I was still learning how the language works. I wouldn’t say the whole game is a kludge, but… I’m not going to pass around the source code, either.

On a line-by-line basis, it’s easy enough to read the OEO source. But figuring out how it all fits together… or why I made some of the decisions I made… that’s another matter entirely. And if I don’t understand my code well enough to see why I thought something was a good idea, then a well-intentioned fix might introduce more bugs than it resolves.

I have a lot more tools in my toolbox now, and my s’mores are much prettier for it. But the OEO comments that used to live in my head are long gone, and the way I write I7 code in 2015 is not the way I wrote it in 2010. If I’d commented my code in the first place, the OEO fix process would be a lot faster and a lot less painful.

Many people (such as Jeff Atwood) have opined that sufficiently well-written code should not need comments, as the first goal should be to optimize the readability of code. I do not disagree with this goal, but I find that it’s tricky to judge the clarity of my own code. Having burned myself in the past, I would rather overcomment than undercomment.

Useful comments

Design summaries – how puzzles and areas were set up.
It’s surprisingly easy to forget a puzzle solution, especially when multiple steps are involved.

Complex activities and rulebook changes – what the purpose of the code is.
It may be easy to see what the code does without understanding why it was necessary or desirable. For example, the current build of “Rainbows and Dance Parties!” includes extensive alterations to how player commands are processed. These changes are bugfixes to resolve disambiguation problems, but it’s not necessarily obvious from the code why the command to go inside should always be rejected and replaced with “fly to Indiana”.

Extension hooks – how other people should use the code.
The most widely distributed pieces of Inform 7 source are extensions¬† (Inform 7 libraries, essentially). If you’re writing a piece of code for other people, then it’s important to document how they should use the code, with particular notice to whatever variables, activities, kinds, etc. are important for an outside user.

Future plans – things that need to be added or changed.
If I leave these notes in a notebook, I’m going to forget about them. If I put a big splashy ***CONTINUE note in a comment, there’s no way I’ll forget. (“Todo” is more traditional, but mine are easier to spot at a glance.)

Potentially useful comments

Architecture notes – how the code is organized.
My source structure varies significantly by project. The headers (book, part, chapter, etc) are helpful for navigating, but if I have any doubts about whether related code is easy to find, then I include a comment about where to find related code. (For example, if NPCs are grouped together separately from rooms, then I’ll include a comment near each occupied room about which NPCs are in it.)

Code summary – what the code actually does, high level.
Inform 7 looks like English, so it’s not unreasonable to expect the code to be fairly readable. But it has a whole lot of internal jargon, and not everyone has inhaled the entire manual. (What’s the difference between an action, an activity, a rule, and a rulebook?) If I’m doing something in an unusual way (linking rooms via a table of room exits, for example) then I often include a quick summary of how the code works.

Sporadically useful comments

Code explanation – what the code actually does, low level.
Asserting that this can be useful is a somewhat controversial position. Many new coders hear that commenting their code is important, but they’re not entirely sure what comments to make, so they write their code twice (once in code, once in the comments). This is rarely a good use of time, and it’s obnoxious to anyone else reading the code.

But when you’re still learning a language, it can be tricky to understand just what the code is doing, and it’s better to have overly commented code that you understand than uncommented code that bewilders you. In that case, leaving comments can ensure that your comprehension level stays high. For example, my understanding of Inform 6 is quite terrible, so I comment all my I6 inclusions in detail to save myself from confusion later.

TL:DR; As a best practice, comment your code

If you’re working alone, then you don’t have to comment your code. No one will complain if you don’t. It will save you time in the short run. Your files will be more concise.

But by commenting your code, you can crystallize your understanding of the project and pass it along to everyone else who reads it, which can be the difference between a three-line change and a painful slog through your entire code base.

Future collaborators will appreciate it, even (especially!) if they’re you.


Thank you to everyone supporting Sibyl Moon through Patreon!
If this post was useful or interesting, please consider becoming a patron.

Bookmark the permalink.

11 Comments

  1. Thanks, this is one of the most phenomenally helpful posts I’ve read for a while. I’m in the middle of a big Inform 7 project at the moment, and although we all know we should comment our code; actually having some ideas about what sort of comments might be useful later on is priceless.

  2. I have to say I always find Inform 7 code (for a whole game of any decent size) hard to follow if it’s not mine, whether or not it’s commented. Though obviously, commented is infinitely better!

    My opinion is that this is because the programmer has tremendous flexibility in how they can arrange their Inform 7 source code, and related mechanisms can be spread out through more disparate blobs of code than they would in some other languages. So the Inform 7 programmer arranges their code in an idiosyncratic way that’s good for them. In only two outings, they might have come up with a scheme that suits them perfectly, but that scheme might be entirely unlike how the next person would arrange it. At that point, the comments are going to be lifesavers.

    I feel like this is idiosyncratic to Inform, and a strength in obvious areas and a weakness in other obvious areas. But I see it as part of the nature of the language.

    • I think you’re right about the tremendous flexibility in style leading to more-difficult-to-read code. I wonder occasionally whether I7 would benefit from style conventions, and then I throw the idea out again, because there are so few of us working in groups that it seems better for everyone to just develop their own style.

  3. I think these are observations true of any one-person or small development team. Unless writing throwaway code, one should always comment it for the future. For some of us, it doesn’t need years before our old code becomes ineligible.

  4. Using headings and subheadings is crucial in a longer work. My install of Inform currently doesn’t have the shortcut arrows to click on with the error messages, so finding where a problem originates is a matter of searchboxing, or using the sectioned table of contents Inform makes with your headings. It is much easier to examine or search in a receipt-sized tear off of code (I7 on Mac actually makes it look like a ripped out strip!) than the whole source I usually section every room, and sub-section anything really important in a room.

    Also naming new rules something memorable is super-helpful–besides knowing what exactly triggered an output with the RULES ON debug, it reminds future-you what is happening, and also searching the source as above. “Check grilling (this is the use hammer as panini-press rule):” will be easier to find than one of potentially similar but unnamed “Check grilling” rules.

    • 100% agree on the benefit of naming rules cleanly!

      The sectioned table of contents is helpful, but I never seem to be on the correct “zoom”. Either I want to be closer in, or farther out, and backing out to go in at a different depth is a little time consuming.

  5. Thanks for the reminder about using the section headings and so forth. I do comment when I put in textual placeholders (since my instinct is often to get the mechanicsy bits working first), or about mechanicsy stuff that isn’t working yet or that I want to implement. Thinking about it, though, I’m not sure whether I wouldn’t prefer to have a separate document to, well, document the more high-level structural stuff? Just for the sake of being able to make, like, flowcharts and all that jazz. Do you ever use that kind of graphical documentation for yourself?

    • I do sometimes make flowcharts, but for game flow rather than code structure. So I leave them in my notebook and abandon them once they’ve been converted into code.

      I’m not a fan of separate documents, but I know some people are.

  6. Personally I like to have a separate design document for the high level stuff. For me in-code comments are reserved for special cases where the code is extra complex or difficult to reason through. As Jeff Atwood hints at, the need to explain your code can act as a red-flag that perhaps there is a better, less complex way to do something. So it becomes an opportunity to refactor. Inevitably, comments get out of sync with the code, thus the become untrustworthy, then at that point you have to revert to reading the code anyway.

    You have some good use cases for commenting your code, as long as they are kept in sync with current code and design and well maintained comments can often shortcut the understanding of code, especially if you are unfamiliar or trying to learn a language.

    • I know how important refactoring code can be, but I’m only slowly coming to grips with the idea that refactoring != screwing up. It always makes me feel like I should have coded it differently in the first place.

Leave a Reply

Your email address will not be published. Required fields are marked *