Stop writing header files

Although one of my favorite languages, C++ has a number of issues that make it difficult to write and maintain. One of the worst is its compilation model: you import declarations using fragile literal text inclusion (#include), and you have to waste your time keeping these declarations redundantly in sync with the source files. Templated function definitions require even more redundancy. The same information is really in both places - this violates The Pragmatic Programmer 's oft-repeated tip 11, DRY (Don't Repeat Yourself).

Worse yet, the line between what goes in the header file and source file looks like it was drawn by a drunkard. You have an inline function? Put it in the header file. You want to make it not inline anymore? Put it in the source file. You want to template it? Back in the header file it goes. In C there are additional issues, since a function definition that is out of sync with its prototype results not in a compile-time error but an implicit declaration and a mysterious link error.

So what's the solution? The best solution is to simply stop writing header files. Instead, write the source file, mark the nonredundant information that needs to go into the header, and then use a build tool to generate your header based on this information prior to compilation. The header can never be out of sync, you can make changes more quickly, you drop the number of lines of code you have to actively maintain, and everybody is happier.

Of course, that sounds like a lot of work - especially the part that involves writing a tool that has to parse a nontrivial subset of C++. Luckily, some fellow victims out there have already produced tools that do this. The best one I've come across so far is Lzz: The Lazy C++ Programmer's Tool, a tool that allows you to lay out function definitions in C++ code in much the same way as Java or C# (within the class), and then it produces both the header and source files. Here's a sample:

 class A {
  public:
    inline void f (int i) {
        if (i <= 0)
            g();
        else
            g(i);
    }

  private:
    void g (int j = 0) {
        if (j > 0)
            g(j - 1);
    }
};

The function f ends up in the header file and g in the source file. If I remove the "inline" keyword, however, f gets moved to the source file. Don't have to worry about it.

Lzz has some limitations though, so make sure you read the documentation.  It also includes a couple interesting extensions called Lazy classes and Lazy functors that I won't get into here. Try it out and see if you're willing to kiss your header files goodbye.

Derrick Coetzee
This posting is provided "AS IS" with no warranties, and confers no rights.

P.S. For those of you waiting on the Bloom filter code, I've got something written and I'm just waiting for approval from the powers that be. Hang in there.