Coding Conventions and Style Guide
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
last updated: Nov 2004

Source files

1. Put the NED description, the C++ class declaration and the implementation
   of a simple module into three separate files. Don't put two or more modules'
   code into the same file unless they are build upon one another. Thus, 
   for a simple module called Foobar, you would have Foobar.ned, Foobar.h and 
   Foobar.cc.

C++ coding style

2. Choose your favourite indentation style and keep to it consistently. 
   Prefer // comments to /* */ ones. Add Doxygen comments /** */ for 
   classes and class methods. Don't put more than one statement on the same 
   line. Avoid putting comments at the end of the line -- place them above 
   the code on a separate line instead! Always use blank lines to
   break the code into reasonably short logical blocks; above each block, 
   put a comment in a few words what that block does. 

3. Identifiers: Begin module type names with a capital letter, and capitalize
   the beginning of each word, like in TokenRingMAC. Do not use underscore `_` in
   module names. Use the C++-style naming on member functions: beginning of 
   each word is capitalized (except for the first one) and no underscores:
   sendUnnumberedFrame().

Organizing simple modules

4. Prefer handleMessage() to activity(). 

5. Objects like cQueues, cOutVectors, cStdDevs go into the class
   declaration. You can assign names to them with setName() and otherwise
   initialize them in initialize().

6. Avoid global variables (and what's the same, static class members). They
   are not reset to their initial value (zero) when restart the network in 
   Tkenv or perform several runs with Cmdenv.

7. Query the values of parameters into state variables (-->class members) of
   the same name in initialize(). If you know the value of a parameter is 
   a random value (like uniform 0..10) or it can change during simulation, 
   then to avoid having to look it up by name each time (like d=par("delay")) 
   you may query its pointer into a cPar* state variable with the same name 
   prepended with 'p' (like pDelay=&par("delay")).

Constructors, destructors, initialize() and finish()

8. Never put code that's supposed to do simulation-related things into the
   simple module destructor; put them into finish() instead. In fact, you almost
   never need to write a destructor since OMNeT++ keeps track of objects you
   create (dynamically, as local variables or as class members) and disposes of
   them automatically. However it cannot track non-OMNeT++ objects so they may
   need to be deleted manually from the destructor.

9. You need to write the simple module constructor explicitly if you have
   dynamic data structures in the class that need to be freed by the destructor.
   Even in this case, make the constructor as simple as possible (e.g. simply NULL
   out the data structure pointers) and leave real work to initialize().

10.Especially, do not put simulation-related code into the simple module
   constructor. For example, modules often need to investigate their surroundings
   (maybe the whole network) at the beginning of the simulation and save the
   collected info into internal tables. Code like that cannot be placed into the
   constructor since the network is still being set up when the constructor is
   called.

Make use of what C++ offers

11.Do not hesitate to split up handleMessage() into several member functions, 
   as this generally improves code readability. For example, if you're
   implementing a state machine, you can put the general logic into 
   handleMessage() and the code implementing the actual states into separate 
   member functions. As a rule of thumb, one member function shouldn't be 
   more than one screen page long unless really necessary.

12.Make the functions virtual. Maybe someone who reuses your code will need a
   different behavior than what you thought of.

13.Use inheritance if you're writing a very complex simple module: create a
   basic simple module class and build upon it deriving new module classes. This
   will make your code more readable and easier to manage/reuse. Unfortunately,
   inheritance is not supported in NED so you actually have to make distinct NED
   descriptions for each simple module class. Even if you have an abstract
   classes, prepare a NED desctiption for it: it is useful as a reference to
   others who might derive a different simple module class from your abstract
   class. Inheritance in NED is planned in later releases of OMNeT++.

14.Define message classes in .msg files. Avoid hand-coded message classes and
   attached cPar objects.

For better performance

15.Reuse messages wherever possible. For example, if you implement timers, 
   you can create a message once and then schedule the same message again 
   and again each time the timer is restarted. Look at the Fifo example 
   about how to do it.

Prepare for debugging

16.Add ev<<... statements to the code to print out what the module is doing. 
   It will pay out several times when it comes to debugging.

17.Put a WATCH() on the state variables into initialize(). This can be 
   invaluable during debugging.


