Jump to content
  • Advertisement
Sign in to follow this  
DMINATOR

Comments the way to do ?

This topic is 4857 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi So I am mostly coded for myself, and I didn't do anything special with comments, I written them as I understood the code, and in the parts, where I thought it was necessary. But what is the right way for Software Companies to do ? Where the code should be, where not, and what should be written in what way ? I am looking especially advice from people who are working for commercial companies, but anyone else is also welcomed :) Thanks.

Share this post


Link to post
Share on other sites
Advertisement
I am programming in Java (commercially) and C++ (more or less for myself).

I comment my code extensively. All classes have a "class comment", each method has a comment (partly not only about _what_ they do but also their rationales), and each field has one. Additionally, comments are inserted into the method bodies. Often algorithms are such complex that I (as the author) would not understand them 2 monthes after writing, if especially tricky parts would not be commented.

I use JavaDoc for commenting Java source, of couse, and doxygen (under linux) for C++. So I use also more or less standardized formatting for comments (e.g. @param in JavaDoc or \pre in doxygen).

I use assertions in the way suggested by Meyer's Eiffel language: "Design by Contract."

In medium to large scale projects also unit tests are essential. I write them also for my private libraries. They not only give one a safety of "all is correct" but also early points out some bugs and inefficiencies. And reworks are much less painful to verify.

Well, partitioning the code into appropriate compilation units is another question. I don't assume that there is a golden way to go. Ok, in Java one has not such freedom as in C++. I make "packages" in Java (of course) but also in C++ (ok, at an amount of 500+ classes one would die on searching otherwise). Besides that I _normally_ have one compilation unit per class.

In a consequence all this is a question of how many effort one wants to spend now and in the future. I've often had to read code written by other people, and often other people have to read my code. I know how painful that may but need not to be ...

Share this post


Link to post
Share on other sites
These are mostly not my tips but I have found them useful:

If you use java, the best thing to do is make sure that the javadocs are complete for your program. Since your sig indicates you use C# then I would probably do the MS-version of a javadoc (since I assume MS would make at least a half-clone of javadoc)

When you use C++ make sure that each function is commented with a description of what the inputs and outputs are and what task is performed. Also make sure that each 3 to 5 lines of "non-trivial" code have a comment attached describing any non-obvious parts of those lines.

And be careful not to write pointless or stupid comments, like:


...
x++; //increment x
i = sin(M_PI/2) //take the sine of pi over 2
...

Share this post


Link to post
Share on other sites
Quote:
Original post by etothex
And be careful not to write pointless or stupid comments, like:


...
x++; //increment x
i = sin(M_PI/2) //take the sine of pi over 2
...


Just to expand from this as a base point...

<blatentopinion>

Comments should not be used to say what a given line of code is doing, this should be obvious from the code itself (self documenting code). Comments should address things like why, and to what end. If a section of code is nonobvious in purpose I prefer to factor that out into an appropriately named function (self documenting code) or using appropriately named temporaries, rather than commenting - this also leads to more reuse.

Basically, things like:


... box.right - box.left ...
=> ... width( box ) ...
or => scalar_type box_width = box.right - box.left;
... box_width ...


An alternative good use for comments is things like listing side-effects - e.g. std::vector::* functions when a resize triggers a realloc will invalidate existing iterators.

</blatentopinion>

Share this post


Link to post
Share on other sites
My general rule is, if there is code that could not be quickly read and understood by someone familiar(but not an expert in) C++ and what your program does, then it needs a comment. Basically, any time something that is not immediately clear or uses some non-obvious or non-standard techniques.

Consider a function computeAngleBetweenVectors(Vector v1, Vector v2). In the body of the function you could take the dot product and figure the angle that way. The code, IMHO, should be commented something to the tune of "use the dot product to calculate the angle" or even "calc. the dot product". Not much more is needed, because it will help someone reading your code interpret it, without giving them any more information that wasn't easily gained from the code itself.

BTW, using smart, descriptive variable and function names _really_ helps here - because that provides a lot of info in the first place.

Another rule of thumb is to assume that the readers of your code know a lot of basic, common knowledge - but have forgotten all of it. Following the computeAngle example, you should assume that the reader is familar with using the dot product but would not recognize the code for such on sight. The comment should clearly explain the high-level view on the code - the reader should see the code, read the comment, and see what you are doing, and if necessary know the terms to search under if they are unfamiliar with the dot product.

Obviously, the dot product example is a bit contrived because it is so simple. But the same principle applies to more complex algorithms that may not be as intuitively readable in the code.

Share this post


Link to post
Share on other sites
Here is an example. Not very complicated stuff, but with a little trick. However, more or less my method bodies look this way as soon as enough lines come together.


bool
BoundingSphere::consider(const Point3_t& point) {
// classifying the point (initially _sqRadius is -1, so that the first candidate is ever classified as an outlier)
const Point3_t difference(_center,point);
scalar_t distance = difference.squaredNorm2(); // in fact the squared distance
const bool isOutlier = distance > _squaredRadius;
// if the point is an outlier the volumes geometry must be adapted ...
if(isOutlier) {
distance = XMath<scalar_t>::sqrt(distance);
// faking on the first point ...
if(_radius<0) {
// due to this little trick the newRadius will become 0, and the center will be translated by 1 multiple of
// the difference vector from Point3_t::ZERO on, so yielding in the point as center of a sphere w/ radius 0
_radius = -distance;
}
// computing the new radius to include the sphere so far as well as the outlier
const scalar_t newRadius = (_radius+distance)*0.5f;
// shifting the sphere "half-way" towards the outlier
if(distance) {
_center.add(difference,(newRadius-_radius)/distance);
}
// scaling the sphere
_radius = newRadius;
_squaredRadius = newRadius*newRadius;
}
// done
return isOutlier;
}


IMHO the comments should not paraphrase the code but (a) may explain the flow of control, and (b) should make clear what effects code has.

Quote:
Original post by etothex
BTW, using smart, descriptive variable and function names _really_ helps here - because that provides a lot of info in the first place.

I absolutely agree (see above ;-)

Share this post


Link to post
Share on other sites
If you have a moderately long function that you can't really break into pieces, it is good to summarize it by writing small "headings" in front of code blocks, even if they are otherwise easy to understand. A control function for some resource loader might look like this:
/* Check that arguments are valid */
...

/* Load from file */
(open file, small read loop, close file, error handling)

/* Parse contents */
(call parse function, handle errors)

/* Run through SomeFilter if type is .xyz */
(call(s) to SomeFilter, error handling)

/* Cache to SomePlace if caching is turned on */
(call(s) to cache function(s), error handling)

/* Replace existing data structure atomically */
(some compare-and-swap code)

/* Handle common errors */
(end of a long try-catch block for instance)

This way a reader can scan the code much more quickly because there is no need to read any of the programming language while looking for something.

edit: use plenty of whitespace too.

Share this post


Link to post
Share on other sites
I know this doesn't help, but it seems like no one at my company believes in commenting, bc when I am at my company and I am trying to find bugs in code that someone else wrote I typically end up spending too much time trying to figure out what they're trying to acheive and how they did it.

that's my rant.
~guyaton

Share this post


Link to post
Share on other sites
Haegarr, which test framework are you using for C++? I'm having a hard time finding something easy to use, e.g. most frameworks require you to use a (test_)main() function which interferes with my WinMain() etc.

PS: Selm, hehe... only half an hour away!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!