Previous Table of Contents Next


Debugging Is a Waste of Time

The C and C++ world is awash with slick debuggers. But before you place a debugger high on your list of C/C++ tools, consider this fact: Every minute spent using the debugger is a waste of time — nothing is being produced. The place to control errors in C programs is during production, not by debugging.

This is not to say you shouldn’t have a good C debugger — most compiler products come with one anyway. But don’t plan to use the debugger as a tool to improve your C productivity. That’s a self-defeating strategy.

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.

Reuse It Or Lose It

Although there’s no “silver bullet” for software development, code reuse is about as close as you can come to a technique that dependably reduces development time and increases software reliability. The reason is simple — you will save time, if you can supply a component of an application by reusing an existing one rather than building a new one from scratch. And if the reused component has proven its reliability in previous use, its performance in a new application is likely to be better than a newly created component that undergoes its first production tests in your application.

Most programmers and managers know the value of reusing software components; the problem is they usually don’t have a rich set of suitable components available when they start a new project, so they’re forced to build what they need. More often than not, deadline pressures and limited resources keep newly built components from being implemented so they can be reused on future projects &151; and the problem propagates through another project cycle.

The fundamental barrier to reuse is economic: Reuse pays off only across projects and over time, but requires investment in the short-term. It’s expensive to build and catalog reusable components, so unless an organization has some financial practices that distribute the component supplier’s costs to the consumers of the components, nobody will build for reuse.

The economics of reuse suggest an easy solution: Buy reusable components, if suitable ones are available. One of the undeniable advantages of developing applications in C/C++ is the large number of source and executable libraries available as commercial products. For standard system functions, such as file systems, user interfaces, and communications and connectivity, commercially available products are often of higher quality and lower cost than if you developed them from scratch. These packages are so inexpensive for MS-DOS and Windows environments that a reasonable strategy is to buy multiple products that cover the same areas, try them out in your own program development, and select the product (or parts of each) that satisfies your requirements best.

Although developing your own reusable components is more expensive, it is sometimes necessary for application areas not covered by commercial products. As I mentioned earlier, it’s essential that the organization recognize the cost and value of building reusable components. This may take the form of an explicit method of project accounting, or it may be implicit; for example, by assigning some staff the primary responsibility of “component builder.”


Previous Table of Contents Next