Ten Essential Development Practices
by Damian Conway
|
Pages: 1, 2, 3, 4, 5, 6, 7, 8
Of course, the specific details that your templates provide may vary from those shown here, according to your other coding practices. The most likely variation will be in the license and copyright, but you may also have specific in-house conventions regarding version numbering, the grammar of diagnostic messages, or the attribution of authorship.
4. Use a Revision Control System
Maintaining control over the creation and modification of your source code is utterly essential for robust team-based development. And not just over source code: you should be revision controlling your documentation, and data files, and document templates, and makefiles, and style sheets, and change logs, and any other resources your system requires.
Just as you wouldn't use an editor without an Undo command or a word processor that can't merge documents, so too you shouldn't use a file system you can't rewind, or a development environment that can't integrate the work of many contributors.
Programmers make mistakes, and occasionally those mistakes will be catastrophic. They will reformat the disk containing the most recent version of the code. Or they'll mistype an editor macro and write zeros all through the source of a critical core module. Or two developers will unwittingly edit the same file at the same time and half their changes will be lost. Revision control systems can prevent those kinds of problems.
Moreover, occasionally the very best debugging technique is to just give up,
stop trying to get yesterday's modifications to work correctly, roll the code
back to a known stable state, and start over again. Less drastically, comparing
the current condition of your code with the most recent stable version from
your repository (even just a line-by-line diff) can often help you isolate your
recent "improvements" and work out which of them is the problem.
Revision control systems such as RCS, CVS, Subversion, Monotone, darcs,
Perforce, GNU arch, or BitKeeper can protect against calamities, and ensure
that you always have a working fallback position if maintenance goes horribly
wrong. The various systems have different strengths and limitations, many of
which stem from fundamentally different views on what exactly revision control
is. It's a good idea to audition the various revision control systems, and find
the one that works best for you. Pragmatic Version Control Using
Subversion, by Mike Mason (Pragmatic Bookshelf, 2005) and Essential
CVS, by Jennifer Vesperman (O'Reilly, 2003) are useful starting
points.
5. Create Consistent Command-Line Interfaces
Command-line interfaces have a strong tendency to grow over time, accreting new options as you add features to the application. Unfortunately, the evolution of such interfaces is rarely designed, managed, or controlled, so the set of flags, options, and arguments that a given application accepts are likely to be ad hoc and unique.
This also means they're likely to be inconsistent with the unique ad hoc sets of flags, options, and arguments that other related applications provide. The result is inevitably a suite of programs, each of which is driven in a distinct and idiosyncratic way. For example:
> orchestrate source.txt -to interim.orc
> remonstrate +interim.rem -interim.orc
> fenestrate --src=interim.rem --dest=final.wdw
Invalid input format
> fenestrate --help
Unknown option: --help.
Type 'fenestrate -hmo' for help
Here, the orchestrate utility expects its input file as its
first argument, while the -to flag specifies its output file. The
related remonstrate tool uses -infile and
+outfile options instead, with the output file coming first. The
fenestrate program seems to require GNU-style "long options:"
--src=infile and --dest=outfile, except, apparently,
for its oddly named help flag. All in all, it's a mess.
When you're providing a suite of programs, all of them should appear to work the same way, using the same flags and options for the same features across all applications. This enables your users to take advantage of existing knowledge--instead of continually asking you.
Those three programs should work like this:
> orchestrate -i source.txt -o dest.orc
> remonstrate -i source.orc -o dest.rem
> fenestrate -i source.rem -o dest.wdw
Input file ('source.rem') not a valid Remora file
(type "fenestrate --help" for help)
> fenestrate --help
fenestrate - convert Remora .rem files to Windows .wdw format
Usage: fenestrate [-i <infile>] [-o <outfile>] [-cstq] [-h|-v]
Options:
-i <infile> Specify input source [default: STDIN]
-o <outfile> Specify output destination [default: STDOUT]
-c Attempt to produce a more compact representation
-h Use horizontal (landscape) layout
-v Use vertical (portrait) layout
-s Be strict regarding input
-t Be extra tolerant regarding input
-q Run silent
--version Print version information
--usage Print the usage line of this summary
--help Print this summary
--man Print the complete manpage
Here, every application that takes input and output files uses the same two
flags to do so. A user who wants to use the substrate utility (to convert that
final .wdw file to a subroutine) is likely to be able to guess
correctly the required syntax:
> substrate -i dest.wdw -o dest.sub
Anyone who can't guess that probably can guess that:
> substrate --help
is likely to render aid and comfort.

