Guidelines for Programming Projects
Programming projects are part of many courses. The primary goals of
these projects is to make you more familiar with course material and to
improve and expand your programming skills - design, coding, testing,
debugging.
Programming Priorities
When you set about to tackle a programming assignment, your priorities in
decreasing order of importance should be:
Correctness
Your code must perform the required operations correctly and handle
"anomalous" input and conditions gracefully. A beautifully
designed and implemented program that does not work or, worse yet, works
incorrectly is, to put it bluntly, a failure. This will become even more
critical after you've graduated. While you will probably get partial credit
for a non-working program here, your future employer will not be so
accommodating. So learn the lesson now - correctness must be your first
priority.
The ranking of the following priorities are somewhat arbitrary and
some courses may consider one of these priorities to be more important
than another. I offer them in order of my general feeling about their
importance.
Comprehensibility
Your code should be well documented and easy to understand - by you as
well as others. This is a prerequisite to maintaining and extending
your code. You should give careful thought to the design of your code
before you begin implementation (in my experience incomprehensible code
often starts off well enough but is badly mangled due to poor initial
design). You should identify those parts of your code that are unique
or potentially confusing and be careful to document those parts
especially well.
One tactic I use is to begin coding by writing my algorithm as a
narrative pseudo-code description. Then I gradually replace the narrative with
code to perform the proper task, and turn the narrative into high-level
comments. Further comments are added to document code that is anything less
than obvious.
Efficiency (aka Performance)
Your programs should be efficient in their use of time and memory. Some
courses (e.g., analysis of algorithms) place greater emphasis on
efficiency than others. However, a program that works slowly is
obviously superior to a (potentially) fast program that doesn't work.
When programming, make it work, then make it work fast. It is quite
easy and common to waste significant programming time optimizing
portions of programs that have little effect on the overall efficiency.
In the words of Dr. Donald Knuth - We should forget about small
efficiencies, say about 97% of the time: premature optimization is the root of
all evil.
Reuse and Extensibility
Programming with extensibility in mind requires you to think ahead to
ways that your code might be used or modified in the future. A key
principle is to make your code as general-purpose as you can (e.g., a
Stack class that can hold objects of any sort is more general than an
IntegerStack class that can only hold instances of a particular class).
Likewise, reuse requires you to factor out those generally-useful
structures and algorithms and package them for reuse. But do not be
over-aggressive - extract reusable components when you discover
something you need to reuse. Overly aggressive decomposition can end up
fracturing your code into too many little fragments.
Elegance
This is a subjective criteria that encompasses the overall beauty of
your design. In some ways, elegance is the sum of the other priorities
taken together. Elegant programs use and reuse appropriate data
structures and algorithms, are well designed and implemented, easy to
read, understand, maintain, and extend. Contrary to what you might
expect, elegant programs rarely use new or novel techniques unless
called for, and program size (e.g., number of commented lines of code)
is rarely a good measure of elegance - squeezing code into as few
lines as possible can be terribly cryptic and nearly impossible to
read, let alone maintain; too much code is also hard to read
and maintain, and can perform poorly. Elegance is about finding
balance. Speaking of the history of Computer Science, the late Edsgar
Dijkstra once said:
I thought that programmers should not be puzzle-minded, which was one
of the criteria on which IBM selected programmers. We would be much
better served by clean, systematic minds, with a sense of elegance.
The order given above does not imply that you should first implement
a correct program with a given data structure, then rewrite your
program with a different data structure to achieve reasonable
efficiency! You should keep all of these priorities in mind as you
design and implement your programs.
I also recommend that you program incrementally. Begin by developing
a minimal set of classes and behavior and incrementally add new
capabilities. This gives you a sense of progress and, in the event
things don't go well, you still have a partially-functioning solution
to a project. However, don't get locked in to an initial implementation
if you find that your program is becoming incomprehensible or difficult
to extend. There are times to redesign and start again.
See this article on
writing "unmaintainable" code for a contrasting approach.
Last modified: ,
by David M. Hansen