Skip to main content
GameDev.net gamedev.net
🔒 Locked

Documenting Code

Started by Gink Sep 9, 2005 at 11:12 AM 28 replies 3.6k views
Original Post
Gink
Gink
On a real project, what type of documentation would be provided by source code so that a user would be able to understand how to use the code? Would it just be documented in the source files or would there be text files and UML charts etc?
Oxyacetylene
Oxyacetylene
Obviously it depends on the processes in place for the team that makes the project. Some teams will have more rigorous procedures than others.

One thing you might consider, is using doxygen to generate documentation from the comments in the source code. For example, I put comments like these before every function, doxygen then extracts these comments, and makes HTML documentation for the project.



//=========================================================================//! @function    TerrainChunkNode::QueueForRendering//! @brief       Add the terrain chunk to the render queue//!              //! @param       queue [in]	Render queue to add the chunk to//!              //=========================================================================void TerrainChunkNode::QueueForRendering ( Renderer::RenderQueue& queue )
Gink
Gink
So it would be better to embed UML and documentation into HTML rather than text and image files?
kSquared
kSquared
Quote:
Original post by Gink
On a real project, what type of documentation would be provided by source code so that a user would be able to understand how to use the code? Would it just be documented in the source files or would there be text files and UML charts etc?

If you're using any of the Visual-Studio-.NET languages, you should strongly consider using the XML-style comments. They're immensely helpful, and documentation tools like nDoc generate very pretty and readable documentation from them.

UML documentation can be automatically generated with enterprise-level tools these days. One choice is Enterprise Architect, though many (myself included) don't like it because of the clunky user interface.
- k2 "Choose a job you love, and you'll never have to work a day in your life." — Confucius"Logic will get you from A to B. Imagination will get you everywhere." — Albert Einstein"Money is the most egalitarian force in society. It confers power on whoever holds it." — Roger Starr{General Programming Forum FAQ<
Gink
Gink
Say I have a 10-20 line simple algorithm, if I was to present this code to someone should I even use UML diagrams and if so, would it be an Activity Diagram?
Sijmen
Sijmen
I think that for small things such as algorithms UML is not usefull. I often use UML to show the general structure of the program, and I think that's what it's ment to do.
Gink
Gink
Yeah I thought it was kind of ridiculous to be using UML for something this small, so the only documentation I would need is good commenting basically?
Sijmen
Sijmen
Quote:
Original post by Gink
Yeah I thought it was kind of ridiculous to be using UML for something this small, so the only documentation I would need is good commenting basically?


Yes, as far as I'm concerned.
Mage2k
Mage2k
UML shouldn't be used as a code documentation tool, as in what functions do and what-not. UML is used to describe/design systems, their components, and the interactions between those components. So, at the source level, something like Doxygen would be useful. However, for large projects with many different components, supplying UML diagrams would be extremely useful in explaining how the system works.
---------------------------------------------------There are 10 kinds of people in the world:Those that understand binary, and those that dont...Mage
blanky
blanky
I used to not like DoxyGen, it seemed to cryptic and messy, but now I guess it's alright. I'm gonna start using it, as well as uml sculpter, thanks whoever mentioned them! :) Now I'll start documenting everything I make.
blanky
blanky
That's only C# though right, that would be cool if it supported C++.
Conner McCloud
Conner McCloud
Quote:
Original post by blankdev
That's only C# though right, that would be cool if it supported C++.

While I don't know anything about the NDoc half, I don't see why the markup itself would be C# only. So long as your compiler treats /// as a comment, the documentation parser should be perfectly capable of picking the tags out of the source code.

CM
blanky
blanky
Yeah I was thinking about that, still would like something strictly for C/C++ though.
Inmate2993
Inmate2993
Doxygen works for function headers. However, within the body of a function, you should comment just about every line to explain what it's doing. Of course, this isn't exactly practical, nor sane, but heres a good trick: Comment the body of the function BEFORE you write the code. You'll be breaking the task down into it's parts the way you understand them. That way, the code when written doesn't have any arbitrary comments, and you'll meet all of your commenting requirements.

For instance:
/** * Bubble Sort, don't use. * @param array Integer array to have bubble sorted. * @param size Size of the array in memory. */void bubblesort( int * array, int size ){  /* Iterate through the neccessary elements in the array. */    /* Iterate through the remaining elements of the arrary. */      /* Compare the two elements to see which is smaller. */        /* Switch the elements so the smaller appears first. */}


/** * Bubble Sort, don't use. * @param array Integer array to have bubble sorted. * @param size Size of the array in memory. */void bubblesort( int * array, int size ){  int x, y, t;  /* Iterate through the neccessary elements in the array. */  for ( y=0; y<(size-1); y++ )  {    /* Iterate through the remaining elements of the arrary. */    for ( x=y+1; x<size; x++ )    {      /* Compare the two elements to see which is smaller. */      if ( array[x] < array[y] )      {        /* Switch the elements so the smaller appears first. */        t = array[x];        array[x] = array[y];        array[y] = t'      }    }  }}


Perfectly commented example of a very very bad function.
william bubel
Vopisk
Vopisk
Quote:
Original post by Inmate2993
Doxygen works for function headers. However, within the body of a function, you should comment just about every line to explain what it's doing. Of course, this isn't exactly practical, nor sane, but heres a good trick: Comment the body of the function BEFORE you write the code. You'll be breaking the task down into it's parts the way you understand them. That way, the code when written doesn't have any arbitrary comments, and you'll meet all of your commenting requirements.

For instance:
*** Source Snippet Removed ***

*** Source Snippet Removed ***

Perfectly commented example of a very very bad function.


That actually is extremely useful commenting, a lot of sources that I've looked at have function prototypes that are not commented at all, leaving the user/developer to speculate as to their possible use or implementation, then when you get to the actual function declaration it's little if at all better. I really like the system describe above however, perhaps I'll start using something similar myself.

Vopisk
MaulingMonkey
MaulingMonkey
Quote:
Original post by Inmate2993
However, within the body of a function, you should comment just about every line to explain what it's doing.


No. Instead of writing comments to say what zjfire stands for, make the code itself more verbose. It's called "self documenting code". For instance:

void bubblesort( int * array, int size ){    const int * begin = array;    const int * end   = array + size;    for ( int * left_sortee = begin ; left_sortee != (end - 1) ; ++left_sortee )    {        for ( int * right_sortee = (left_sortee + 1) ; right_sortee != end ; ++right_sortee )        {             if ( *left_sortee > *right_sortee )             {                 std::swap( *left_sortee , *right_sortee );             }        }    }}


Replace (int *) with iterators for a container. I don't need to comment the std::swap line to know that I'm swapping the sortees, and I don't need a comment to tell me that I'm iterating through the array to the end, nor that "right_sortee = (left_sortee + 1)" means I'm iterating through the remainnig elements on that line.

I also don't need a comment to tell me that bubblesort preforms a bubble sort. I shouldn't even need function prototype comments except for documentation generation - I can tell that array is an array, and assuming I can't determine that "size" means "array's size", I can easily rename it to "size_of_array".
me22
me22
MaulingMonkey is absolutely right here -- your (should) already make it clear how it's doing it, so the comments should explain what it's doing.

Here's an example using some code from my current project:
//// First, how it would look with really bad "how" comments ////// check if we're at the end of the inputif ( in_it == in_it_end ) {     // report the error     throw std::runtime_error("Corrupted Data [H Length]");}// read the lengthunsigned char len = *in_it++;// check if we're at the end of the inputif ( in_it == in_it_end ) {    // report the error    throw std::runtime_error("Corrupted Data [H Offset]");}// Read the offsetunsigned short offset = static_cast<unsigned char>(*in_it++);offset <<= 4; // shift offset right 4 bits offset |= (len>>4)&0x0F; // set low 4 bits of offet to high 4 bits of lenlen &= 0xF; // use only lowest 4 bits of lenlen += 2; // increment len by 2

//// It's real form with much better "what" comments ////// Read the length and offset of the match in the sliding window/* These are stored in 2 bytes, with the lower 4 bits of the first byte * being the length ( 0-15, representing 2-17 because there are no * 0- or 1-length matches ), the upper 4 bits of the first being * the lower order bits of the offset and the second byte being the * higher order bits of the offset. */if ( in_it == in_it_end ) {     throw std::runtime_error("Corrupted Data [H Length]");}unsigned char len = *in_it++;if ( in_it == in_it_end ) {    throw std::runtime_error("Corrupted Data [H Offset]");}unsigned short offset = static_cast<unsigned char>(*in_it++);offset <<= 4;offset |= (len>>4)&0x0F;len &= 0xF;len += 2;

MaulingMonkey
MaulingMonkey
Quote:
Original post by me22
MaulingMonkey is absolutely right here -- your (should) already make it clear how it's doing it, so the comments should explain what it's doing.


A very useful distinction.

For example, you don't see a person writing (in psuedo-assembly):
mov a , temp; //move a to tempmov b , a; //move b to amov temp , b; //move temp to b

You instead see:
//swap a and b:mov a , temp;mov b , a;mov temp , a;


Assembly can't directly represent as high-level concepts as C can, which in turn can't directly represent as high-level concepts as C++. Your comments should explain what the language itself can't directly represent. I would argue that any time that any time it can, but isn't

e.g.:

temp = a;
a = b;
b = temp;

instead of:

std::swap( a , b );

is a time where the code should be refactored.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.