How many of you write self-documenting code?

Started by
63 comments, last by SimonForsman 8 years, 9 months ago

In my opinion, code would be worlds easier to read, learn, debug, and understand if more programmers stopped using [unnecessary] abbreviations and started writing self-documenting code. Self-documenting code is...well, code that doesn't need explanation or comments to explain its function.

Here's an example from http://www.cprogramming.com/snippets/source-code/

.


/* n= positive integer e= power S= sum of integers raised in e power */

int e,n,i,S=0;

.

Is there really a reason for this sort of abbreviation? I see it all the time, everywhere, and even in learning materials. I don't really understand because as far as I know there aren't any technical limitations that would require such abbreviations to be used. On another note, " i " is later used in its usual fashion in a for-loop...but I've never seen it declared outside of the loop before.

So why not write it in a self-documenting fashion:

.


int power, positive_integer, sum_of_integers_raised_to_a_power;

.

If it's about typing long variable names, I don't really understand that notion. We're programmers, right? I'm not a professional or anything, but in the long run I believe it's worth the extra effort because when you're working with other people, no-one will have to spend time learning your coding style or searching for comments to figure out what the source is doing. Besides, most programming software offer code completion.

Sorry for little rant. I promise that I'm not just searching for petty things to talk about here. It just strikes me as a real problem. If you have throw-away variables that don't need to stick around for later use, like the following example, it's not that big a deal.

.


// This is perfectly OK! It's still easy to read!
string phrase = "Hello!";

for(int i = 0; i < phrase.size(); i++){
    cout << phrase.at(i);
}

// This, however, probably needs a comment!
string p = "Hello!";

for(int i = 0; i < p.size(); i++){
    cout << p.at(i);
}

.

How many of you write self-documenting code? If you don't always do so, what are your reasons for not using this style?

Advertisement

The idea you propose - writing fully descriptive names - is only a small part of the picture. I find sum_of_integers_raised_to_a_power particularly pedantic.

I focus mostly on isolating small functions which are descriptive by themselves and suggest by themselves an order of call.

This is not always possible; mostly because of time/effort constraints. Sometimes, it just isn't worth it.

Using single-letter identifiers is universally considered bad but for a two-liners it might be acceptable.

Previously "Krohm"

I pretty much NEVER comment anything, if code isn't readable, it doesn't need to be commented, it needs to be rewritten. Back when i was a project manager i reviewed code once in a while and if it wasn't good, i didn't ask for documentation, i asked my team to "rewrite it untill it makes perfect sense to someone reading it".

It's not only about the little details you state, none of those are self documenting code but simply common sense (it's less self documenting than stoping to purposefully encrypt your code, there is no reason to use cryptic variable names to begin with). It's all about the intent of each function being clear, the algorithm within it being expressed in a form that matches the way you'd think of it in non programming terms etc.

I mostly (pretty much only) program in C# and i admit that LINQ helps make this possible a great deal as in a lot of case code i write wouldn't be as self documenting without it and when there are 15 layers of inner loop you kinda always need to document that.

Using single-letter identifiers is universally considered bad but for a two-liners it might be acceptable.


Agreed in the majority of cases, but in come cases (loop counters, certain formulae, etc.) a single-character identifier is well established as standardised notation and will be well understood. In these instances a longer name may not aid understanding, although it's worth noting that because these are well established cases the particular usage would still qualify as self-documenting.

- Jason Astle-Adams

I'm not sure why most programmers seem to be doing this but it is a wide-spread phenoma. Robert C. Martin goes into the subject in 'Clean Code' (which in my opinion should be standarized reading material for EVERY and ALL programmers which they should re-read every one or two years).

I've ran into these issues at my current job more than once and over there it is a cultural thing. Many of my colleagues find that writing three letter variables is less work(because hey, intellisense isn't there to autocomplete it the first time you write it out) and prefer to write everything according to the hungarian misnotation. The result is a mix of incredibly unreadable code, mixed in with prefixes such as int, dbl, bln on variables are all different types(in many cases not even the type declared in the variable name) with sometimes a line of comment above each regular line of code, such as:


// loop over all the items in the list
for (var objItem in lstItems)
{
    // do something with objItem
    DoSomething(objItem);

    // Transfer into the list of processed items
    lstProcessedItems.Add(objItem);
}

What I've seen in my work is that the more people stick to basic guidelines such as the Single Responsiblity Principle(SRP) and the like the more likely they are to also write self-documenting code. The more you mix different aspects together the less easy it becomes to write code that documents itself because boundaries become fuzzy and naming isn't as exact and simple as when an object or a method does only one thing.

I do agree with single letter variables are a big no-no unless you're using Linq(Where(o => o != null) is as readable as Where(theObject => theObject != null)), loop-variables to signify index or loop values.

But in the end: since every book or tutorial seems to abbreviate things it is what you learn first. And first habits are easily becoming engrained as the norm.

I generally write self documenting code as much as I can. A lot of comments on everything just makes the code look cluttered, and I figure that if my code isn't easily readable, then one of two things is going on:

(a) My code sucks and needs to be refactored and rewritten to make more sense.

(b) It's a really complicated problem that can't really be refactored and should probably be explained with comments where necessary.

When working on contract projects my clients have always loved the way that I write clean readable code, because they really don't have time to read through a bloated mess filled with comments that explain a ton of simple get and set functions before they can figure out how to use the module I wrote. The ironic thing is that when I started taking classes to get a degree in computer science the professors knocked off a bunch of points for writing the kind of code that's actually useful in a production environment.

I do not comment my code. As mentioned before, if it needs a comments, it is probably in need of re-factoring.

But, I do document any libraries that will be used for multiple projects. APIs should be documented. But I find that I never look at comments anyway. I find out everything I need from the unit tests or simple example code.

What I find more useful is making code easy to find. For example, I've got a GUI with a bug. So I need to find that code behind the button. Where is it? I have no idea. So I do a search for a string on that panel that looks unique, and I find the panel. All my gui panels have the same public void initialize() methods that sets up the GUI. So I know right where to go. And then I find the button. The button has code like this:


private JButton getButton() {
  if( button == null ) {
     button = new JButton( "button name" );
     button.addActionListener( new ActionListener() {
        public void actionPerformed( ActionEvent e ) {
           controller.onWeirdButtonPressed();
        }
     });
  }
  return button;
}

Ah, there is is. All the code is in controller.onWeirdButtonPressed(); Nothing is passed in, nothing is assumed, and everything that needs to happen when this button is pressed is in this method. Documented code does you no good if you can't find it. biggrin.png

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

Of course.

I wouldn't want to work with anyone who doesn't.

In rare cases a comment is needed, but the comment itself should never repeat what the code already expresses.

code like "if (n<=0) /* if n is a negative number*/" is just silly.

"sum_of_integers_raised_to_a_power" is overkill though, and I think it actually makes the code less readable, the problem in that code isn't so much the names of the variables, the problem is lack of context because everything is crammed into main().

In the cppsnippets code, that code would fit in a function called something like "ExponentSeriesSum" that return the sum.

Then inside the function you could have a "sum" which would be obvious what it means. In a tight loop, n for a positive integer is ok, (standard notation) but you could keep it unsigned, then its obvious it is positive (and impossible that it is not), and keep the input sanity check outside of the function. (preferably in an aptly named function of its own)

code like "if (n<=0) /* if n is a negative number*/" is just silly.

And incorrect ;) 0 is not a negative number

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

Code should very rarely need to be commented.

High-Level Design, however, should almost always be commented.

Simple rule of thumb being dont comment the what, comment the why. Easy to see what something is doing, but you cant always determine why something is being done.

As an example, say you have a class that represents a physics object. You have a vector3 field that holds the accumulated force that needs to be applied to the velocity next intergration step, that gets zero'd at the end of each step. You can call it 'Vector3 forceAccumulated' and it is clear enough what it represents, an accumulatedForce, however you cant know the behavior and what effects it has without following references of it. So a simple comment by the declaration saying something like "accumulated force applied next integration step, zeroed at each step", lets readers know the purpose and behavior of the field that code alone cant quickly tell you.

This tends to lead to header files having lots of comments, allowing them to be used as references, where as the actual implementation files are very sparsely commented, allowing the code to be read easily without annoying comments getting in the way.

On another note, heavy use of Doxygen and its Kin are the bane of my existing when people write the super verbose comments with all the fancy tags and stuff.

This topic is closed to new replies.

Advertisement