Fog Creek Software
Discussion Board

cyclic includes

What do others think about cyclic includes as in

a.h includes b.h
  b.h includes a.h

Is this ever justified?

Keith Paton
Friday, March 8, 2002

Why do you want to know? I mean, you will probably agree that it is ugly as hell. It causes major problems as soon as there are really dependencies between the two headers. If there are no real dependecies between the two headers, why do it?

I can think of no situation where it makes much sense to do it that way. If it does not make sense, it is not really justified, is it? (I just read a sentence the other day I liked so well that I put it on our whiteboard so I have to look at it all the time. It says: "Never do anything dumb on purpose")

If you are dealing with a big project and lets say function declarations are organized in a way that would need you to do something like that, think about refactoring (or at least reordering the functions) if this is possible.

Thinking about it, there might be situation where you have to live with something like that because you are using other peoples code and are not allowed or able to change it, but if it is possible for you to do something to prevent cyclic dependencies, then by all means do so.

Jutta Jordans
Friday, March 8, 2002

What Jutta said :)

"Large-Scale C++ Software Design"

Mike G.
Friday, March 8, 2002

Why do I want to know?

This cyclic dependency breaks one of the Lakos rules mentioned above.

I am glad to find that others also think the cyclic dependencies need to be detected and fixed.

My auditing tools extract all sorts of relations from C and C++ code and point out all cyclic dependencies and other breaches of the Lakos guidelines.

The tools I devised to do this are described in a recent article in Dr. Dobbs Journal.

Keith Paton
Friday, March 8, 2002

Lakos' "Large Scale C++" book is great. Refactor a.h and b.h so their common elements are in a new file c.h.

Banana Fred
Friday, March 8, 2002

The main reason Lakos objects to cyclic anything (but especially includes) is that in his model of development, every component is exactly on header, on source file, and one test driver.

By making sure there are no cycles in the system, it's possible to find a hierarchy of these components such that any component only depends either on a) nothing else in the system or b) only other tested components in the system.

Even if you think you can't afford to test every one of your components (and you'd have a tough time convincing JL of that), adhering to that kind of structure will make your design cleaner, your debugging simpler, and even have compile and link benefits.

Oh, the other simple rule: make sure that in a.cpp, the first non-comment/non-blank line does
#include "a.h"

That makes sure you don't have any wierd include order dependencies, like a.h only working if the .c file included z.h first.

Mike G.
Friday, March 8, 2002

One approach that is used in the standard libraries is to prevent a include file from being included twice. This is done by checking for a preprocessor variable and only including the code if the variable is undefined.  It may not be elegant but it prevents problems.

John McQuilling
Sunday, March 17, 2002

*  Recent Topics

*  Fog Creek Home