Advertisement

How many of you write self-documenting code?

Started by July 09, 2015 12:54 PM
63 comments, last by SimonForsman 9 years, 3 months ago

I've been writing a collaborative (non-gaming) project with a colleague for about two years now, and while we agree on some things, we definitely have a clash on coding styles. I would typically write variable names perhaps 5 - 10 characters (and include a small comment descriptor explaining exactly what it is) whereas he would write the longer 'sentences' explaining what is what. So for example, I would write the following :


int i;                   // Loop counter over all particles
int Npart = 16;          // No. of gas particles in loop
float rpart[3];          // Position of current particle in loop

// Compute forces for all particles
for (i=0; i<Npart; i++) {
  rpart[0] = ...
  ...
}

whereas he would write something like


int number_of_particles = 16;

// Compute forces on all particles
for (int iparticle=0; iparticle<number_of_particles; iparticle++) {
  float position_of_current_particle[3];
  position_of_current_particle[0] = ...
  ...
}

The big problem I have with the long 'sentence' style names is that even small trivial parts of code (e.g. adding two variables together in a third summation variable) suddenly become way too long to read comfortably and I simply can't glance over the code to get an overview of what is happening because I can't even see where the variables begin and end easily (maybe using camelCase here would be help instead of snake_case??). So I end up going through some parts of his code and 'trimming' the variable names down to size so it's not so verbose. Another aspect of it that we disagree is that I declare all my variables either at the top of the subroutine (with a comment next to it) or at the beginning of the current code block (e.g. if/else or for loop) whereas he declares all variables inline just before he needs them. I guess if the code is 'self-documenting', it doesn't really matter where they are declared, but I am a bit of a neat-freak when it comes to coding so like to keep things together :-)

I prefer his version. And for the reason you said (where variables begin or end) I use CamelCase, and I always separate most operators with spaces on both sides.

CurrParticlePos[ i ] = PrevParticlePos[ i ] + WhateverElse[ ( i + 1 ) * 3 ]; // maybe no spaces around the [ operator I honestly can't remember...

I also avoid using too long formulas, I make temporary variables instead.

I also use some abbreviations, most of them are obvious for me, a habit I can change if I even have to. For example Prev, Curr, Pos, Accel, Init. Most of them is whitspread I think, but maybe I also have some specific ones too.

Oluseyi

I don't want to argue with you. I think we should agree to disagree at this point. I'd rather not derail this thread any further.

Advertisement

So just for fun I asked some gamedevs on twitter if there are comments in their released game code. Make of it what you will...

Christer Kaitila(http://www.onegameamonth.com/) - tons and tons: I'm old and forgetful so I leave reminders to my future self of the "whys".

Asher Vollmer(Threes) - the ratio of lines of code to comments is probably 500:1?

(and my favorite)

Ron Gilbert(Maniac Mansion, Monkey Island) - HAHAHAHAHAHAHAHAHHAHAHAHAHAHAHAHAHAHAHAHAHHAAAHAHAHHAHAHAHAHAHAHAHHAAHAHHAHAHAHAA

(breath) HHAAHAHHAHAHAHAHAHHAHAHAHAHAHAHAHA

I think, therefore I am. I think? - "George Carlin"
My Website: Indie Game Programming

My Twitter: https://twitter.com/indieprogram

My Book: http://amzn.com/1305076532

So just for fun I asked some gamedevs on twitter if there are comments in their released game code. Make of it what you will...

Christer Kaitila(http://www.onegameamonth.com/) - tons and tons: I'm old and forgetful so I leave reminders to my future self of the "whys".

Asher Vollmer(Threes) - the ratio of lines of code to comments is probably 500:1?

(and my favorite)

Ron Gilbert(Maniac Mansion, Monkey Island) - HAHAHAHAHAHAHAHAHHAHAHAHAHAHAHAHAHAHAHAHAHHAAAHAHAHHAHAHAHAHAHAHAHHAAHAHHAHAHAHAA

(breath) HHAAHAHHAHAHAHAHAHHAHAHAHAHAHAHAHA

Those are interesting responses. happy.png I'm not sure what to make of the last one (it's pretty hilarious though).

I'm not sure how many people do this, but I sometimes use them when I want to remind myself of the basic concept behind an algorithm. I will forget the verbatim syntax at some point if I don't look at it, but if I can remember how it works...I can rewrite the algorithm in any language. Programming is problem-solving. When you've found the solution to a problem, you should certainly document that! This probably falls into the how category and is highly reusable.

Just for fun, I opened up one of my Python game prototypes to check out the source code that I wrote many months ago. I found this comment in my animation function.

.


# Show images between the lower bound frame (start) and the upper bound frame (end)
# If the current frame is the last frame of the animation, reset it to the lower bound frame

.

That's the basic idea behind looping an animation. Using that basic idea, I've created syntactically different but functionally identical animations in Python, C++, and Actionscript 3. It might seem like common sense, but many algorithms do when we finally figure them out.

I mostly write code in C#, and use the hell out of ReSharper. I write the code, then I aggressively extract method, introduce constants and rename things until it is pretty hard not to understand what is happening. I'm trying to get better at pulling functionality out into smaller classes that are more like functional modules, as I'm trying to get into more of a unit-testing mindset. Also starting to use more of things like code contracts and the JetBrains assertion attributes, which generate warnings in ReSharper if you are potentially passing an invalid parameter.

Code-level comments don't work well with this style, because they get out of sync so quickly. If a self-contained block of code more than four or five lines needs a comment explaining what it does, a function should probably be extracted.

Xml-doc comments can be useful, where they are documenting invariants or side-effects of a particular function, exceptions explicitly thrown, etc. Quite often if things need comments explaining what they are, they probably need a better name.

I have worked with some people that pick absolutely bat-shit names for things. Simple nouns in foreign languages, when everyone on the team is a native English speaker, including the namer. Partially abbreviated names that don't bear any relation to what they do. Single-letter LINQ lambda values that aren't abbreviations of the object type the collection consists of.

What I find that I just cannot tolerate is when no effort is made to clean up code once it is working and remove the cruft that accumulates as you are working something out. Temporary variables like tempXXX, myYYY, foo, etc. Big chunks of commented-out dead code, comments like // hope this works... Chunks of identical code that could be trivially refactored into helper functions, or at least parameterized, so that you can make a change in one place instead of five (and inevitably missing the sixth). Or random assemblies or NuGet packages that get included unnecessarily.

</rant>

Eric Richards

SlimDX tutorials - http://www.richardssoftware.net/

Twitter - @EricRichards22

Single-letter LINQ lambda values that aren't abbreviations of the object type the collection consists of.

Actually this is often pretty ok in my book, it depends on the number of transformations you're doing and the context, in a small query you can perfectly leave out the variable name and substitute it for a single letter all along as most of the intent in naming is already there in the operators.

Advertisement

Single-letter LINQ lambda values that aren't abbreviations of the object type the collection consists of.

Actually this is often pretty ok in my book, it depends on the number of transformations you're doing and the context, in a small query you can perfectly leave out the variable name and substitute it for a single letter all along as most of the intent in naming is already there in the operators.

Perhaps I wasn't clear, but I've seen things like:


using (var db = new LinqToSqlContext()){
    return db.Items.Select(z=>z.ItemID).ToList();
}

Why not pick i here, if Items is some sort of ICollection<T>, where T: Item?

Eric Richards

SlimDX tutorials - http://www.richardssoftware.net/

Twitter - @EricRichards22

I prefer his version. And for the reason you said (where variables begin or end) I use CamelCase, and I always separate most operators with spaces on both sides.

CurrParticlePos[ i ] = PrevParticlePos[ i ] + WhateverElse[ ( i + 1 ) * 3 ]; // maybe no spaces around the [ operator I honestly can't remember...

I also avoid using too long formulas, I make temporary variables instead.

I also use some abbreviations, most of them are obvious for me, a habit I can change if I even have to. For example Prev, Curr, Pos, Accel, Init. Most of them is whitspread I think, but maybe I also have some specific ones too.

I have to say, I would be happy with your style also. It's a reasonable balance between detail and conciseness, and actually in more complex parts of the code where there are more variables, I also write variables a bit more like this. The thing I don't do is the spaces between all operators. I actually use spaces similar to how you would write and use them in mathematical formulas. So for example, a formula of the form 'r = r0 + vt', I would also write in code as 'r = r0 + v*t', so the closeness of the variables is related to the order/precedence of the operators. So, in your above example, I would write 'WhateverElse[(i + 1)*3]'. But of course, in a collaboration project, there has to be some consensus and I've reached some kind of understanding with my collaborator so we know what kind of style we should aim towards! :-)

Xml-doc comments can be useful, where they are documenting invariants or side-effects of a particular function, exceptions explicitly thrown, etc. Quite often if things need comments explaining what they are, they probably need a better name.

Personally i use xml-doc / doxygen / javadoc comments almost exclusively for generating external API documentation on the build-server and the generated docs tend to look quite a bit nicer if you also include obvious things such as a short natural language description of the method.

i also set my IDE to minimize those comments by default and only use a small portion of them for tooltips. (most of those comments are written for the tools, not for humans reading the code)

[size="1"]I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!

Single-letter LINQ lambda values that aren't abbreviations of the object type the collection consists of.

Actually this is often pretty ok in my book, it depends on the number of transformations you're doing and the context, in a small query you can perfectly leave out the variable name and substitute it for a single letter all along as most of the intent in naming is already there in the operators.

Perhaps I wasn't clear, but I've seen things like:


using (var db = new LinqToSqlContext()){
    return db.Items.Select(z=>z.ItemID).ToList();
}

Why not pick i here, if Items is some sort of ICollection<T>, where T: Item?

I wouldn't pick z but i don't see any issue with it, it's very readable as the key items here are Items and Select, you're clearing selecting the property ItemID on each one of Items, how you name the inner variable is fairly insignificant here because of the shortness of the query (i would've named it "item" instead of "z", but i still don't feel it affects the readability at all, it would be different in a complex multi level query where idenfitiers are easy to confuse however)

This topic is closed to new replies.

Advertisement