Department of Engineering

IT Services

Program Development

Stroustrup writes that the last section of his book aims

to bridge the gap between would-be language-independent design and programming that is myopically focussed on details. Both ends of this spectrum have their place in a large project, but to avoid disaster and excessive cost, they must be part of a continuum of concerns and techniques.

Programs vary considerably in their composition. I've seen these figures quoted

  • Coding takes 10% of the total time. Debugging takes 50%.
  • The Graphical User Interface is 80% of the code
  • Error handling can be 50% of the code

Complexity is the enemy, so

  • Divide and conquer.
  • Use modules - namespaces or files (helps the optimiser too).

Don't re-invent the wheel

  • Copy models
  • Adapt existing parts
  • When making new parts design them for re-use

Style

It helps if you decide upon a uniform style for writing code. It's common to suggest that for all except the most trivial classes it's wise to define

  • a void constructor -
  • a copy constructor - to create a new object using values from an existing one. Use call-by-reference to avoid infinite recursion.
  • the assignment operator - that returns a reference.

And then there's the "the rule of three" - if you write any one of a copy constructor, copy assignment operator or destructor, then you will almost certainly need to write all three for your class to function properly.

Stanley Lippman in Dr.Dobb's Journal, October 99, (p.40) noted that unnecessary definition of these functions is likely in practise to make the code bigger and/or slower - he got a 40% speed improvement by removing all 3 from a piece of code, the compiler's default alternatives being more efficient.

When deriving classes

  • if using public inheritance, most base class member functions should be declared virtual to ensure that the derived class customisations will override the base class behaviour even in a context where a base class object is expected.
  • use virtual inheritance if you are not especially concerned about performance or if you might use multiple inheritance later.

Makefiles

If you have many source files you don't need to recompile them all if you only change one of them. By writing a makefile that describes how the executable is produced from the source files, the make command will do all the work for you. In the 1A/1B courses makefiles were created by the xcc program, but you may well need to write your own eventually.

The following makefile says that pgm depends on two files a.o and b.o, and that they in turn depend on their corresponding source files (a.cc and b.cc) and a common file incl.h:

   pgm: a.o b.o
       aCC a.o b.o -o pgm
   a.o: incl.h a.cc
       aCC -Aa -c a.cc
   b.o: incl.h b.cc
       aCC -Aa -c b.cc

Lines with a `:' are of the form

target : dependencies

make updates a target only if it's older than a file it depends on. The way that the target should be updated is described on the line following the dependency line (Note: this line needs to begin with a TAB character).

Here's a more complex example of a makefile for a program called dtree. First some variables are created and assigned. In this case typing `make' will attempt to recompile the dtree program (because the default target is the first target mentioned). If any of the object files it depends on are older than their corresponding source file, then these object files are recreated.

The targets needn't be programs. In this example, typing `make clean' will remove any files created during the compilation process.

# Makefile for dtree
DEFS =  -O2 -DSYSV
CFLAGS = $(DEFS) -O
LDFLAGS = 
CC = aCC
LIBS = -lmalloc -lXm -lXt -lX11 -lm

BINDIR = /usr/local/bin/X11
MANDIR = /usr/local/man/man1

OBJECTS_A = dtree.o Arc.o Graph.o 	#using XmGraph

ARCH_FILES = dtree.1 dtree.cc Makefile Dtree Tree.h TreeP.h \
   dtree-i.h Tree.cc Arc.cc Arc.h ArcP.h Graph.cc Graph.h GraphP.h

dtree: $(OBJECTS_A)
        $(CC) -o dtree $(LDFLAGS) $(OBJECTS_A) $(LIBS)

Arc.o:	Arc.cc
        $(CC) -c $(CFLAGS) Arc.cc

Graph.o:	Graph.cc
        $(CC) -c $(CFLAGS) Graph.cc

dtree.o:	dtree.cc
        $(CC) -o dtree.o -c $(CFLAGS) -DTREE dtree.cc

install: dtree dtree.1
        cp dtree $(BINDIR)
        cp dtree.1 $(MANDIR)

clean:
        rm -f dtree *.o core tags a.out