I'm doing a little practice problem that is made up of multiple files (5 files). As I have a few hours a day to learn C++ (and there are days that i can't even keep to those), I keep forgetting how things work.
How do you / what is your advice on keeping a good overview of how things work? UML diagrams? Lots of comments?
PS: I posted on this forum, because "Beginners" tends to be about C++ syntax, I'm sorry if I was mistaking.
Being able to read code is something that comes with practice - in general, having too many comments will just annoy you. Normally, for comments it is more interestening what you are trying to achieve - meaning, why you are doing something rather than what you are doing.
Comment why you did things. That's what is important. It's very easy to come up with rationale as you start something, but you will almost assuredly forget some time in the future, leaving you wondering why you did something a certain way.
I've never used UML diagrams outside of when I had to (project requirements, etc.). I've never needed them, but they could be helpful, especially for someone who is coming into a project without having read the code before.
In the words of Bjarne Stroustrup, from the book: Programming Principles and Practice Using C++, Bjarne wrote: Comments are written to describe what the program is intended to do and in general to provide information useful for humans that can't be directly expressed in code.
I put a comment at the top of every function (edit: and every other entity, except variables. Global variables and member variables get a single line comment) which briefly (in a sentence or two) describes what it does, then one sentence for each of the parameters it takes (if any) and another sentence about its return value (if any). If necessary, I also make a note of anything it does that might be unexpected, anything that needs fixing, or anything else like that. Since all of my functions (except one or two) only do one thing (as they should), I rarely need to put a comment in the body of a function. If I do its normally to notify someone of a work-around or something like that.
In addition to what chrisname said...I normally also include throw specifications (including the guarantee that the method offers, no-throw, strong, or basic.) and what could possibly cause one to be thrown.
boost wrote:
* The basic guarantee: that the invariants of the component are preserved, and no resources are leaked.
* The strong guarantee: that the operation has either completed successfully or thrown an exception, leaving the program state exactly as it was before the operation started.
* The no-throw guarantee: that the operation will not throw an exception.
If you're looking to start a documenting habit, I would strongly recommend looking over this article. The advantage to using a format that Doxygen can recognize is that you can automatically generate a HTML hierarchy and/or windows help file (*.chm) from the source. It's very useful for developers that may someday use what you write today.
http://en.wikipedia.org/wiki/Doxygen
The disadvantage to conforming to Doxygen is...I suppose a lesser degree of rebellion against documentation standardization?
Yes, it frustrates me to no end when I'm using a piece of library code that throws an undocumented exception.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/**
* @pre
* Preconditions Here
* @post
* Postconditions Here
* @param 0 -> N-1
* Parameter Description
* @return
* Return Description
* @throw
* This method may throw a frying pan at you if you make it mad.
* @deprecated
* @warning
*/
@Luc Lieber Fair enough. A while back I was using real exception specifiers like crazy until I found an article which told me how bad they generally are :P
I don't really comment my code much any more. I should probably do slightly more to explain what I'm trying to do, but at least I don't make comments which just echo the code as I used to.
Sometimes I put throw specifiers on methods that I can toggle off (using macros). Even so, the only throw specifiers that I use are to denote no-throw methods. I read a while back that throw() used in Microsoft's compilers can help the compiler eliminate some error checking code (which shouldn't be there in the first place if you're guaranteeing a no-throw method). Using the throw specifiers to specify what's thrown doesn't really have the same effect. I believe that it was in Herb Sutter's blog that I read that.
Yeah. That article by Herb Sutter is what I read too - http://www.gotw.ca/publications/mill22.htm basically condemned exception specifications in general, but said that Microsoft's empty throw() was an exception to this and it actually did optimise things.
I got "autodia", a UML diagram generator for dia, and it's preety nice as it helps to see my code from a different perspective... That is to say, more like how I have it in my head. I also got some documentation about drawing UML diagrams, but I don't understand all of it right now.