Introduction
Before I embark onto describing my coding style which I have picked up from a few
practical as well as theoretical sources, it might just be a good idea to analyze if
C++ is really for you. In essence the difference between C++ and C is more theoretical
than practical. If you are beginning to program in any OOPs language then you have to
think in OOPs way otherwise there is no real advantage. Simply using a C++ compiler
to compile a C program wouldn't really help. Though some die hard C++ fans would counter
me, I feel that C++ is only needed if you are actually building some software which needs
to last over generations. Effectively which means that it would be used by a number of people
in its entire life span as well as it would be modified by those same very people. This brings
us to the two core issues of software engineering. Manageability and efficiency, while C++ is far more
manageable, C is much more efficient. However if you are only interested in writing software for some small student
assignments then may be you would be better off using a simple and far more efficient (even
efficiently written programs in c++ are anywhere between 60% to ?? slower than C ones) language
like C. Also if all that you are interested in is a quick and simple solution may be looking
at Perl or python would help. The main bottleneck in programing in any language supporting OOPs is developing
the thought process, wherein you are actually thinking as per the OOPs model and not
just converting and collecting your functions in classes. If you are new to OOPs and
are just beginning to use C++, I suggest that you rather start with Java. The
reason is that Java leaves behind efficiency and concentrates just on portability, which
makes the OOPs model explicit. In a way Java forces you to think in OOPs whereas C++ still
has back doors wherein you can bypass the OOPs model.
In this article I present a set of coding conventions which we have been following for
some time now and have found to be pretty effective. These have been picked up from
a variety of sources. However this is in no way the defacto coding standard and there may be
a lot of loop holes. The only defense which I have at the moment is that we have been practising
these and have found them to be effective.
Coding Style
- The first and foremost convention is regarding nomenclature. We follow
the following, class names start with a capital letter, function names start with a small
letter and capitalization may be used to break word, underscores are not used. If you are building
a library, prefix the name of that library in all the class names. This would save name conflicts
to a large extent.
- Files are named separated by underscores. The names itself is derived from the class
contained in that file. In order to keep the file name itself small, common prefix can be
removed from all the files. C++ header file names end in .hh and C header file names in .h.
For the C++ source files, a .C may be used though we use .cc.
So, for example, a file containing the class,
AssetSimuProcessConstructor can be put in the file simu_proc_constr.hh.
- Constructors are declared together in one public section, next other public functions in another
public declaration, then private functions and finally private variables and classes. Separate
interface functions and other common functions by various public declarations.
- Parenthesis are written separated by spaces as mySmartPrint( stderr, "Test\n" );
and comma is written attached to the left variable.
- Variable names use underscores to break words and never capitalization. Also,
follow the golden rule of keeping name of the variable small.
- Header files never include other header files. The dependencies are sorted out in
the source files. This helps prevent multiple inclusions as well as makes
the dependencies clearer for someone who is looking at your code for the first time.
- We follow the following style for include files, first put all C++ standard includes,
then put any ?C? standard includes, next any common local includes. All the defines should
follow any includes, until the includes themselves need these defines. It is also a good
practice to group all the defines together in one file.
- It is always a nice idea to make one class the base of all others containing just the
id (name or something more). This is useful for many things (e.g. debugging).
- Define one simple DEBUG macro and use this to print your debugging information.
The macro itself contains debug levels and also echoes the id of the base class, to
clarify which object this message is coming from. If you later want to distribute
your software for some professional purpose may be these macros could be stripped off.
This has the advantage that at any given time debugging is built into your software.
- Static functions are always a bad practice like global vars until there is some really good
reason for using them.
- Make classes of concepts not functionality, remember objects are meant to hold
data and functions together not just to group common functions.
- If you expect some constraint to be satisfied for the correct execution of your code
put an assertion. Also make liberal use
of const, this provides the compiler with an opportunity to optimize the code more
aggressively along with helping save some common programing errors.
- If you need to get some parameters from the user on command line, use getopts instead of
writing the parsing function your self. This makes the implementation neat as
well as saves you a lot of unnecessary error checking.
- Whenever you want to force a design decision, abstract out the interface using abstract
classes, with all functions as pure virtual. This will make the code maintainable across many
generations.
- Automatic documentation tools like Doxygen, do a great job without too much effort on your
part. They also help someone browsing through your code get an overall idea
of the software. So, it is generally a good practice to use them. Whenever putting comments, try
to follow the style which the particular tool understands (e.g. /** .. */) for Doxygen.
- Always discuss the top level class hierarchy with someone good in OOPs, before proceeding
to implementation. The clearer you are before starting implementation of your ideas in C++,
the simpler your code would turn out to be.
- C++ is slower but more manageable than C. Until you have people who really understand what
they are coding and the reasons behind future and past design decisions use C++ for any large sized project.
This will help keep the goofups at a maintainable level.
- Use a versioning system if you are working with someone else. CVS is real good. Also when
using cvs put the first line as $Header$ in comments (# or //), this really helps.
- Write comments to illustrate the ideas behind what you are doing, not how you are doing.
How you are doing something is clearly established from your code. The ideas make reading the
code lot more pleasurable and clear. Comments like *}//End of loop. are junk, even an
idiot can see that.
- If you need some variable just for loop iteration declare it inside the for statement.
However, try to declare all your other variables at the top this will make understanding
the code easier as well as make it more maintainable.
- Donot use C style calloc and malloc in C++, the operators new and delete are better.
- It is always more manageable to use class pointers rather than variables. Use new to create
and delete to delete objects.
- Keep the size of private classes small. In case your private classes are growing large
you perhaps need to relook at your design. Donot create separate files for private classes.
Define their functions along with their base class.
- Use iterators they save you a lot of type casts along with many other benefits.
- Use template classes only if you need them. They complicate simple things. Generally
unless you are making generic libraries they are not for you.
- It is generally a good idea to define a constructor which can take the object of the class
type itself as an argument.
- Finally the golden rule, "Try not to do C programming in C++".
Conclusion
There is no substitute to practice -:)!
|