Posted 07 March 2010 - 09:01 PM
Currently, I'm using a similar per-module setup in the C++ coding standard at work.
Originally, I had one header / source file per class. However, this had several disadvantages.
* For instance, this one-by-one setup means many translation units, which is costy, in particular if you use lots of boost or other template magic internally.
* Many (small) translation units also mean a smaller "system headers" to "own code" ratio - which in effect means parsing the same system files many times all over again.
* This also means many include directives at the top of source files, most of which reference to things anyways contained inside a single "module".
*Additionally, older compilers (don't laugh - sometimes we are still down to VC++ 6) do (measuredly) better optimization within the latter setup.
* Finally, I think it helps with documentation of intent: The smallest element of a system typically is not a class (when do you actually use a class standalone...) but a module, which contains a series of interlinked classes. For example, consider a file system: The file system has classes FileSystem, File, and FileNotFoundException. Neither of these is typically used on its own, they depend on each other, so why place them in different translation units or in different headers ?
I think the roots of the "one-class-one-file" paradigm are to be found somewhere within Java programming, where there simply may not be more than one openly available class in each package. This is somehow a complement of the C++ roots: In C, a translation unit typically was a functionality module (i.e. an entire Java package, i.e. a series of classes...)
These days, I pack everything together that forms an entire module (i.e. a file system, a rendering context, a physics context, ...). Hardware-specific elements (... OglContext, W32Window, ...) end up in modules of their own. If the associated source files become too crowded, they can be split up into different translation units, but this needn't necessarily effect the associated headers. If headers become too crowded, this is a typical sign of an overloaded module => the module should be split into subfunctionality.
The module-based header architecture solves all of the problems named above.
Finally, it also gives a clear indication where to place documentation for an entire submodule: Often, documenting single classes within single header files ends up with documentation for the entire submodule in one of the major classes. In a shared module setup, the module documentation can simply be placed at the top of the module header.
The namespace-per-header issue is something I can't comment on in as much detail - we generally use but a few namespaces per project, since this saves typing, and a single project needn't protect its "main" namespace from itself ;)
Hope this helps :)
Cheers,
- Wernaeh
Some call me mathematician, some just call me computer guy. Yet, I prefer the term professional weirdo :)