|
|
|
Displaying Newsletter
|
Issue 31, 27 Nov 2002
|
|
|
|
|
A crash course in inline source code documentation with Doxygen
|
by Tyler Dauwalder |
|
|
|
So I'm sure a number of you out there were a bit skeptical as to whether or not I'd be able to churn out two Doxygen newsletter articles in a row (I sure didn't think I'd manage :). Well, just to spite all of us non-believers, here I am with a shiny new tutorial on documenting your source code with Doxygen. The things I'm going to cover here are just the basic meat-and-potatoes parts of Doxygen that I use on a day to day basis; for anything else, please consult the online Doxygen manual; it's really quite handy :).
Doxygen comments come in two flavors: JavaDoc style or Qt style. Each comment represents a description for some entity in your code (meaning a class, or a function, or a variable, etc.), and there are two types of descriptions: brief and detailed. Each description is optional, but an item may have no more than one of each type of description. Here's what they all look like:
Listing 1:
/// JavaDoc style, brief
/** JavaDoc style, detailed
*/
//! Qt style, brief
/*! Qt style, detailed
*/
Note that unless you set 'JAVADOC_AUTOBRIEF = NO' in your config files (which I always do :), the JavaDoc versions will try to perform some funky magic behind your back and treat the first sentence in a JavaDoc comment up to the first period as the brief description; if you think this is a good thing, just leave your config files alone :)
At any rate, when Doxygen parses through your files, it applies the descriptions in your Doxygen comments to the immediately preceding declaration or definition in the source file. Thus, to document a BagOfPopcorn class with both a brief and a detailed description, one could do something like the following:
Listing 2:
//! A class that simulates a bag of popcorn.
/*! The BagOfPopcorn class should not be confused with the
BucketOfPopcorn class.
*/
class BagOfPopcorn : public PopcornContainer {
...
};
"A class that simulates a bag of popcorn." would be applied as the brief description for class BagOfPopcorn, and "The BagOfPopcorn class should not be confused with the BucketOfPopcorn class." would be applied as the detailed description. Depending upon how you configure Doxygen, brief descriptions are generally displayed in pieces of the documentation that list a number of entities to choose from (such as the "Compound List" page or the initial overview of a class' members on the specific class' page), and detailed descriptions are used separately from or combined with the brief description to form the main chunk of documentation for a given entitiy (for the Storage Kit documentation presented last time, detailed description are combined with the brief descriptions).
Now suppose you didn't want to include the Doxygen comments with the given declaration or definition. For example, we've tended to include all Storage Kit documentation in our source files, leaving the headers clean and easy to browse; if there were no other way to document a given entity, we'd be forced to include documentation about a specific class in the header for that class, as the source file contains no documentable declaration or definition for the class as a whole. Fortunately, one can place a Doxygen comment pretty much anywhere and reference it to a specific entity in the following
manner:
Listing 3:
/*! \class BagOfPopcorn
\brief A class that simulates a bag of popcorn.
The BagOfPopcorn class should not be confused with the
BucketOfPopcorn class.
*/
Placing this comment somewhere in BagOfPopcorn's source file would have the same effect as placing Listing 2 in the header. The "\class" bit is a Doxygen command that tells Doxygen to apply the comment to the specified class, in this case, class BagOfPopcorn. Similar commands are available for other documentable entities:
\namespace documents a namespace.
\file documents a file.
\struct documents a struct.
\enum documents an enumeration type.
\fn documents a function.
\var documents a variable, or a typedef, or an enum value.
\def documents a #define macro.
There are a few others as well, but I've never needed them. Note that the \file command is the only way to document a file. Further, certain things like global functions will only show up in the generated documentation if the file they live in is documented as well.
Another command introduced in Listing 3 is the \brief command. You can use the \brief command inside of a detailed description in lieu of a separate brief comment. The nice thing about the \brief command is that it can span multiple lines, whereas the specific brief comments are restricted to one line; a line of whitespace designates the end of the brief description.
Another useful thing to know is how to document function parameters and return values. The \param command documents a single parameter (thus you use it once for each parameter), and the \return command documents the return value. So, for example, you could do something like the following (note that the \c command forces the next word into a monospaced font):
Listing 4:
/*! \brief Recites the poem in the given language at the given tempo.
\param language The language in which the poem should be recited.
\param tempo The speed at which the poem should recited.
\return
- \c B_OK: success
- \c B_BAD_POEM: returned if your poem sucks (note that the poem
will not have been recited)
- other error code: failure
*/
status_t
Poem::Recite(Language language, Tempo tempo)
{
...
}
You may have noticed the bulleted list looking bit in Listing 4. This part is fun :). Probably my favorite part of Doxygen is making bulleted lists, which, besides making you look way more organized than you really are, is unbelievably easy to do. I'm not even going to bother explaining it, just check out another example:
Listing 5:
/*! \class CardboardBox
\brief A class that simulates a cardboard box.
- Things cardboard boxes are good for
-# Being worn as a helmet
-# Being thrown at strangers
-# Being used as a fort
-# Being used to store popcorn while it is consumed
- Things cardboard boxes are not good for
-# Being used as pillows
-# Being used to transport water
*/
You ought to be able to figure out what it'll generate just by looking at it, but in case you're curious or skeptical, I've prepared a
package with a header/source file pair and a ready-to-go Doxygen config file.
It contains all the examples given here, plus a few others I haven't mentioned, and I'd highly encourage you to check it out and play with
it if you're at all interested. You'll just need to install Doxygen as instructed
last time,
unzip the example archive, and run 'doxygen example.cfg' from the doxygen-example/ directory.
Doxygen should generate output in html, LaTeX, RTF, Man page format, and XML.
For those who are curious where the config file came from,
I simply ran 'doxygen -g example.cfg' to generate a generic config file, loaded it up into an editor, and filled in the blanks;
there are a lot of useful comments in there to help you along. Hopefully, that should be enough to get you started.
If you find yourself wondering what else you can do with Doxygen (there's actually quite a bit more),
be sure to browse through the online manual.
And keep in mind that HTML tags can be used anywhere in your documentation; Doxygen will automatically convert
them to appropriate markup for other output formats if necessary. Have fun!
|
|
|
I wanted to take a second to thank all the team leads who took time to answer questions and explain things I had confused. Any errors in this listing are mine not theirs. :-)
-Luke
App Kit / Interface Kit:
- Many header issues resolved. Thanks go to Marcus Overhagen.
- Jack Burton says that BString will be integrated into the build as soon as he fininshes the tests.
- Gabe Yoder posted BClipboard is now passing tests.
- Marc Flerackers submitted code for BMenu, BMenuItem, BMenubar and BPopupMenu. He's looking for volunteers to work on BtextView and related private classes.
- DarkWyrm is hammering the font code into shape for prototype 7
- Ingo Weinhold imported the new FreeType code (and fixed the jamfiles) into CVS. Now we are current with v2.1.3.
- DarkWyrm also contributed a fix for garbage text in window titles and updates to decorator and the API, plus what he describes as a 'Complete server update'. (and he isn't kidding!)
- Jeremy Rand uploaded some BPolygon tests to CVS.
- DarkWyrm uploaded an initial BWindow implementation by John Hedditch to CVS. (Someday we will be putting stuff on screen. :-))
- "Jack Burton" submitted changes to the String.h header file, fixing some issues there.
Be File System Kit:
- Beta 4 available!! Grab yours now here. (Virtual Memory can be enabled !!) Keep in mind this is a _BETA_ and, as such, should only be used on a 'spare' partition.
- According to Bruno (BGA) Beta 5 should be out "real soon now"(tm) (Axel says it could take a bit more time than that :-) I think I'd settle for "when it's ready" ;-) ) with many fixes implemented over beta 4.
- Axel has submitted code for OBFS' own chkbfs! And added a new option to it even, allowing errors to be fixed that the original couldn't even find.
- Live queries should now be working (again! :-) ) under OpenBFS.
- Currently taking a slight speed hit in comparison to BFS. Axel says don't worry, be happy. Just kidding ;-) This is due to the way OBFS is currently using the write cache (flushing after every 64 blocks) and probably won't be changed for some time. Keep in mind that OBFS is still much faster updating indices / directories, even with these constraints.
- The BGA and Axel bug hunt continues... :-) (10 KDL bugs, 9 KDL bugs, 8 ... :-) )
Creative Design Team:
It appears the Creative Design Team is ramping up for production.
(everything else is top secret ;-) )
Game Kit:
- The GameSound classes have been submitted and a test app has been checked into CVS. (I haven't looked to see what it tests, though).
- VitViper is working on the BJoystick class tests. He says they are at 85%. (the CVS police may be hunting him down ;-))
Input Server Kit:
The InputServer team is alive and well. Jason has this to say:
"The OBOS InputServer continues to improve. We are currently able to use the BeSampleCode Nervous InputServerDevice with our input_server. Instructions on how to get our input_server working will be coming soon. Our input_server cannot replace the existing input_server, but it can be used in conjunction with the AppServer Proto6 and later. When our input_server is correctly installed and started, you can start proto6 and see Nervous do its thing. :-) We have support for InputServerFilters, but that and the InputServerMethod code continues to evolve. To help us with support for InputServerMethods, our team has begun creating a Transliterate Russian InputServerMethod (The team is learning Russian for fun). As the TR-ISM evolves, I will write newsletter articles detailing how to write an ISM in hopes that others will jump in and help provide us all with ISMs for other languages."
Kernel Kit:
- Michael Phipps submitted what he describes as "mega changes" to the VM. Now using hash tables and introduction of a vnodeManager. (to allow cached, opened and mmapped files to work together)
- Daniel Reinhold submitted changes to the POSIX signal code (putting in code that will eventually allow us to obtain current thread id's)
- Marcus Overhagen submitted some changes to the SMP code.
MIDI Kit:
- The MIDI Kit team now has a web site up here.
- The midi2 kit documentation from Be (what there is of it at least) is posted on the team web site and they also have a link to the midi1 kit documentation posted.
- Jerome Leveque submitted changes to a pile of Midi component files. Not to mention fixing a deadlock in Midi.cpp that occured when deleting BMidi class.
- Matthijs reports that they have studied how the midi2 kit works and they have filled in the gaps in the API documentation, as well as documenting the protocol between the midi_server and libmidi2.so. (Great job guys!)
Media Kit:
- Marcus Overhagen brought us much closer to having a media kit. :-) Hey there is working code!
- Shatty (Andrew) is hoping to get a demultiplexer working "soon" but has 'real life' commitments to meet that are keeping him busy. (not to mention StyledEdit ;-) )
- Marcus has made lots of changes to the media kit code, adding automatic media_addon_server launching and termination, detection of and cleanup after application crashes (for now, anyway) and (as a special bonus :-)) if the media_addon_server crashes, it will restart. Note that Marcus doesn't plan to have any need to restart the media server. Adding / removing media kit components like codecs, or media nodes, will be possible without restarting.
Networking Kit:
- It builds again, after fixing the Jamfiles and headers. Thanks Marcus!
- Philippe Houdoin posted a huge list of changes to the net team list. Due to the size of the list (no kidding, check it here ) some of the highlights are:
- We now have BNetAddress, BNetBuffer and BNetDebug in libnetapi.so (and yes it builds, headers are even included ;-))
- Foundation laid for ability to switch at runtime between the kernelland net-stack and the userland net-stack. (for debug purposes - not intended as a feature)
- kernel and userland stack drivers now publish different devices, /dev/net/stack and /dev/net/server.
- Networking command line apps all build again (after a long build breakage).
- lots of pending changes - Philippe is the man!
Preference Applications Kit:
- "Jack Burton" dropped a bunch of code into CVS, fixing the screen preflet app. He says it "Still has some minor bugs, but it's fully functional".
- Shatty (Andrew) pushed a pile of (Open)StyledEdit fixes into CVS. Among other changes, it looks like the color reset font bug is fixed and he has made the menus update for font family and size.
- There has been a lot of discussion about bi-directional text handling (for example left-to-right or bottom to top) and where support for it belongs.
- The MidiPlayer application has been included in the Preference Team. Jerome will still be working on the code.
These guys just punch out the code, but very quietly. Check out their web site here to get more information (application by application). There are tons of CLI applications posted that interested coders can tackle (check the "Jobs {Command Line}" link, listed under "Modules" on the left of their web page).
Printing Kit:
- Print_Server Beta 3 is out (From the "Did you miss it?" department :-)) Get yours today here.
- Michael Pfeiffer posted news of changes he made to the Printer Preferences application to select and add a local printer. He says that USB is still untested. (any brave souls want to do some testing?)
- Printing Preferences windows changed in anticipation of cool button bitmaps from the Creative Design Team. ;-) Ok, so you want to see it? Check here. (Note that the buttons you see are from Michael, not the Creative Design Team)
ScreenSaver Kit:
Updates from Andrew - ScreenSaver Kit Team lead: "It's at the "80% complete, but needs a partial redesign for the last 20%" stage. :-) I am barely working on the redesign now, as my work just threw up an impossible deadline of early February for our project, so my time is at a premium. Basically, here's where I see things:"
- The ScreenSaver rendering thread needs to be completed (for both the preflet and real life).
- Prefs storage is being double-checked right now.
- The input_server add-on is unknown (not there yet)
- The base ScreenSaver class may need a little work, but this is really minor and can wait for now.
Storage Kit:
- Registrar Milestone 3 has been reached! Thanks to the Storage Kit Team with support (this time) from Gabe Yoder, all but one method (one that requires our own App_Server) is implemented. There are two more services to be added, the background MIME database updates and system shudown. It makes much more sense to work on both of these services once we can run applications under our OS.
- The private OpenTracker Device API is now being worked on. Ingo Weinhold posted a long message about it to the mailing list ( read it here ).
Translation Kit:
- Michael Wilber submitted some changes to the TranslatorRosterTest code (from Brian Matzon, thanks Brian!) and has plans to add more tests of the rest of the Translation Kit.
- The Translation Kit is in Beta! Michael says they went to Beta status after resolving some bugs from the Alpha stage.
|
|
|
*** Warning - this editorial may contain concepts and ideas disturbing to Unix purists!***
First, let me start out by stating that I use Unix (Solaris) almost every day. While I am not the master of all things Unix, I have a better than average knowledge of it, I like to think. I like a great many things about Unix. Pipes are probably the most useful concept I have ever seen in computer science. It is componentization of software some 20 years before it came into vogue.
While I like Unix, it has some issues, too. Some ideas whose time is past. Some concepts that are outdated and need to be replaced. I believe that foremost among these archaic constructs is /dev.
I can hear the wailing already. Hear me out. For those not initiated in the rites of the acolytes of Bell Labs, /dev is the directory where devices are mounted. So you could look at see /dev/tty for a teletype device. Or /dev/prt for a printer. Back in the days when everything was character based, this was exceptionally powerful. If you wanted to get input from a device, you could do it right from the command line. cat < /dev/foo. Very nice. Or send output to a device - cat tmp.txt > /dev/bar. This has served us well for a very long time, but that time is past.
The first issue that I take with this approach is that most devices are not simple minded printers or modems or teletypes anymore. It doesn't make any sense to say cat < /dev/scanner. Few people want to deal with joysticks, ethernet cards or video cards from the command line in this way. Much of the benefit of making your devices accessible easily from the shell is gone.
Secondly, / is a place for files. Overloading it with devices and other various hardware interfaces doesn't make sense to the average user. Why does it make sense to have a video card in /dev?
Thirdly, from a programmer's point of view, using *only* open, close, read, write and ioctl on devices no longer makes sense. It forces us to funnel every possible command that couldn't be forseen by guys with teletypes to go through ioctl. Think about the act of setting up a scanner for scanning. You end up with code that is very hard to read.
The ioctl commands must be published and (hopefully) standardized. Say you are writing a CD ripper. If one CD Rom's ioctl for "start rip on track 4" is different from a different driver's command, your code must account for that, if you want to work with both devices.
With /dev, you have to know the name of the device that you are interested in. Or, at least, what directory the device driver will publish itself to (yes, that is hard coded). So if you publish an app for, say, MIDI manipulation, you will probably search for /dev/serial1. But what if someone has a /dev/usb/midi/1 device? You can't work with it.
The /dev directory has been filled, too, with "psuedo" devices. The most obvious is /ptty - psuedo tty's for use with PCs. But there are others - kmem (kernel memory) is a good example. This is a nightmare for beginning users.
While I could go on, I have to leave room for the solution to this issue...
BeOS has a wonderful concept called rosters. A roster is basically an "intelligent" keeper of a list. You can use the roster's API questions and it can respond with items or sublists. My concept is a device roster. All devices would have a roster entry that allows you to get one or more device classes back. You can query based on type of data or on device type. For example, you could ask for all devices that can return anything in the mime type "image/". This should return digital cameras, scanners, hard disks, etc. Or you could query for every printer device, etc. All of these devices should derive from a common class (BDevice or some such), but be subclassed (maybe more than once). As an example - a CD ROM drive could be BDevice-->BMassStorage-->BCDRom. This would allow developers some flexability in addressing devices - they could choose to dig deep in the features or they could stay shallow and address more devices.
On a related note, I think that this would open the door to a different type of file panel. How about a BImageFilePanel? One that queries the device system for image yielding devices and has neat features like thumbnails, etc? Or a BSoundFilePanel that lets you play snippets before loading the whole file?
This system should also make it easier to deal with device configuration. A single application could exist that shows all of the devices. They could be configured via a single GUI, using standardized interfaces.
There are certainly details that would need to be worked out, but I believe that this system would be far more powerful and would shed the legacy pain of /dev.
|
|
|
|
|
|
|