Thinking Forth
About 20 years ago I first read the book
Thinking
Forth by Leo Brodie, and it
taught me a great deal about how to approach software design and how to factor
problems. Looking through the book yesterday, it struck me how very well its
design advice still holds up, even if the tools of the day are Java and C#
instead of Forth...
Let's look at a few examples of the
wisdom Brodie was pitching
here:"Generality
usually involves complexity. Don’t generalize your solution any more than
will be required; instead, keep it
changeable." I don't know about
you,
but I've seen that kind of overkill many times over the years. I've seen
frameworks so over-developed and sluggish that the programmers expected to use
them spent a lot of effort avoiding them. For acceptable performance, it became
necessary to implement a parallel, task-specific body of code. This sounds a lot
like the Extreme Programming tenet of "you're not
gonna need it," doesn't
it?"You don't
understand a problem until you can simplify
it." Seriously, how many times have you
spent
hours
coding something tedious, when all of a sudden a cog slips somewhere in your
brain and you see a far simpler, cleaner way of doing the same thing? When this
happens, it may be a sign that you didn't understand the problem well enough
before writing the code; it's much more efficient to have this flash of insight
during the design phase of a
project."Start
simple. Get it running. Learn what you’re trying to do. Add complexity
gradually, as needed to fit the requirements and constraints. Don’t be
afraid to restart from scratch." Again,
Brodie seems to be presaging some ideas behind various agile programming
practices. Brodie isn't advocating starting a project without any planning here,
in case the lack of context is misleading. Rather, he's discussing an iterative
approach to software development as a preface to discussing planning, both its
importance and limitations, and pointing out the importance of
prototyping.Throughout the book, there
are numerous quotes from the creator of the Forth language, Charles Moore. While
some of these don't have much to do with more mainstream computer languages,
they reveal a philosophy of simple and elegant software design that should give
us pause. When asked how long a Forth word (a function) should be, Moore
responds, "A word should be a
line long. That's the target. When you have a whole lot of words that are all
useful in their own right --- perhaps in debugging or exploring, but inevitably
there's a reason for their existence --- you feel you've extracted the essence
of the problem and that those words have expressed it. Short words give you a
good feeling." Features of Forth (such as
its implicit parameter passing) encouraged such granularity and relentless
factoring of a problem, but the philosophy has wider
application.Regardless of the
programming language you use, factoring into small, reusable functions is a
vital craft. Brodie offers several tips about factoring to get one thinking:
"Factor at the point where you
feel unsure about your code (where complexity approaches the conscious limit)...
Factor at the point where a comment seems necessary... Limit repetition... When
factoring out duplicate code, make sure the factored code serves a single
purpose." The chapter on factoring is
packed with good advice, even if you ignore the examples specific to
Forth.I remember having to rework
someone's serial device driver some years ago. The driver was written in 80x86
assembly language, and the author used numerous flags to keep track of the
communications state. The result was a bug-ridden nightmare; the driver would
encounter an unusual packet and flip the flags into some impossible, nonsensical
state. The solution in the rewrite was a return to first principles, figuring
out the valid states the transmitter and receiver could occupy, and maintaining
a single state variable for each. Brodie seems to have been there, too. From the
Data
Handling chapter:
"When the application requires
handling a group of conditions simultaneously, use a state table, not separate
variables."You might be
surprised to note a chapter on minimizing control structures. Say what? What's
wrong with
those?
Well, we've all seen the evil that ensues when somebody gets lazy with factoring
and nests "if" statements 40 levels deep. Brodie adds this:
"The use of conditional
structures adds complexity to your code. The more complex your code is, the
harder it will be for you to read and to maintain. The more parts a machine has,
the greater are its chances of breaking down. And the harder it is for someone
to fix." Moore opines,
"Every conditional should cause
you to ask, 'What am I doing
wrong?'"The strategies for
minimizing control structures presented by Brodie don't apply equally well to
all languages, but he still comes up with some good tips:
"Don’t test for something
that has already been excluded... Combine booleans of similar weight... Choose
the control structure that most closely matches the control-flow problem...
Don’t decide, calculate [when the conditionals involve
numerics]."It may seem weird
to review a 20-year old book that largely centers around a niche language, but
to this day Thinking
Forth remains one of the best and most
enjoyable books I've read on factoring and solving problems. And it's available
free on
SourceForge under a Creative Commons
license thanks to Leo Brodie and the collaborative efforts of Bernd
Paysan and others.Thinking
Forth can help clarify your thinking in any
computer language.
Posted: Fri - March 4, 2005 at 06:54 PM
|
Quick Links
Recommended!
Software I've Written
Other Writings
Sites I Maintain
Archives
|