Search code examples
c++namespacescode-organization

How to better organize the code in C++ projects


I'm currently in the process of trying to organize my code in better way.

To do that I used namespaces, grouping classes by components, each having a defined role and a few interfaces (actually Abstract classes).

I found it to be pretty good, especially when I had to rewrite an entire component and I did with almost no impact on the others. (I believe it would have been a lot more difficult with a bunch of mixed-up classes and methods)

Yet I'm not 100% happy with it. Especially I'd like to do a better separation between interfaces, the public face of the components, and their implementations in behind. I think the 'interface' of the component itself should be clearer, I mean a new comer should understand easily what interfaces he must implement, what interfaces he can use and what's part of the implementation.

Soon I'll start a bigger project involving up to 5 devs, and I'd like to be clear in my mind on that point.

So what about you? how do you do it? how do you organize your code?


Solution

  • Especially I'd like to do a better separation between interfaces, the public face of the components, and their implementations in behind.

    I think what you're looking for is the Facade pattern:

    A facade is an object that provides a simplified interface to a larger body of code, such as a class library. -- Wikipedia

    You may also want to look at the Mediator and Builder patterns if you have complex interactions in your classes.

    The Pimpl idiom (aka compiler firewall) is also useful for hiding implementation details and reducing build times. I prefer to use Pimpl over interface classes + factories when I don't need polymorphism. Be careful not to over-use it though. Don't use Pimpl for lightweight types that are normally allocated on the stack (like a 3D point or complex number). Use it for the bigger, longer-lived classes that have dependencies on other classes/libraries that you'd wish to hide from the user.

    In large-scale projects, it's important to not use an #include directives in a header file when a simple forward declaration will do. Only put an #include directives in a header file if absolutely necessary (prefer to put #includes in the implementation files). If done right, proper #include discipline will reduce your compile times significantly. The Pimpl idiom can help to move #includes from header files to their corresponding implementation files.

    A coherent collection of classes / functions can be grouped together in it's own namespace and put in a subdirectory of your source tree (the subdirectory should have the same name as the library namespace). You can then create a static library subproject/makefile for that package and link it with your main application. This is what I'd consider a "package" in UML jargon. In an ideal package, classes are closely related to each other, but loosely related with classes outside the package. It is helpful to draw dependency diagrams of your packages to make sure there are no cyclical dependencies.