Node:How to Code, Next:How to Format, Previous:How to Implement, Up:Top
A program consists of different libraries, and a library consists of different object files (built from different source files). The following is not only true for the relationship between libraries, but also for the relationship between the different sources of a library, as well as the different sources of a program.
If every module can be understood without reading the source of the other modules, people will understand the whole program better. If every module can be tested without relying on other modules, your code can get more stable. And, if every module can be debugged without digging through all the other code, you will be able to fix bugs much faster than otherwise.
Avoid circular dependencies in your modules. Avoid dependencies on too many other modules in a single module. Avoid modules that are tied together too strong.
For C, the header files are the faces of your modules. If you put something in a header, you have to expect that people rely on it. Don't put implementation specific stuff in a header. Don't define structures in your header - define the structure in the main source, and simply put a type definition in the header, to make your structures opaque.
As every source file is a `low-level module', every source file must have it's own header if it exports symbols that other source files of the same `high-level module' (library or application) uses. Don't write a `big' header file in which you define all symbols that are shared among your library or application, as that would make the internal dependency structure of your modules very unclear.
And, of course, protect all headers against multiple including.
The #include
preprocessor directives are a way of documenting
dependencies. Don't include what you don't need. Explicitly include
every header you directly depend on, even if it's implicitly included
in another header.
Be careful to use #include<...>
for system headers and headers
that are external to your project and #include "..."
for your own
headers.
In header files, only include other headers when the code in this header needs the other header. Foreign headers you include in the header of your library have to be present on every system where your library should be used.
In source files, include all headers the source depends on, even those already included in the source's own header. This documents clearly what your source depends on.
If your project has a global configuration file (like autoconf's
config.h
), this must be included in every source file, and it
must be included as the very first line of your code after
comments, so that all other header files can react on the
defines. config.h
may only include #define
's. Nobody
expects code in such a file. Don't include config.h
in a header
file, unless you want to force all projects that use your header to have
a config.h
, too.
Next should be your source's own header file (where this source exports
its external symbols). By putting no other includes before this, you
implicitly check whether your header file is self-contained, i.e. if it
contains all #include
's it needs to compile.
Then, include all needed header files that are external to your project, with the most usual ones first. Last, include the needed header files of the other modules of your project.
Never put any code before the #include
's. Nobody searches them
somewhere else as at the very top of your source or header file.
Nobody expects real code in files that end in .h
.
When you write a module, you will write code to test it. That code is a
part of the module. Put it in it's own file, document it, and make it a
program that others can use to test if the module behaves correctly on
their system. GNU Automake provides a very good means for running
automatic tests when a program is built with make check
.
Choose a prefix for a module, and use that prefix for all symbols in
that module. If the module prefix is foo
, then all public symbols
of that module should start with foo_
, and all private symbols
with _foo_
.
If the module foo defines a structure bar, name the structure tag
_foo_bar
, define the structure tag in the main source, and define
a type foo_bar
in the header. Name all the functions operating on
this structure beginning with foo_bar_
. For example, name a
function that frees the memory of the structure, foo_bar_free
.
Well, that's the reason why we have static symbols anyway, isn't it?