C Language

Order Out of Chaos

With C and C++ development, some form of source and binary code version management is essential. Both languages encourage building applications by combining many small components, either source "header" files, independently compiled modules, or executable libraries. Without some means of control, C development can rapidly get out of hand.

The broad area of software configuration management (SCM) covers a variety of tools and practices for tracking changes to software, especially version management. The most important practice is rigorous "check-out/check-in" of source code that's being modified. A number of tools (e.g., the Unix Source Version Control System - SVCS, and Intersolv's PVCS Version Manager product) let you place all source code in a shared "archive" and control the check-out of source files. When a source file is checked out to be modified, a "lock" is recorded in the archive so that no one else can simultaneously modify the same file. (Most tools provide a facility for "branching" into two parallel revision tracks, if necessary.) Subsequently, a revised version of the source file can be checked in, possibly after undergoing additional testing or other quality assurance review.

Controlling source is only part of what's required when code is shared among people and projects. A facility to control versions of binary code (object or executable) is important so that programmers have a stable base from which to reuse shared code. With proper tools and procedures, it's relatively straightforward to revise the implementation of shared binary code, as long as the interfaces don't change or are upwardly compatible. Coordinating incompatible changes to interfaces is much more difficult, however.

When an implementation changes but the interface remains the same, the most that's usually required is to recompile programs that depend on the revised code. Automated "make" utilities can simplify this process. With a typical make utility, object dependencies are stored in a file. When the make utility reads a file of dependencies, it checks the time stamp of each object and re-creates those objects that have an earlier time stamp than any object upon which they are dependent. "Make-make" utilities automate the rebuild process further by scanning C source code to derive the dependencies and then building the dependency file used by the make utility.

When an interface changes, modules using the interface often have to be revised, too. "Impact analysis" tools (a fancy word for a type of cross-reference tool) help by listing all modules that use a particular interface. It's then up to the programmer to make the necessary revisions. The final step is often the most difficult: synchronizing the introduction of a new interface with the implementation of revised older programs that use the new interface. Make utilities can help simplify the production of new versions, but scheduling tests and upgrades of production systems remains largely a manual management task.

SCM tools are generally available on most platforms that have C and C++ compilers. Often, these tools are packaged with the compiler products themselves. These tools shouldn't be viewed as optional C programming "goodies"; they're essential for any production C/C++ development. The time to acquire and start using these tools is the day you get the C or C++ compiler, if not sooner. Don't wait until you have hundreds of source files before you start managing them.