tags:

views:

142

answers:

4

My C++ project is growing larger. We are also moving to using cmake for building now. I want to divide the application into libraries so that they can be linked for testing, preparing the application package, etc. Right now I would divide my code into libraries as follows:

  • core
  • GUI
  • utilities (these are used by core and other components)
  • io (xml parsing/outputing using print functions of classes in core)
  • tests (unit tests)
  • simulator (tests the core)

An alternative would be to divide based on the directory structure - one library for each directory. But from my past experience it leads to too many libraries and then library dependencies become tough to handle during linking.

Are there any best practices in this regard?

+1  A: 

I like starting from a package diagram that only has one way arrows.

http://www.agilemodeling.com/style/packageDiagram.htm

Your list looks like a good start.

Lou Franco
+5  A: 

Sit down with a piece of paper and decide your library architecture.

The library should be designed as a set of levels.

  • A libary on level A (the base) should have dependencioes only on system libraries and only if it must on libraries on level A.
  • A library on level B can have dependencies on libraries at level A and system libararies and only if it must on libraries on level B.
  • etc

Each library should represent a complete job at its particular level. Things at lower level generally have smaller jobs but lots of them. A library at a higher level should reresent a complete task. ie don't have a lib for windows objects and a lib for events. At this level the job here is handline all interaction with a window (this includes how it interacts with events).

You seem to have identified some resonable functional groups. The only one that see a bit suspicious is io. If you truly have some generic IO routines that provide real functionality fine. But if it is just grouping the IO for a bunch of different objects then I would scrap that (it all depends on the usage).

So the next step is to identify the relationship between them.

As for using directory structures. Usually everything in one directory will be present within the same library, but that does not exclude the posability of other directories also being present. I would avoid putting half the classes in directory in libA and the other half of the classes in libB etc.

Martin York
By io, I meant parsing and outputting XML (or some other format) etc. io would use the factories and printing functions from classes in core.
Amit Kumar
I am not saying it is wrong. You have to look at the code and make a judgment call. If the Factories and printing functions are substantial enough to warrant a lib fine.
Martin York
+1  A: 

Seems reasonable.

I'd query what your unit_tests library is supposed to do. Given a collection of "projects" building libA, libB, libC... I'd expect to see some matching projects testA testB testC (whether they build libraries or executables depends whether the built tests run standalone or are loaded into some test runner).

I'm also slightly wary of "utilities" libraries. These seem to have a surprising ability to cause pain and suffering in the long run. For example, maybe your IO library has no other dependency than the utilities library. One day you want to reuse the IO library in another project on another platform. Only problem is, you now also have to port all of the utilities library (90% of which IO doesn't use), or disentangle the 10% of it which IO actually depends on. Sometimes it's better to have libraries be a bit more dependency free, at the cost of some code duplication.

timday
I agree with what you say about the "utilities" library. But hopefully the example you give would be lesser of a problem as we already build on windows with visual studio compiler and linux with g++.
Amit Kumar
+2  A: 

You should have a read of Large-Scale C++ Software Design by John Lakos.

You may not be able to read it before you start your work, but you should put this book on your list.

Otherwise Martin York's advise is sound.

One more thing though, I would recommend picking up a tool like doxygen that can give you dependency diagrams of your code base. If your bothering to do this type of restructuring you should rid yourself of circular dependencies between your libraries. Lakos describes a lot of ways to cut dependencies - some obvious, some less so.

Craig W. Wright
I find the book by Lakos overly verbose. In the book it is difficult to separate out clean, useful and non-intuitive tips from unclean, useless and obvious tips. I'd be interested to know if somebody has extracted the good parts of the book.
Amit Kumar
Oh yes, it's quite verbose! To the point of being tedious. On the other hand there are some real gems in there, and no, I dont' know of a more concise version. :(
Craig W. Wright