Things are pretty hectic here in the LiveCode office at the moment. Not only are there 3 (yes three) separate versions of LiveCode out there for testing (6.6, 6.7 and 7.0), each with there own set of new features, there are also several projects being worked on that are still in their infancy. These new projects will form the basis of future LiveCode releases. It’s tricky to decide when to end development on one project and begin working on another. That’s often why as developers we find ourselves working on several things at any one time.
As we’re preparing to draw a line under the 6.5/6.6 cycle (with the release of LiveCode 6.6.2 – naturally we’ll still be fixing any bugs that crop up in these versions), I find myself doing a lot of debugging and sifting through old sections of code. And this got me thinking about coding style and specifically how we comment code. Each developer appears to have their own particular way of doing things. I’m trying to decide which I prefer. Here are a few that I have come across. What type are you?
The read the source commenter
Or in other words, the coder who views comments as optional. This coder takes the opinion that all the information you need is contained within the source itself. In reality they’re just lazy. I think I’m allowed to write this: I’m very much of this type.
For the most part, I actually don’t mind this style. I often prefer to work through the code line by line, figuring out what it does and how it all fits together as I go. As long the code is well written and I have a grasp on roughly how the given component works, it usually works out okay.
But there are some pitfalls. How many times have you found yourself in this position? You come across a line of code that you have no idea what it does or even why it’s there. What you do know is that if you remove it, it fixes a bug that you’ve spent hours tracing down. What you don’t know is the impact of removing the line. Will it pass without incident or will computers around the world suddenly start catching fire? See, a little explanation here wouldn’t go amiss.
So some commenting is useful. But how much?
The essay writer
This type of coder makes the assumption that everyone reading their code is an idiot. Often, the lines of comments far outnumber the lines of code. I once heard someone say that you should write your code with the intention that your gran should be able to understand it.
And here’s my problem with this style. I’m not an idiot (or at least I like to think not). And I’m certainly not your gran.
Working on a project like LiveCode, which has a very mature code base, you find that a lot of your time is spent poring over code, trying to figure out what it does and how it works in order to fix bugs. You want to do this as quickly and efficiently as possible. However, there’s nothing worse than when going to fix a bug, finding yourself faced with a swathe of green. It makes you feel like that to even begin contemplating fixing the issue you need to spend the next few hours sitting down in a darkened room getting into the author’s mindset. Only then will you have reached a point where you will be able to understand and comprehend the complexity of the code that follows.
In reality, when fixing a bug, you want to do it as efficiently as possible. You don’t need to have a complete grasp on the full inner workings of the system. You just need to know enough to understand what the issue is and know that your fix won’t cause any further issues.
My opinion is that more significant chunks of technical documentation should be kept separate from the source code itself. If you find yourself having to write a lot of comments to explain your code, maybe the problem is with the code itself. Try and write clean and clear code. Often code that is well designed and thought out requires fewer comments and is much easier for third parties to understand.
The redundant commenter
Ahh, the redundant commenter. The only thing that annoys me more than the essay writer is the redundant commenter. I’m sure that this coder has good intentions at heart. It’s just they appear not to be able to put these good intentions to use. Take for example, the following lines of code:
-- Repeat through each person in the address list repeat for each line tPerson in tAddressList . . . end repeat
As I’m sure you can see, the comment above is less than useless. Consider this: You’ve spent what feels like hours tracing down a bug, get increasingly more and more frustrated. At this point you would take any minor hint or guidance. Just a little something that might point you in the right direction. You spot a line of green. You think this is it, this is the comment that is going to make everything clear. You read it. You collapse in a heap of disappointment. At this point, I usually get up from my desk, go home and swear I’m never going to look at a computer again.
That may be an exaggeration, but padding out your code with redundant comments isn’t really helpful. It’s commenting for the sake of commenting. If a line of code is self explanatory, there’s no need to comment.
Finding a balance
So, comments are needed. But too much can be counter productive. So what’s a good balance? I generally try to stick to the following rules. Use descriptive names for your variables and handlers. Don’t be scared of verbosity, but don’t go overboard.
- Use a prefix system for variables (e.g. local variables, parameters, globals, script variables etc).
- For each handler, write a sentence or two describing what the handler does (not how), including a run-down of parameters it takes, what it returns and any errors it throws. If you can’t do this in a few sentences, that suggests that you may need to rethink your abstraction.
- Comment on any blocks of code that are doing something subtle or that is not immediately obvious.
- Attempt to make the code you write as clear and simple as possible. After you’ve got a block of code working, if you think you can rewrite it in a cleaner way, then do so.
- If you are working on a larger project that requires further description, do this in a separate document.
These, though, are just my thoughts and opinions that have been formed over years of looking at other people’s code. I imagine that if you ever had to work through some of my code, you’d no doubt be of the opinion that I’m full of nonsense and doing it all wrong.
11 comments
Join the conversationPaul Dupuis - April 11, 2014
— Yes
Mark Smith - April 11, 2014
I very much agree with what you’ve described but i have another category, the code archiving commentor. Whenever they change any code they make a copy as comments all of the code as it was before and leave it in situ. Very annoying and making code very unreadable.
Mikey - April 11, 2014
I would tend to disagree with you, here, Mark. When something comes up later, it is really important that someone is able to reconstruct what is going on in the code. If I can’t do that via some other archive mechanism, my only defense is to do it in the code. I should mark the version number, and what it was before – somewhere, even if it’s at the end of the line that was changed.
Mark Smith - April 14, 2014
In it’s simplest form I agree but I have seen commented code running for hundreds of lines with the working code interspersed with it. If I said 1,000 lines of code and only 100 of it “live” then it is too much. When the version works, is on release and has moved on several versions, it needs a clear out not simply added too.
If only it was something I did not see and something I did not hear developers complain about regularly.
Mikey - April 11, 2014
Starting at the last:
• Prefixes are for folks who can’t find the line that says GLOBAL or the line that says LOCAL, or the line that begins with “on” or “function”. There are very few IDE’s that I’ve ever worked with where prefixes are useful (but they do exist)
• The description of the handler is a good idea, but IMHO if it isn’t even simpler, the handler is too complex and should be broken into smaller ones. One CS professor once said that if a section of code is longer than a page, you have a problem. I certainly don’t go that far, but if a handler name isn’t enough, and the parameter list isn’t enough, it’s time to fix it.
• Comment blocks IMHO should go even further than describing the subtle. The main blocks of a handler should be marked with what they do, so someone can quickly find what’s going on and skip the stuff that doesn’t matter. To help with that, I’ve taken to using some tagging to mark the beginning and the end of those blocks, and then surrounding them with 3-5 lines of whitespace.
#
bunchOfCode
#
• Separate documents are death because separate documents will invariably become lost. Much of the source we have is OLD. The rest of it will become old. Add an extra card to a project, or a substack, etc. and put everything in there, please. I can’t tell you the number of times I have built some component and eventually either lost the source or the documentation for it. It happens. It happens far too often. If the method you are using does not survive the test of time and you pulling a too-much-gin-too-early-in-the-day, or relies on some service that might not even exist in a few years, or you might grow out of in a few years, you need to think of a better way.
Structures should be marked, because we’ve all accidentally trashed and end if, or end repeat, or an else, or something else.
if x>y then
whatever
else if x=y then
whatever2
else # xy
repeat with i = 1 to the number of cards in this stack
yaddaYaddaYadda
end repeat # with i = 1 to the number of cards in this stack
You don’t have to assume that the person who follows you is your gram – although, thanks to LC’s syntax, that might be possible, but you SHOULD assume that you will have forgotten most of what you’ve learned about the code you’re looking at at some point in the future when you look at it again. So if you print out the code, all 50 or 100 pages of it, and you write something on the paper when you read it, that should be embedded in the comments in the code for the next time, so you don’t do it again.
If you are implementing some algorithm (maybe Boyer-Moore), TELL ME THAT. If you are implementing some variation on that, it’s even more important that you do – Boyer-Moore is different than Boyer-Moore-Sunday, and Boyer-Moore-Sunday is not Boyer-Moore-Sunday-Laveaux-Kerner, and when I’m trying to track something down, it’s important that I know a) that you implemented the one you meant to implement and b) that I am able to discover what the vagaries, subtleties, and potential issues are with the one you implemented.
We just went through this with Gugliermo’s Dropbox library a few months ago, when a third and a fourth person started working on the code, but it didn’t get marked, and something started working differently than it had before in an obscure situation.
More comments are far better than fewer because…the IDE makes it easy to ignore them or skip them.
Mikey - April 11, 2014
Unfortunately, some of what I was trying to demonstrate was eaten.
Much of the spacing was lost, as were some of the symbols, so let’s see if faking the HTML works
When marking a block,
#walk records, remove duplicates
bunchOfCode
#/walk the records, remove duplicates
Ralph DiMola - April 11, 2014
Michael,
Could not agree more. I especially find myself getting into these pitfalls when submitting a test stack for bug reporting. As I excise chunks of code to make the bug reporting code simpler for RR, I lose comments and handler titles. I will endever not to do this is the future. I had not used variable prefixes in the past. I now use prefixes and find them very useful.
Mikey - April 11, 2014
One other thing that drives me bananas – prefixes for effective variable types, and typing every single variable. Folks who are used to strongly-typed languages seem to be the most frequent culprits, here. Even better than an implicitly-typed language, you have a context-sensitively-typed language. It’s a good thing. You don’t have to have a lot of extra code that does nothing more than type-coercions so you can output your number in the middle of a string. I get the “but I can’t type to save my life, and these catch my typos”. Testing your code does, too, and it’s a lot fewer keystrokes that could be better used writing better comments.
Dar - April 11, 2014
I tend to write short handlers and comment those rather than the code within. When I have to have longer code, I break things up into sections with commented headers. I do a few end of line comments such as “bug workaround” or “dar added this 4/4/14”. I do some other end of line comments but I don’t remember why.
I also comment local variables and array types.
I try to keep my essays short, using crisp summaries with buzzwords or references. But, I wouldn’t mind adding some math, tables or graphs. I need to learn here.
I see limitations in my comments when I go back to maintain code much later. Usually what I want there is a good description of the handler and a good description of complex types.
Most of what I write is for others, so I work hard to adapt to customer guidelines. In some cases, customers like my style and adapt to that.
Often, when it looks like lots of comments are needed, it is a sign to break things into meaningful pieces or clean up the design.
jacque - April 11, 2014
I think I’m a middle of the road commenter. I use descriptive handler and variable names, I supply a 1-2 line description of what the handler does and a short description of either the variable content and/or where its value was set, and a short list of the handlers that call the current one so that I can trace backwards later without the debugger. Usually those comments take only a few lines. In the body of the handler I only comment lines that aren’t clear on their own; for example, “– only runs when called by handler x” or “– var can be empty” to remind me why that line of script exists.
For years, I thought variable prefixes were stupid and useless until I had to work on some code that used them. The advantage became obvious and now I use them too. I am quite capable of finding the “global” or “local” declarations in a script, but if a prefix exists I don’t even have to look. I know instantly that a variable that begins with “t” has its value set somewhere in the current handler. If it begins with “l” or “s” I know I don’t need to look for it outside the current script. It’s a big time saver and I have become a convert.
SparkOut - April 12, 2014
I think comments are important, and the commenting style depends on the expected audience. I can’t think of a time where another coder has reviewed any of my work – save sample explanations on the forum – and so I have habitually styled comments like I am writing for Gran (ie the client) where source code is supplied. I think this is important for the trust and confidence factor for the client, and actually promotes repeat work.
I am also guilty of skimming comments in quick and dirty closed code and feeling like it doesn’t matter – until that time months later I want to reuse a technique or adapt something.