Advice on best practice for header file organization? 
Author Message
 Advice on best practice for header file organization?

I'm looking for advice on best practices in the use of header files.  I'm
often mystified by some of the uses of headers in real-world source code
I've browsed.  For example, browsing the python 1.6 sources in soure
navigator reveals a graph of #includes so complicated it defies analysis,
all converging on one, very large, monolithic "python.h" header and then
branching out again.  It's extremely difficult to understand the
organisation of a large system with such a complicated tangle of
dependencies.

I've seen advice on the net to the effect of "don't include headers from
other headers, instead comment what also needs to be included in the
header", but this advice is routinely disregarded, and it's normal practice
to have long chains of #includes in any of the headers for libraries on
Linux -- the glib and gtk headers, for example.

I also notice strange affectations -- the use of underscores to define
"internal" names that are then exported using #defines or typedefs, eg

typedef struct _GtkRequisition    GtkRequisition;

Even I've heard use of the underscore is deprecated, this is very common.

It also often seems arbitrary what gets included in a header -- for example,
certain names and #defines were exported in headers, others included in the
*.c file that includes the header, with the decision seeming, in some cases,
to be arbitrary.  I typically think of headers as providing public
interfaces to a given module, but it's clear many real-world headers are
polluted with module-private names.

This is an issue that seems to be crying out for good advice.
--



Tue, 06 May 2003 03:00:00 GMT  
 Advice on best practice for header file organization?

Quote:

> I'm looking for advice on best practices in the use of header files.  

"Best" is almost always a subjective measure. Different strategies have
different consequences. Choose the one whose consequences you like.

[...]

Quote:
> all converging on one, very large, monolithic "python.h" header and then
> branching out again.  

For a system like Python, that might well be a necessary method. Note
that it's an embeddable/extensible language, i.e. there are headers of
at least two different types: user-visible ones that will be installed
somewhere in the C compiler's #include search path, and private ones,
that will not be made visible outside the Python source tree itself.
I guess that's how this structure came into life.

Quote:
> I've seen advice on the net to the effect of "don't include headers from
> other headers, instead comment what also needs to be included in the
> header",

I personally would call that bad advice. It gains you next to nothing,
at the cost of unnecessarily hard maintenance of the .c source files
that use stuff exported from that header.

My usual rule-of-thumb inside header files is: include exactly those
other headers that declare stuff (types or macros, usually) which is
used by the header file at hand. E.g. if your header declares a
function that takes a FILE * argument, #include <stdio.h> into the
header.

This makes headers self-contained, but still avoids unnecessary cyclic
dependencies of headers on each other.

Quote:
> It also often seems arbitrary what gets included in a header -- for example,
> certain names and #defines were exported in headers, others included in the
> *.c file that includes the header, with the decision seeming, in some cases,
> to be arbitrary.  

The sensible thing in this regard: declare/#define in the header
exactly that stuff which you want to export.  All module-internal
stuff goes into the .c.

--

Even if all the snow were burnt, ashes would remain.
--



Wed, 07 May 2003 03:00:00 GMT  
 Advice on best practice for header file organization?
There is no answer that is good for all cases out there. A single header
is quite good but if it becomes to large then it will become un-readable
(and un-maintainable). Since most projects start low, the original
single header is then splitted into pieces which get included back into
the original single-header file since many older software expects only
one header file to include. And, well, this is what you see in many
header file organizations - it's just history of its growing up.

There is only one advice I like to give based on my personal
observations - if the single header approach has outgrown its time,
and you are going to split it into pieces, then please put the pieces
into a subdirectory. There are occasions, where project.h is just a
shallow file (or even a symlink) to project/project.h then.

Therefore, start low, with a single file, and end up with subdirectory of
pieces. Each piece should be ifdef'd to be processed only "once", and
if the order is important, you may create a loader-header that may has
to have some ifdef-noice to ensure a fine loading-process. Still, there
are quite some other schemes you can use out there, but for many real
projects I would advice you that you shall not let your eyes get
confused by the header file organization - just try to grasp the
history that is evident by it.

cheers
-- guido                                Edel sei der Mensch, hilfreich und gut

--



Wed, 07 May 2003 03:00:00 GMT  
 Advice on best practice for header file organization?

Quote:
>> I've seen advice on the net to the effect of "don't include headers
>> from other headers, instead comment what also needs to be included
>> in the header",

> I personally would call that bad advice. It gains you next to
> nothing, at the cost of unnecessarily hard maintenance of the .c
> source files that use stuff exported from that header.

The only reasonable argument I've seen in favor of this approach is to
avoid silently bringing in unexpected symbols/definitions. For
example, if foo.h contains (in part):

#include <stdio.h>
extern int init_foo(foo *pfoo);
extern int init_foo_from_args(foo *pfoo, int bar, char const *baz);
extern int init_foo_from_saved_file(foo *pfoo, FILE *fp);

then suppose some .c file includes foo.h in order to use init_foo().
The programmer can then unwittingly use (say) sprintf() without
including stdio.h in the .c file, and the compiler won't complain.
If later on the code that calls init_foo() becomes unneeded, removing
the inclusion of foo.h will suddenly cause the file to not compile.

This is a pretty simplistic example, and one that's easy to fix, but
in a large code base with lots of different header files, it can make
keeping an accurate list of #include's rather tricky, leading to
time-consuming effort to track down symbols when removing a header
file causes breakage, or (far more likely) .c files to evolve a
strange list of non-intuitive inclusions which nobody wants to edit.

Despite all that, I fully agree that it's almost always better to make
each header file stand alone.

b
--



Fri, 09 May 2003 14:28:37 GMT  
 Advice on best practice for header file organization?


Quote:
> I'm looking for advice on best practices in the use of header files.

The advice from the  other posters responding to you question looks good
to me.  To this I would add:

1) Don't put anything in a header file that isn't meant to be shared.

I've seen too many programmers use the rule "All #defines and
typedefs belong in a header.

2) Put prototypes for all extern functions defined in a .c file in a .h
file with the same name.  Include that file in the aforementioned .c
file.

E.g., if you have foo.c that defines two extern functions init_foo and
use_foo as well as some static functions, put prototypes for init_foo
and use_foo in foo.h and include foo.h in foo.c.  Don't prototype the
static functions unless you have to (e.g. if the functions are mutually
recursive) and even then, do only in the .c file -- static prototypes
aren't meant to be shared.

3) Put guards around your header files to ensure they're included only
once.

4) Define everything only once.

These last two seem obvious, but others have argued with me about them.

Good luck,

I Don't Do Windoze
--



Sun, 11 May 2003 03:00:00 GMT  
 Advice on best practice for header file organization?

Quote:

> The sensible thing in this regard: declare/#define in the header
> exactly that stuff which you want to export.  All module-internal
> stuff goes into the .c.

A module is an implementation file e.g. "foo.c" ?

What do You think about
internal header files  (only for the module)
and
external  header files (for the module and as interface description ?)

Markus
--



Mon, 26 May 2003 14:55:01 GMT  
 Advice on best practice for header file organization?
: A module is an implementation file e.g. "foo.c" ?

: What do You think about
: internal header files  (only for the module)
: and
: external  header files (for the module and as interface description ?)

I'd disagree.  If a single .c includes a .h, there is no point in making it
a .h.  Headers are STRICTLY for shared info - types, externs, prototypes,
macros, and possibly inline functions.  My baseline for making a .h is "How
many files might need to know this?"  If the answer is "just this one" - it
goes into a .c.

Of course for a "module" whcih spans .c files, local headers are fine.

--
As long as you're a man, you're what the world will make of you.
Whereas if you're a woman,
You're only what it seems.
        --Stephen Sondheim - "Passion"
--



Mon, 26 May 2003 03:00:00 GMT  
 Advice on best practice for header file organization?

Quote:


>> The sensible thing in this regard: declare/#define in the header
>> exactly that stuff which you want to export.  All module-internal
>> stuff goes into the .c.

> A module is an implementation file e.g. "foo.c" ?

Yes. Or more precisely: a module is a pair of an implementation file
and it's header file. What the Pascal people would call a 'Unit'.
Interface plus Implementation makes a module.

Quote:
> What do You think about
> internal header files  (only for the module)
> and
> external  header files (for the module and as interface description ?)

Little. If a header is only ever #included by one single .c file,
there's not much point in spawning it off to a separate file, in the
first place.  Its content can just as well go right into that .c file
itself.  Headers are for communication among different modules, not
for a module speaking to itself.

IMHO, 'internal' or 'private' headers only really make sense in the
context of libraries that want to distinguish between their external
interface and some internal interfaces that are shared among several
modules that make up the library. The same reasoning would hold if you
group a larger application into 'super-modules' or 'layers', each of
which would behave like a library, or even be built as one.

In such situations, there'll be one or more header files that are
'internal' or 'private' to the super-module, and usually a single
external header that contain only stuff which the super-module as a
whole wants to export.

--

Even if all the snow were burnt, ashes would remain.
--



Mon, 26 May 2003 03:00:00 GMT  
 
 [ 8 post ] 

 Relevant Pages 

1. Good practice using header files.

2. Red-Black trees - Advice on code organization

3. Advice on project organization in C# + VB environment

4. Advice on making your own header file

5. Best Practice - OO

6. Best practice in Windows Forms?

7. Data access 'BEST' practice

8. Best Practices Question - Interacting with VB, C#, C++

9. Best Practices

10. Software Metrics Best Practices

11. finalizers: best practice

12. Best practices for object serialization?

 

 
Powered by phpBB® Forum Software