- Should I have one file per class? Should I have one folder per inheritance branch?
Thanks to code indexers I often forget how and where the code is actually on disk.
File per class to me makes no sense. Especially in C++ I tend to have lots of small utility classes.
Generally: component is a directory. All components live under the same root. (This is more of an unfortunate consequence that I have to use make as a build chain. With better build systems like SCons which support recursion natively it doesn't really matter.)
I stick to the general principles of reusability, sufficiency and cohesion (as per Booch) for grouping classes. It happens often that I put the code into a shared/static library to facilitate integration into the build chain, thus for the grouping of classes into components/directories I use principles very similar to the ones used for grouping methods in the classes.
- Should I have an 'include' folder that contains my header files, or should my header files be in the same folder as my .cpp/.c files?
I personally prefer headers in the same directory with source files.
Notable exception are the public headers which define the public interface of the component. Those I put into the include/compname/ sudbirectory: then it is easy to see that the change I'm doing/about to check-in is going to have impact on other components.
Obviously other components are allowed to include only the headers from the $ROOT/compname/include/compname/ subdirectory. (Having compname/ dir under include/ makes include directives in other files to look like #include "compname/headername.h"
what helps readability and also prevents header name collisions.)
- I plan on regularly adding more classes (adding more levels to the inheritance tree). At the lowest level in the tree, implementations are likely to be relatively unrelated but still override the same virtual functions. Should such unrelated implementations reside in the same folder?
Inheritance is rarely relevant to the physical layout of files.
Base classes are modified seldom since they have little impact on the business logic. Top level classes is where the meat of the logic is and it is going to be worked on by many people for a long time. Thus the basic classes, reused by many components, deserve to have their own component. Simply to move them out of sight.
That brings another important point. How many people are going to work on the project? On one man project you can do pretty much whatever you want the way you want. On a team with 3+ people, the component/module would serve as a natural container for one person to work independently on it. Thus the form project takes may not depend on how classes hierarchy looks - rather the places of code which are going to be worked on most should be sufficiently isolated from each other. And class hierarchy if needed should accommodate for that: you should avoid cases when one person works on a base class - another on its descendant. That is the case where aggregation may be considered instead of inheritance.