This page contains an archived post to the Design Forum made prior to February 25, 2002.
If you wish to participate in discussions, please visit the new
Posted by Bill Venners on 22 Mar 1998, 3:05 PM
> > I want to talk about when to solve the specific
> > problem versus the general problem. My thought is
> > that you should always lean towards solving the
> > specific problem, unless your product is
> > a library or component that is supposed to solve
> > a generic problem for other programmers.
> Just for the sake of the argument, let me throw in
> 3 (not really well-thought-out ;-) ) thoughts that,
> IMO, point to the opposite, i.e. "by default, do it generically":
> a) Probably you are familiar with Kernighan/Ritchie's classic
> Programming in C, where they quite forcefully argue more than once
> that one should think, design, and code as generic as possible.
> [I know - that's not a valid argument, because it is "citing
> a guru to intimidate you" - but I think it's worth to think
> about the effect that this opinion has had on the development
> of the "Unix culture"]
One of the oldest, most crinkled books on my shelf. I flipped thorugh
it a bit last night, but wasn't able to find any of those spots you
refer to. It has been so long since I went through that book, I don't
remember where to look for their programming philosophy.
> b) I do have a general rule of the thumb that is about:
> - if you do/use/... something once, make it dirty
> - if you do/use/need/... it a second time, you will need/use/... it very often -
> hence you should make it generic.
> c) Orthogonal (i.e., generic) designs allow users to more easily
> use a system in ways the implementor did not expect. Together with
> the axiom "Users will use a system in novel and unexpected ways",
> this points strongly to a generic design for software: Make everything
> scriptable; make everything programmable; make everything open so new
> systems with (at least slightly) modified behavior can be "derived"
> from the present system; etc.
> Ok. However, now, after I have thrown around with enough intelligent
> top-level unconcrete ponderings about the only rightful attitude, which
> is "think generically, and do so", I admit that in many cases (a) I do
> not know how to make a class, subsystem, tool, etc. generic; and (b) even if
> I know it, it is mostly a quite expensive endeavour, where either I or my
> project manager (who controls the time=money) or we both quickly runs out
> of patience.
> So, hard real life forces us to keep to painful specific solutions most of the
> time, instead of flying on the clouds of the real generic solutions to
> every- and anything.
Alas, I think I made my comment too generic. Allow me to be more, uh, specific.
I'm not really thinking so much about generic versus specific in the realm of designing
systems, but in designing classes, especially problem domain classes. By "generic," I'm
thinking about adding stuff in to make the class more general purpose than you really need
at the moment, either to make the class more reusable or more easily able to be adapted
to changed requirements in the future.
While the end goals of enhanced reusability and changeability are worthy goals, I think
there are two drawbacks to leaning towards generic classes, both of which you kind of
mentioned. One is that it is hard to predict the future, so all your extra work may
not really help the next person to come along who needs to change the class. And
second, it simply takes longer to make something more generic.
As a manager, I'd be trying to keep the programmers I manage fairly
focused on accomplishing the job at hand. (Though I wouldn't try to
micro-manage their class designs, just try to get them to talk about this
kind of issue and try to emphasize the importance of keeping focused.)
But on the other hand, when it comes to data management classes (those
classes that don't really map to anything in the problem domain, but rather
just help you manage the application's data in one way or another), I'm
more warm to trying to design a more general class. I think its good to
try and think of this kind of class in generic terms (this is a semaphore,
or this is a finite state machine) so it can be
reused more easily. Yet I still think its important not to get too
carried away on making the thing generic that one loses focus on getting
the job at hand done in a timely manner.
I guess what I like to see when I go in to maintain someone's code
is easy to read, cohesive, decoupled classes and interfaces that are
fairly well focused on the job that needed to be done at the time. Then I
can go in and make the changes I need to make to meet the new
But I'd sure be interested in hearing other people's opinions. What
do they like to see when they have to go in to maintain someone else's
code? Generic? Specific? To what extent? Under what conditions? Etc.
> Nevertheless, in my heart I'm with Terence Parr, who wrote in the
> foreword of his thesis (about ANTLR) something along the lines of
> "Before I solve a problem once in five days, I rather spend five years
> on designing a really generic solution, from which the specific one can
> then be derived in just 5 seconds."
Yup. I've done that too on several occasions, though I never had the
opportunity to take 5 years to do it. Sometimes it has worked out, other
times it didn't. One time I used lex and yacc to build a tool that would
generate C code of a database interface layer from the SQL definition of
the database. After that, instead of editing the C code of the DB layer
each time we changed the database, we could just regenerate it. Once I
got the bugs out of the tool, which was easier than debugging hand-changes
to the DB layer code, the generated code didn't have bugs. The tool only took
me one day to create and debug, and it saved us lots of time over the
years I was there. People still used it after I left as well, so that one
was a success. Other times, however, it turned out that I should have
just done the stuff by hand instead of trying to find some fancy way
to automate it.