Some Suggestions on Programming Style
I expect that by the time you take this course, you will
have designed and written
sufficiently many programs of "reasonable" size that you won't need
any hand-holding when it comes to writing code. I personally don't
particularly care whether your program design and code are good, bad, or
ugly, as long as they meet the specifications given. I should
point out, just the same, that the project consists of several
programming assignments of significant size, each of which builds on
all of those that came before it. This means that even though
I won't impose any style requirements, it's in
your best interests to make your code easy to understand, debug,
maintain, and change as the project progresses—in other words, to
follow the rules of good programming you have been taught in earlier classes.
What follows are some simple suggestions that may help in this regard.
-
Code that works is better than code that doesn't.
-
First, get your program working with simple code and algorithms that
work correctly, i.e., meet the spec. Then, if you find its performance
unacceptable and there's enough time left, profile the code to
see where improvements need to be made, and tune your code appropriately.
All too often, students obsess prematurely on efficiency and refuse
to consider simple approaches (e.g., a recursive routine to traverse a tree)
on the grounds that they're "too inefficient." This is almost
always a mistake.
-
Code that works on some inputs is better than code that works on none.
-
Instead of trying to write code for an entire programming assignment
all at once,
I find it easier to work ``outside-in'' : i.e., first write a program
that works on the outer levels of the syntax, e.g., declarations.
When this is done, get simple functions -- say, those with no locals
or body statements -- to work. Then add locals and/or simple statements,
after that simple expressions, then more complex expressions, etc.
This way, even if you run out of time before you've implemented
everything, you stand to get some partial credit for the pieces you have working.
-
Code that is easy to understand and modify is better than code that isn't.
-
As the project evolves, the needs of different parts of the code may
change. It isn't always possible to anticipate all such needs
(for example, when doing the
type checking assignment,
we will not have covered code generation issues, so you may not be able
to anticipate all of the symbol table requirements that may arise
during later assignments). This
means that sometimes you may have to go back and make changes to code
you had written for an earlier assignment. Write your code in a way that
simplifies the task of going back and modifying code you wrote earlier:
-
Write clean, structured, well-commented code that is easy to understand.
(This will turn out to be important when you're trying to figure out what
you were thinking when you wrote that routine at 3 AM after a week of not
much sleep.)
-
Design your code in a modular fashion, so that parts of it can be changed
with minimal effect on other parts.
In particular, try to use ideas from abstract data
types as far as possible, so that changes to the implementation of
a data structure can be kept hidden from the clients of that structure.
-
Keep your data structures and algorithms simple as far as
possible. (Assuming your design is modular, you can come back afterwards
and use profile data, e.g., from gprof, to speed up those parts of
the code that are unacceptably slow.)