tags:

views:

130

answers:

4

I'm in the planning stage of a relatively large (10k+ lines) project with several classes (30+) and several levels of class inheritance (5+).

What is the best (or most conventional) way to lay out my project in terms of file and folder structure?

  1. Should I have one file per class? Should I have one folder per inheritance branch?
  2. 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?
  3. 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?

Thanks,
Advait

+5  A: 

1) Yes. One file per class in most cases is a good idea. Unless you have a really trivial class, or a collection of abstract interfaces, use one class per file.

2) Try to separate things. Usually in a project that big, you'll have some code that are specific to some parts, others that are common to many parts. Those that are very limited in usage, just keep it 'locally'. Others, put is in include dirs.

3) No need really. It is usually better to keep classes (i.e. files) which are closely related, close together; I'd try to keep them together, unless you have something like a generic interface, in your global includes, and specific inheritance inside a module dir.

Gianni
well, it's a bit simplistic to say "One file per class is always a good idea". "Often" or "Usually" would be enough.
kriss
@kriss. Good point. Fixed.
Gianni
For more on (2), consider folders to group classes by behaviour -model/view/controller, interfaces, exceptions, tests, UDT's, etc.
JBRWilkinson
+1  A: 

1) This looks more like Java type - but if your classes don't take more than 4 lines, mayn't be a good idea. But if later on you want to extend an already existing class, one file for each class is a good idea.

2) That's a choice for you, how to arrange you .h files and .cpp files. But if lot of dependencies are to be for a single class, it seems reasonable to put related ones in one place.

3) Maybe. But put your base classes/interfaces at a central part and derive around it.

DumbCoder
A: 

The idea is simple. Imagine that you are drawing a dependency graph between you classes and choose a layout that minimize dependencies between files.

This is true at file level, and this is also true at folder level but for larger code units.

You should also be aware that compiler's doesn't optimize code well between files (problem is linker). So if you have tightly coupled classes, keeping them in the same file is good for performance. Another solution when it is possible it to make them headers only classes.

Where to keep headers ? If you are providing a library you will have to put them in usual system directories. But as C++ headers contains code, for other cases keeping them with cpp files is usually the best solution. It makes editing both hpp and cpp at once simpler.

kriss
A: 
  • 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.

Dummy00001