Programming Standards for Ma128a
Part of the intention of this course is to teach some programming techniques
and provide programming experience. Since we also have a lot of other
topics to teach, we can't do as complete a job as courses
like E77 or CS61A/B/C devoted to programming, but we still hope to
teach you the difference between good code and bad code, and a bit
about testing.
Fortunately, our CS61B colleagues have written some detailed material on
coding, testing and debugging styles. Though it is oriented around Java
and C, most of it applies to good code written in any language,
including Matlab and Fortran. I recommend reading
General Guidelines for Programming Projects (in postscript)
(or the pdf version) for details.
But here are some general guidelines.
Programming Style
Write your code with the reader in mind. In other words, pretend that
you (or someone else) will want to look at it again in 6 months and want to
use it and possibly modify it. So you should make it as easy to
read and understand as posssible. So document it well. Here are
standards to do that:
Testing
Test your code thoroughly. Though testing can only show the presence of
bugs, not their absence, it is a major way to gain confidence. Depending
on the language you use, it may have a built-in debugger that lets you
"single-step" through the program, stop at a certain line in the code,
examine and change values of variables, and continue executing, etc.
Use such a debugger if it is available, otherwise use print statements
in the form "if (debug>0), `print some data', end", where debug is
a flag you can set. For large programs with many parts, you should
both test the parts to see if they behave as expected, and test the whole
thing ("black-box testing"). The trouble with just doing black-box testing
is that you may not even execute all the lines of code you have written.
Picking test cases is hard work. You have to get into a nasty mood,
pretend that the program is your adversary, and try to think of things
that will break it. In the real world, testing and coding is sometimes
done by different people or teams to make this adversarial approach work better.
The idea is to think of inputs that are in some sense as hard as possible,
right at the boundary of the legal set of inputs that the program claims
it will work on.
In numerical programs, it is often challenging to say exactly what this boundary
is. For example, it is often possible to break a code by putting in
data all near the overflow threshold or underflow threshold, so that
the intermediate computations quickly over/underflow. Or the user may
want the zeros of a polynomial that you can't evaluate with any accuracy
anywhere in the search interval.
A really robust code might try to detect and deal with all such possible
nasty cases, but such code is hard (and expensive) to write. As one example,
a state-of-the-art library for solving linear algebra problems called
LAPACK (for Linear Algebra PACKage)
includes all its test code as part of the publically available software,
and there is more test code than actual library code.
So while we will study the limits of numerical algorithms in this class,
we will not expect you to write really "bullet-proof" code that deals with
all possible nasty inputs. We will expect you to make and describe
a good-faith effort to try a lot of examples that you believe to be hard
examples. Your ability to think up hard examples is a measure of your
understanding of the algorithm.
What you should turn in
For your programming assignments, you should turn in the following items.
Each one will count 1/3 of the grade.
Doing your own work
In the
Course Outline we said that you could work in groups, but each person had
to turn in his or her own work. For the last assignment, some people turned
in joint assignments, which is not what we intended. So to make it perfectly
clear, you are not to turn in joint assignments, and in the future
only 1/n-th credit will be given to each member of an n-person group turning
in one assignment. In your assignment, you need to identify the other group
members, explain briefly how you split the work. The purpose of this policy is
to encourage you to learn from one another, but to insist that each person
learn all the aspects of the assignments, including programming, documenting,
analyzing and testing.