Commenting Scheme on Large Projects

Pages: 12
I didn't mean to imply my rule is a good rule. I probably should have a fixed limit.
The width of my laptop screen lets me go about 140 characters wide so I should probably stay under 132.

Eighty is too short for me like you say with namespaces and classes, and also with a lot of the library functions I use.

closed account (o1vk4iN6)
Yah 80 is way too little, you should think about getting a bigger screen maybe :P. Looking at my most recent project the longest line I have is 130 characters but that's for a class constructor that has 10 arguments. I have to say though looking at it now I don't know why I have it formatted the first way it just looks so awful... It doesn't increase line count as much as I thought. My longest line is now 85 characters lol.

http://i.imgur.com/HCfDH.png

Constructor with 10 arguments? That seems like a lot
closed account (o1vk4iN6)
Yah, it is only initialized using a macro though so it isn't like I deal with it a lot.
What is that? 20 space indentations?!?! or 3 tabs (8 spaces per)? Please don't tell me you indent every line like that.
Yah, it is only initialized using a macro though so it isn't like I deal with it a lot.


Gonna say, that sounds pretty unwieldy to deal with often. Though if I remember right Win32 has some constructors that are like that...
Why would you initialise it with a macro? Why not just overload the constructor?
closed account (o1vk4iN6)
@chrisname
Well I use macro to get a string literal of the class name as well as defining some repetitive functions. Perhaps initialise wasn't the right word, 'declaring' would better describe it, all parameters are being used.

@Volatile Pulse
Lol it does seem like a lot of wasted space doesn't it. It isn't every line but perhaps some more context is needed:

http://i.imgur.com/6swu6.png

I just like how everything is aligned in such a way which is why I don't like using tab as 3-4 spaces, yes you save characters but hitting tab 7 or 8 more times is more wasteful without saving that many more characters.
Last edited on
@xerzi
Oh, I get it, it's for RTTI. Sorry, I didn't actually read the code.
Damn this internet connection!

Anyways, I'm not a fan of "block" style indentation. It's common amongst C# programmers, and WinAPI, well all MS code that I've seen, really.

I prefer fixed indentations. I'm curious though, what do your definitions look like? Initializer list indentation? Mine:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
template<class T>
vp::list<T>::list() :
   firstNode(NULL), lastNode(NULL), mSize(0) {}

template<class T>
vp::list<T>::list(unsigned n, const_reference value) :
   firstNode(NULL), lastNode(NULL), mSize(0) {
   for (unsigned i = 0; i < n; i ++)
      push_back(value);
}

template<class T>
vp::list<T>::list(list<T>& x) :
   firstNode(NULL), lastNode(NULL), mSize(0) {
   for (auto it : x)
      push_back(it);
}


It's ugly, I don't like it column 1 aligned, I don't like it aligned with line 1 of the definition, or passed that for that fact, and I didn't want it on the same line as the header or with the declarations, mainly because it'd exceed the 80 character width. I might consider putting the initializers under the declarations to have them "neat".

I prefer my style over yours so that if I need to (I rarely do), I can put comments to the right. If I ever do, it's extremely brief, usually has an approx value of the variable, or expression, or it's a math equation to understand the code. I prefer to put all of my comments on the line above any statement so it's perfectly clear and I have less limits on the width.
Last edited on
If it fits on the same line as the function header, then I put it there; if it fits on the next line without being split up, then I put it there; otherwise, I just put it on the same line as the function header and then split it up.

Also, what do you mean by "block notation"? Do you indent your code in "LISP style"? Like this:
1
2
3
4
5
6
int function()
    { if (condition)
      { do_something();
        if (another_condition)
            { do_something_else();
              do_a_third_thing(); } } }
Last edited on
closed account (o1vk4iN6)
Well I have a widescreen 1920x1080 monitor so I can probably add another 200 characters and it won't be off the screen, so if I do need to add a comment there's more then enough room for one. I know what you mean though, I use to always run on my laptop which is 1280x800 and it is a pain to scroll left/right when you don't have to. Screens are becoming more and more high res now though even 1920x1080 is looking small in comparison.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<class T>
vp::list<T>::list() : firstNode( NULL ), lastNode( NULL ), mSize( 0 ) { }

template<class T>
vp::list<T>::list( unsigned n, const_reference value )
        : firstNode( NULL ), lastNode( NULL ), mSize( 0 )
{
        for( unsigned i = 0; i < n; i++ ) {
                this->push_back( value );
        }
}

template<class T>
vp::list<T>::list( list<T>& x )
        : firstNode( NULL ), lastNode( NULL ), mSize( 0 )
{
        for ( auto it : x ) {
                this->push_back( it );
        }
}


That's how I would format your examples. I only use block indentation for functions and classes, everything else I use the same thing as you. I think it looks better then having code directly after the function and initializer list, just looks like a big mess.
Last edited on
I can't decide which of these ways I like to do it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<class T>
vp::list<T>::list(unsigned n, const_reference value) :
                  firstNode(NULL), 
                  lastNode(NULL), 
                  mSize(0) 
{
   for (unsigned i = 0; i < n; i ++)
      push_back(value);
}

///////

template<class T>
vp::list<T>::list(unsigned n, const_reference value) :  firstNode(NULL), 
                                                        lastNode(NULL), 
                                                        mSize(0) 
{
   for (unsigned i = 0; i < n; i ++)
      push_back(value);
}

I was proposing a style from this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
namespace vp {
   template<class T>
   class list {
      private:
         struct node {
            node();
            node(T Value, node *pnode);
            node(T Value, node *Prev, node *Next);
            ~node();

// ...
template<class T>
vp::list<T>::node::node() : value(T()), prev(NULL), next(NULL) {}

template<class T>
vp::list<T>::node::node(T Value, node *pnode) :
   value(Value), prev(pnode->prev), next(pnode) {
   pnode->prev = this;

   if (prev)
      prev->next = this;
}

template<class T>
vp::list<T>::node::node(T Value, node *Prev, node *Next) :
   value(Value), prev(Prev), next(Next) {
   if (prev)
      prev->next = this;

   if (next)
      next->prev = this;
}


To this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
namespace vp {
   template<class T>
   class list {
      private:
         struct node {
            node() :
               value(T()), prev(NULL), next(NULL);
            node(T Value, node *pnode) :
               value(Value), prev(pnode->prev), next(pnode);
            node(T Value, node *Prev, node *Next) :
               value(Value), prev(Prev), next(Next);
            ~node();

// ...
template<class T>
vp::list<T>::node::node() {}

template<class T>
vp::list<T>::node::node(T Value, node *pnode) {
   pnode->prev = this;

   if (prev)
      prev->next = this;
}

template<class T>
vp::list<T>::node::node(T Value, node *Prev, node *Next) {
   if (prev)
      prev->next = this;

   if (next)
      next->prev = this;
}


Everything still get's defined separately from the declaration of the class members, so you can have all definitions in a source file (except with templates) and all declarations and initializations in the header file. I haven't tested it yet, but I'm sure this compiles (I believe it's the way I had it before). The only thing I don't like about this method is that if you change the way a ctor behaves and need to modify the way a member is initialized, you need to edit the header file.

chrisname wrote:
Also, what do you mean by "block notation"? Do you indent your code in "LISP style"? Like this:

No, I meant like how variable data types line up in a column and the variable names in another column. This is typical in the documentation on MSDN, all MS source code I've ever seen, and popular amongst senior coders (referring to age, not experience). I'm not sure if it originated from languages that didn't allow multiple declarations on a single line, or what, but I don't exactly like it. It also tends to promote declaring ALL variables at the beginning of the function, another thing I had, and isn't ideal for a lot of functions (optimization wise).

I prefer to declare my variables when and where I need them, no where else. I like to keep all ints, doubles, strings, on one line so I can easily see the data type and all variables associated with them.

xerzi wrote:
everything else I use the same thing as you.

Yes, the only major differences I notice is the indentation is larger, again limited screen space so 3 space indentation is my preference, and that you pad your parenthesis. I like my variables and arguments, and whatever else, slammed up tight. I like how you keep a space between the if/for statements (if (...)). Some people still think that those are function calls, hidden deep within some implementation of C.

xerzi wrote:
Screens are becoming more and more high res now though even 1920x1080 is looking small in comparison.

Yes, I agree with you, my monitor I have supports over 2000x1600 (I don't know the numbers exactly) but due to the distance I sit away from it, the text becomes too hard to read. When my desktop is working properly, I'm in heaven when I open up C::B. I love the massive amounts of space I have to type, and from time to time, I'll plug my laptop into the monitor via the VGA...yeah, the laptop was made last year (March 2011 if I'm not mistaken) and still has only a VGA display port...

iseeplusplus wrote:
I can't decide which of these ways I like to do it.

If it were up to me, I wouldn't pick any (duh!), but I'd lean more towards the first one if I was worried about width limitations (which I am), or the second one if not. The second one looks cleaner, but you run into the issue that if you have a multiple parameter ctor, your initializer list could be pretty far out there.

Obviously, we can debate about what looks best, but I've seen some really clean code that wasn't very effecient. I've also seen some hideous looking code that was, once you could understand it, a gem amongst codes. I believe it really comes down to readability. It'd be nice if there was a standard way to format code, but then I believe a lot of very good programmers would get upset since it's non conformant (and more than likely my style wouldn't be selected so I'd be upset as well).

I've also narrowed it down to trying to be as concise as possible, don't over do for loops, like I have in this very program, keep a constant pattern throughout your entire code, and always remember to use things like AStyle to help ;)
Volatile Pulse wrote:
No, I meant like how variable data types line up in a column and the variable names in another column. This is typical in the documentation on MSDN, all MS source code I've ever seen, and popular amongst senior coders (referring to age, not experience). I'm not sure if it originated from languages that didn't allow multiple declarations on a single line, or what, but I don't exactly like it. It also tends to promote declaring ALL variables at the beginning of the function, another thing I had, and isn't ideal for a lot of functions (optimization wise).

I prefer to declare my variables when and where I need them, no where else. I like to keep all ints, doubles, strings, on one line so I can easily see the data type and all variables associated with them.

Oh, right, I'm with you. Except that I declare my variables at the start of the outermost scope that they need to be visible in (so, if they need to be visible through an entire function, I'll declare them at the start of the function; if they only need to be visible within a compound statement, I'll declare them at the start of the compound statement). IMO code that declares new variables partway through a block is harder to follow. I find it easier when all the variables are declared at the top of the block. It's also partly a habit from C, where you had to declare variables at the top of the scope (but like I said, I find that more readable anyway, so I scarcely take advantage of the ability of other languages to declare them later).

I also move variable declarations out of loops and into conditional blocks as much as possible so that the program doesn't have to do quite as many stack operations. I'm sure the compiler does that automatically, but since it doesn't impinge on readability and takes next-to-no effort, I do it manually anyway.
chrisname wrote:
(so, if they need to be visible through an entire function, I'll declare them at the start of the function; if they only need to be visible within a compound statement, I'll declare them at the start of the compound statement)

The reason I don't do this is because of conditional return statements at the beginning of functions to test validity of a parameter. Take this for example:
1
2
3
4
5
void foo(int bar) {
   if (bar <= 0)
      return;
   // ...
}


All variables that would have been declared before that conditional would have been wasted memory if bar was, let's say, 0. A lot of functions will do their error checking first, then create variables to work with. That alone is one of the reasons that I don't declare all of my variables together unless I know that function absolutely will use it.

chrisname wrote:
I also move variable declarations out of loops and into conditional blocks as much as possible so that the program doesn't have to do quite as many stack operations. I'm sure the compiler does that automatically, but since it doesn't impinge on readability and takes next-to-no effort, I do it manually anyway.


I'm the complete opposite. There are a few times when I pull the declaration of a variable out, but if it's several nested for statements, I prefer to leave the variables there. Yes, there is going to be a few more variables thrown on the stack during every iteration, but that is almost negligible with ints or other small data types. When we're talking about large objects (let's say a wxFrame object), I'll most certainly pull that out. I feel that declaring int i, j, k, l, ...; is ridiculous unless you're going for the most optimized code possible.

That's to say, though, that if I know my scope of my variables ahead of time (i will be created and destroyed 10+ times over 10 for loops), I will declare it ahead of time. I will also look into creating a static variable in loop 0, and see if it still needs declared in loop 1-9 (I'm not sure how static applies in this situation, but that would be nifty, albeit, a little confusing).

And going back to declaring all variables at once, it's not really noticeable unless you're generating large objects just to have them destroyed at the first conditional. One last thing that I avoid like the plague is multiple declarations of variables of the same name but in a different scope. It's legal, depending on the code, (like I said, I avoid it, so I don't know specifics on when it's allowed and when it's not), but it's a poor programmer habit.
Just going back to the 80 chars per LOC issue.

Part of the reason is that some people in industry STILL use vi editor on a UNIX server at runlevel 5 (no GUI, everything on a terminal) - I had to for about 3 months. VI folds the line if it is too long, but it is better if it doesn't have to.

Some people STILL print on paper as well - on A4 paper with a reasonable size font (for old guys whose arms are too short!!) 80 chars works well.

I suppose it depends on which situation you are part of. If you code for yourself you can do whatever you want. If you are part of an open source project, the others are probably going to have graphics as good as yours. At work, it depends on what the setup / standard is.

The other situation of course is posting code on forums. Often there is less room, because of links / banners / advertising on either / both sides of the screen, and the code is not folded / wrapped. I personally dislike having to scroll sideways to look at code.
As for the commenting scheme:

Everyone agrees that commenting on the function/class level is very useful. Would be good to have something like JavaDoc for C++. Comparing to JavaDoc or ScalaDoc, Doxygen feels like a thing from the previous century.

Comments in the implemention are very important, they should describe not what the code does (because well written code is obvious), but why it does that. E.g. if you do something within a critical section, write a comment why it really needs to be interlocked, e.g by referring to some other part of code that has access to shared data.

As for the 80 characters per line: I use 120 per line, but this is because I prefer longer names with no abbreviations. If I used abbreviations, 80 characters would be enough.

Too long lines are not readable, regardless the size of the display. This is like in books or newspaper - text aligned in columns is much easier to read. I could fit much more than those 120 chars on a 30'' 2560x1600 display...
closed account (o1vk4iN6)
Volatile Pulse wrote:
No, I meant like how variable data types line up in a column and the variable names in another column. This is typical in the documentation on MSDN, all MS source code I've ever seen, and popular amongst senior coders (referring to age, not experience). I'm not sure if it originated from languages that didn't allow multiple declarations on a single line, or what, but I don't exactly like it. It also tends to promote declaring ALL variables at the beginning of the function, another thing I had, and isn't ideal for a lot of functions (optimization wise).

I prefer to declare my variables when and where I need them, no where else. I like to keep all ints, doubles, strings, on one line so I can easily see the data type and all variables associated with them.


Well that would make sense if most elderly people learnt programming around C. Actually saw the style in a project that was originally written in C but updated to use C++. I think it is easier to read and I don't think it is a bad thing that it promotes having a variable per line instead of having many in one line. Having too many on a single line will just increase characters on a line of code.

1
2
3
4
5
6
7
8

int fooHere, fooThere, barUp, barDown.

int        fooHere;
int        fooThere;
int        barUp;
int        barDown;


You can easily still tell they are of the same type but you can also much more easily tell they are associated with each other as the names are aligned and are similar. I still declare variables when I need them and they are much more easily spotted as well.

Even still if they are of different type:

1
2
3
4
5
6
7

float fooHere;
int fooThere;

float     fooHere;
int       fooThere;


I'd rather group by their purpose rather then group by their type. As their type does not define their purpose generally.
Last edited on
Topic archived. No new replies allowed.
Pages: 12