Paul's Observations on Reuse - Go Back

From the JSL list, August 31, 1999 we have this very interesting and mature exchange between Paul and Stan about reuse. Paul's writing is humorous, insightful and concise. Stan's comments and questions are penetrating. Highlighting added by your friendly editor. :-)

We start near the beginning of the thread, which Stan started. The thread dealt with reuse on the Ariane 5 disaster, caused by software failure, as mentioned in a JavaWorld article by Holub on reuse.

Be sure to ponder Paul's Three Time Rule and Laziness Test, and Stan's Never Trust a Reusable Until corollary.


Paul Reavis <preavis@partnersoft.com> wrote:

Actually, the whole description of the Ariane problem sounded
to me like classic reuse-by-clone-and-hack. The description specifically
described that the function was used w/o wrapping error checking, whereas
elsewhere the error checking was present. Looks like each instance was
coded separately, but in a similar manner, and the one time it wasn't
things screwed up. This is horrible clone-and-hack - the error checking
should have been factored out and included in a reusable function.

At the very least it was a case of reuse for possibly only the second
time of code; things are never that robust by that time.

My rule of thumb is three times - after you've used a component in
three dissimilar contexts, you can consider it over the hump as far as
reusability is concerned.
A good reusable gets better as bug fixes are
applied and changes made to enhance reusability in different contexts.
Also, if you aren't using it in at least three dissimilar contexts, you
aren't really profiting from reuse anyway. Though I usually code
everything as reuseably as I can anyway out of habit.

Stan Silvert <SSilvert@3MC.com> replied:

> Paul,
>
> I like your "three times" rule. It does produce one important corollary:
> "Never trust a reusable until it has been used in at least three dissimilar
> contexts." In the Ariane disaster, the contexts were very similar but reuse
> failed anyway!
>
> I think that I have learned something very important here, which is: "Don't
> reuse code for mission critical apps unless the reused component has
> performed well in at least three non-critical apps." This makes me a bit
> sad. How many projects are not mission critical? Not many in my part of
> the world. When do I get the opportunity to test my components in three
> different contexts?
>
> Maybe I am being a bit harsh. Certainly there are degrees of mission
> criticality that you can play with. But, I am beginning to think that
> reusable components should never be built on the fly.


It does depend on your definition of "mission critical". Frankly, I
prefer the IEEE definition, which, loosely, consists of risk to life and
limb or really significant financial loss (the kind that bankrupts
people or companies). Thank heavens most software projects don't fit
into that definition. Truly mission critical projects (manned space
programs, interstate banking software, medical monitoring software,
nuclear power plant control systems) deserve a completely different
process, mindset, standards and practices, and quality control from
non-critical systems. Often simple testing isn't enough, you have to
prove and verify the code, do full coverage analysis, etc. It's a
completely different world, one that I have no interest in participating
in. I never want to find out a bug in my software killed someone.

You aren't going to build a reuseable component on the fly. You
can build for reuseability, though.
I have some standard practices -
exposing configurable state, plugpointing as much as possible, etc. -
that I always follow; it's then easy to make something reuseable once
you've seen another use. But typically those second and third uses do
require revisiting the implementation of the part.

Truly modular and reuseable infrastructure is another issue; I have some
of this and Jack has more. Here you always work within a framework of
reuse. So you are following some practices at all times. But still the
rule applies - parts you deploy just aren't going to be truly tempered
until they've seen some different situations.

If you have the situations in front of you at the beginning, you can
design the part ahead of time. You still have your three cases, but you
have them up front and can go ahead and build the reuseable solution
instead of evolving it. But often that's not the case - your part has to
evolve over time as it sees deployment into new contexts.

One mistake many people make (and I made quite a bit, not too long ago)
is to overdesign for reuse up front, usually at the wrong level of
granularity. For example, you might make a MyApp reuseable application,
which has splash screens, a main window that exits correctly, a
command-line parser, etc. all built in so you can deploy applications
easily. So you add in all this great stuff so that it will last the
ages, and it just doesn't - you end up not using half of it, and then
adding on more things as you try to reuse the beast. In general, you get
a much better payoff reuse-wise if you start with fine-grained objects
that do very specific things, or with truly generic services. The things
that get reused the most in my system are things like:

1) introspection tools
2) data-mangling routines
3) structured storage (simple file loading/saving)
4) wrappers for Swing GUI objects
5) logging, error reporting, etc. services
6) event-driven gadgetry and plumbing

None of these are domain-specific, and all are pretty generic. I use the
Laziness Test to determine reuseable goodness - does using the part make
you feel like a lazy oaf, earning good money for writing a few lines
(preferably one) of blindingly obvious code? If so, you've got a good
part there. Implementing reuseable parts is hard, but using them should
require about as much mental effort as drinking a beer while watching TV.


> Paul,
>
> Maybe a good development practice for a component would be something like this:
> 1) Find some code eligible for reuse.
> 2) Let someone with no interest in the code's original domain make a
> reusable component out of it.
> 3) Allow others to use the reusable.
> 4) Monitor any failures in the reusable and try to improve it.


More generally, you have a few ways to initiate building a reuseable:
1) Proactive: you see (during analysis/requirements or design phase)
several similar problems that could use a common solution, then
implement it to fit each of these problems.
2) Learning from experience: you see a problem whose solution is similar
to one you've already solved, and rework the solution to fit both old
and new problems
3) Reactive: you see several problems that are solved by variations on
the same solution in your existing code; you redesign and rewrite the
code to factor these into a single reuseable.

I'm not including these bad ways:
1) Overeager: you envision future hypothetical situations that your part
might solve, and overdesign it to meet these (possibly imaginary)
requirements
2) Inactive: you just keep on cloning and hacking... I think almost all
software design techniques are in reaction to this sort of practice.
3) Hyperactive: you spend all your time rewriting code that may be
suboptimal design-wise, currently works

> Paul,
>
> To produce reuse on any large scale it probably means having a separate
> person or group in the organization that only does components and does not
> directly work on a revenue-generating project. Those in the component
> development group must be the best developers in the organization. This is
> because reusable components have to be held to a higher standard in order to
> avoid problems such as those in the Ariane project.


Yes and no; quite often it's not just a matter of skill but of mindset.
Note that this is hard to do; there are tons of books on it. Part of the
problem is that the component developers can get too far away from the
day-to-day code that their parts are actually used in. Another is that
you also have to consistently evangelize your parts in the organization,
and train everyone in their use. Meeting the laziness criterion above
sure helps there. But huge APIs are hard to get your brain around, and
often when you're busy implmenting you may not think to go look for an
already-existing, reuseable solution.

> Paul,
>
> Now our problem becomes political. How do you convince management to take
> the best talent in the organization and put it into a group that does not
> directly produce revenue? Until the components are reused several times
> there will be no positive return on investment.


And frankly, in some organizations that's for the best. If you aren't
really reusing these things then it's not worth the investment, period.
This hard fact has soured many companies on OO/reuse.

> Paul,
>
> I'd like to do this in my own organization but I am not sure how to approach
> management. Any suggestions?


Show success on a small scale, and grow it from there. Frankly, the BS
level in software is so high that no one believes anything they haven't
seen or used anymore. And throwing around high-falutin' OO doctrine just
annoys most managers. If it works, it justifies itself. Now, convincing
the development team is another matter - there you might have to convert
some folks beforehand.


(In a later message Stan and Paul continue the dialogue, ending with some fine humor.)

> Paul,
>
> By the way Paul, I too am very afraid of projects where my software could
> kill someone. I only know of one documented instance of this (the famous
> up-arrow on the radiology machine bug), but there are probably more. I have
> to say that I admire the chutzpah of anyone who dares to step into the
> "truly" mission-critical software arena.

There are more indirect criticalities. I used to write IEEE test plans
and execute them on a multi-million record groundwater analysis database
for the Savannah River nuclear site. No only are the environmental
concerns fairly serious, but the kinds of fines that could result from
it were stupendous (millions of dollars).

> Paul,
>
> Also Paul, I loved your comment about how using a part should be as easy as
> drinking a beer and watching TV. Is our ultimate goal to become Java couch
> potatoes? :-)

Well, I dunno about couch, but I seem to have the potato shape started
pretty well here.
--
Paul Reavis
Design Lead
Partner Software, Inc. http://www.partnersoft.com