[comp.software-eng] Reusability considered harmful??

chip@tct.uucp (Chip Salzenberg) (01/31/91)

"Reusability" is perfectly adequate as a description of existing code
that can be put to a new use.

The main problem I've observed with the term is the assumption some
people make that if code even requires a little tweak for reuse then
it isn't really "reusable."  Reuse isn't free.  Sometimes its costs
are up front, sometimes they aren't, and no one has a crystal ball.
-- 
Chip Salzenberg at Teltronics/TCT     <chip@tct.uucp>, <uunet!pdn!tct!chip>
 "I want to mention that my opinions whether real or not are MY opinions."
             -- the inevitable William "Billy" Steinmetz

weide@elephant.cis.ohio-state.edu (Bruce Weide) (01/31/91)

Brad, in suggesting a replacement for the word "reusable" as
applied to software components, you suggest that some opponents of the
idea might argue:

>"Reusability! Why 'reuse' software, when any fool knows it is cheaper
>to throw used bits away and copy more from a master as needed."

Seriously, now, have you really faced this sort of response to your
ideas?  I knew we were having some trouble communicating with certain
communities, but it never occurred to me that the problems might run
so deep :-).

By the way, I applaud your recent emphasis (in a couple postings) on
specification of external behavior, as an alternative to source code,
as a way of explaining/understanding component behavior.  Maybe we
could resurrect the discussion here (mostly flames) of a couple years
ago when we suggested that software components should be sold as
specification + object code, and that source code should remain
hidden.  Talk about a hard sell...

	-Bruce

scotth@newsigi.colorado.edu (Scott Henninger) (01/31/91)

In Article 340 Brad Cox (cox@stpstn.UUCP) writes:

> What do you think about substituting 'division of labor' for
> reusability across the board, on the grounds that it says precisely
> what is meant and nothing more?

But what does it mean???
-- 


-- Scott
   scotth@boulder.colorado.edu

khb@chiba.Eng.Sun.COM (chiba) (01/31/91)

In article <6108@stpstn.UUCP> cox@stpstn.UUCP (Brad Cox) writes:

...

   What do you think of this notion?

   Could it be that we (reusability proponents) are shooting ourself in
   the foot with the word, "reusability", just as the AI community did
   themselves in with a term of their own choosing, "artificial
   intelligence"?

   Such words are fine for agreeing with one's friends, but are terrible 
   for persuading one's enemies.
....

In my experience, the most code reuse is in the FORTRAN (soon to be
Fortran) and COBOL communities. They don't talk about it. They do it.
The folks who have used the words the most have tended to be those
that have pitched me on Algol, Pascal, Ada, Smalltalk, and nowdays
C++. 

Both in biz and sci circles the problems are somewhat better defined
(math folks spent a couple of thousand years getting the notation
down, and matrices are a suitable abstraction for a large class of
interesting <to numerical folks> problems.

Rather than debate names, work on the underlying substantive issues
which inhibit "normal" software developers from reusing code.
--
----------------------------------------------------------------
Keith H. Bierman    kbierman@Eng.Sun.COM | khb@chiba.Eng.Sun.COM
SMI 2550 Garcia 12-33			 | (415 336 2648)   
    Mountain View, CA 94043

Nick_Janow@mindlink.UUCP (Nick Janow) (01/31/91)

EGNILGES@pucc.Princeton.EDU (Ed Nilges) writes:

> "Reusable" software components are very often ugly to use because they do
> more at run time than the potential reuser wants them to do.

Forth, with its low overhead for words (modules/subroutines), encourages reuse
of code, which in turn encourages writing code in a manner that makes it
reusable.  Writing an application consists of using the available words to
write larger words, which in turn are used to write larger words...  Since
complex words are made up of smaller words, it's easy to go back to a point and
reuse parts of it, if the whole word doesn't quite meet your needs.

A language that has high overhead for writing and calling modules (including
the programmer's time cost of having to declare--and document--every variable)
might discourage small modules, so there will be a temptation to pack each
module with extra features.  Can anyone using a different language (C, Pascal,
etc) confirm this?

phil@batserver.cs.uq.oz.au (Phil Stocks) (01/31/91)

In <6108@stpstn.UUCP> cox@stpstn.UUCP (Brad Cox) writes:

>What do you think about substituting 'division of labor' for reusability
>across the board, on the grounds that it says precisely what is meant
>and nothing more?

No, that won't do. People won't settle on whether to spell labour as
"labour" or "labor". In any Commonwealth country "division of labor" is a
political rift, not a software engineering term :-).

What is required is a word that means "componentisation" (why isn't that a
word in the English language? Sigh.). As I understand it, your stress is on
the construction of software components, that are produced wholesale in the
same way as 6 inch screws. An idea with which I agree. I was impressed with
your paper in November 1990 IEEE Software. I'll take this opportunity to
recommend it to anyone who hasn't read it.

Perhaps a word like (dare I say it) "object-orientation" is needed, if we
could include in the definition of object not only the desired
functionality, but also documentation, specifications, test suites, and
anything else deemed desirable.

Perhaps it's time for another meaningless acronym?

-----------
Phil Stocks
Department of Computer Science
The University of Queensland
Queensland 4072
AUSTRALIA
email: phil@batserver.cs.uq.oz.au

EGNILGES@pucc.Princeton.EDU (Ed Nilges) (01/31/91)

In article <7095@uqcspe.cs.uq.oz.au>, phil@batserver.cs.uq.oz.au (Phil Stocks) writes:

>In <6108@stpstn.UUCP> cox@stpstn.UUCP (Brad Cox) writes:
>
>>What do you think about substituting 'division of labor' for reusability
>>across the board, on the grounds that it says precisely what is meant
>>and nothing more?
>
>No, that won't do. People won't settle on whether to spell labour as

Interesting thread.

A lot of the time, reusability fails for the same reason RISC technology
is popular with a large subset of computer architects.  "Reusable"
software components are very often ugly to use because they do more
at run time than the potential reuser wants them to do.  Even when this
is not the case, there is a perception problem, somehwat similar to
the perception of reusability that Brad describes: programmers tend to
be highly suspicious of buying a pig in a poke, of having to pay for
someone else's mistakes, or just of coming up with a less than optimal
product.

This problem is related to the problem of the CISC (Complex Instruction
Set Computer).  The instructions of the CISC can be difficult to use
in a compiler, whereas the extremely regular instructions of the RISC
machine can be easier to consider as straightforward black boxes.

Reusability is not like motherhood, good no matter what.  We badly need
a theory of what constitutes good reusability and what constitutes bad
reusability.  Unfortunately, in an era of computing cultures that
are expand globally, at dizzying speed, it is unlikely that we can
come to any such agreement any time soon.  I therefore predict that
code, globally speaking, will be in future even LESS modular...more
highly adapted to a particular environment...than it is today.

oscar@cui.unige.ch (Oscar Nierstrasz) (01/31/91)

cox@stpstn.UUCP (Brad Cox) writes:

>Could it be that we (reusability proponents) are shooting ourself in
>the foot with the word, "reusability", just as the AI community did
>themselves in with a term of their own choosing, "artificial
>intelligence"?

There is another problem, which is that "reusability" is only part
(albeit an important one) of the story.  That is why I feel that it
is better to emphasize "software components" and even "component-oriented
software construction".  Even if you don't reuse a thing, it is important
to organize applications in terms of interlocking components as this
enhances robustness, maintainability and portability (though one could
argue that these are all instances of "micro-reusability").

The emphasis on "software components" also addresses the gap between
"object-oriented" programming (i.e., at the "chip" level) and software
construction without programming (as we know it).  A component can be
anything from a humble int to a customizable office system.  Furthermore,
the emphasis on "software construction" gets us away from the idea that
we must always be "programming" to build applications (another thing wrong
with the term "object-oriented programming").

Finally, there is another danger in the word "reusability", which simply
has to do with the fact that reusability does not come for free.  Anybody
who hears about a technology that supports reusability will naturally say,
"Yes, that's for me!  I would sure like to reuse software rather than
build it from scratch!"  Except the other half of the story is that someone
must build the reusable components.  Unfortunately this half of the
story is not well understood.  At OOPSLA/ECOOP 90 there was an enlightening
episode one day when there was a morning panel on object-oriented vs
structured analysis and an afternoon session on frameworks.  In the morning
session, *no one* addressed the issue of reusability, and in the afternoon
session, no one had any methodology for designing frameworks of
reusable components (beyond the insight that the process is iterative).

So, by talking about components rather than just reusability, we suggest
that this is the correct way to think about software at various levels
of abstraction (and that there is more to the story).  By talking about
reusability, however, we only point to an abstract goal that is very
hard to realize in practice.  We are still looking for the right view
of software components that will actually give us the degree of
reusability that we seek.

-------------------------------------------------------------------
Dr. O.M. Nierstrasz                 | Tel:    41 (22) 787.65.80
University of Geneva                | Fax:            735.39.05
Centre Universitaire d'Informatique | Home:           733.95.68
12 rue du Lac, CH-1207 Geneva       | E-mail: oscar@cui.unige.ch
SWITZERLAND                         |         oscar@cgeuge51.bitnet
-------------------------------------------------------------------

luism@genesis.Berkeley.EDU (Luis Miguel) (02/01/91)

In article <6108@stpstn.UUCP>, cox@stpstn.UUCP (Brad Cox) writes:
|> What do you think of this notion?
|> 
|> Could it be that we (reusability proponents) are shooting ourself in
|> the foot with the word, "reusability", just as the AI community did
|> themselves in with a term of their own choosing, "artificial
|> intelligence"?
|> 
|> Such words are fine for agreeing with one's friends, but are terrible 
|> for persuading one's enemies.
|> 
|> "Reusability! Why 'reuse' software, when any fool knows it is cheaper
|> to throw used bits away and copy more from a master as needed."
|> 
|> See what I mean? The word gives those who don't want to listen an
|> excuse to misunderstand the message, just as with AI.
|> 
|> What do you think about substituting 'division of labor' for reusability
|> across the board, on the grounds that it says precisely what is meant
|> and nothing more?
|> 

My impression is that the terminology is not the problem, rather I
see two:

1) Much has been made of the reticence of established software engineers
to embrace the reusability bandwagon. My opinion is that this is not
the major obstacle to the widespread adoption of software reusability.
The obstacle is that there are still several hard problems that prevent
reusability from being widely available and applicable.
I believe that until we (researchers and industry) solve these problems
and SHOW the software engineering community what the advantages of
this approach are, people will cling to their old ways.

2) On another note, I also think that we, "reusability proponents", might
have commited a similar mistake to the AI community: that of EXAGGERATED
EXPECTATIONS. Do you think we might have promised a panacea that we have
been unable to deliver? Remember when we heard, in the late '60s, that
we would be soon having conversatoins with our computers?

/Luis

-- 
Luis Miguel. Computer Science Division, UC Berkeley.
arpanet: luis@postgres.Berkeley.EDU         
uucp: {ihnp4,decvax}!ucbvax!postgres!luis                    
at&t: (415) 642-8234

donm@margot.Eng.Sun.COM (Don Miller) (02/01/91)

...in response to semantic argument about "reusability"...

In article <12385@pucc.Princeton.EDU> EGNILGES@pucc.Princeton.EDU writes:
>
>                                             .....      "Reusable"
>software components are very often ugly to use because they do more
>at run time than the potential reuser wants them to do.  Even when this
>is not the case, there is a perception problem, somehwat similar to
>the perception of reusability that Brad describes: programmers tend to
>be highly suspicious of buying a pig in a poke, of having to pay for
>someone else's mistakes, or just of coming up with a less than optimal
>product.

   This is my primary concern with reuse-facilitating OO languages
   like C++.  The nature of the craftsman/inventor is to "build a
   better mousetrap".  I believe that programmers will be tempted
   to modify or ignore reusable functions because they are not a
   good fit with the exact application or the fit cannot be measured
   because it is unclear what the code does.  

   It seems that the best way to address this problem is to treat
   code intended for reuse with great respect.  This essentially 
   means documentation to the level of a system or library call.
   Yes, that means a man page.  It also means focused functionality.
   Code which tries to be all things to all people is unlikely
   to be really useful to anyone.

> ...
>
>Reusability is not like motherhood, good no matter what.  We badly need
>a theory of what constitutes good reusability and what constitutes bad
>reusability.  Unfortunately, in an era of computing cultures that
>are expand globally, at dizzying speed, it is unlikely that we can
>come to any such agreement any time soon.  I therefore predict that
>code, globally speaking, will be in future even LESS modular...more
>highly adapted to a particular environment...than it is today.

   
   In the Journal of Object Oriented Programming (Jan 1990 p13),
   an article entitled "Adequate Testing and Object-Oriented 
   Programming" addresses the testing perspective.  The authors
   describe four features common to many OO languages which 
   bely an intuitive assumption that reuse will not mean retest.
   Test adequacy is addressed in the article as the combination
   of specification-based (black box) and program-based (white box).

   Antiextensionality:  "If two programs compute the same function
   (that is, they are semantically close), a test set adequate for
   one is not necessarily adequate for the other." 

   General Multiple Change:  "When two programs are syntactically
   similar (that is, they have the same shape), they usually 
   require different test sets."

   Antidecomposition:  "Testing a program component in the context
   of an enclosing program may be adequate with respect to that
   enclosing program, but not necessarily for other uses of the
   component".

   Anticomposition:  "Adequately testing each individual program
   component in isolation does not necessarily suffice to adequately
   test the entire program.


   After a discussion of the application of these adequacy criteria
   in the context of object oriented features such as encapsulation,
   method overriding, and multiple inheritance, the authors conclude:

      "Encapsulation together with inheritance, which intuitively
      out to bring a reduction in testing problems, compounds
      them instead.

      Where non-inheritance languages make the effects of changes
      explicit, inheritance languages tend to make these implicit
      and dependent on the various underlying, and complicated,
      inheritance models."

   There are several interesting observations which lead to this
   conclusion.  These observations directly relate to what might
   be "good" and "bad".  


    
--
Don Miller                              |   #include <std.disclaimer>
Software Quality Engineering            |   #define flame_retardent \
Sun Microsystems, Inc.                  |   "I know you are but what am I?"
donm@eng.sun.com                        |   

G.Joly@cs.ucl.ac.uk (Gordon Joly) (02/01/91)

> What do you think of this notion?

At a recent Colloquium I suggested the idea that if software
engineering is to be considered an *engineering* discipline, rather
than a science, the notion of tolerance should be developed.

This arose from thinking about the interchangablity of parts from a
modern production line, and is not original. If you buy a new spark
plug or a tyre, then it has to fit in place, within a certain margin
of error - tolerance. Cylinders fit into an engine block with a
certain gap, within a certain range of error. And so on.

Can the tolerance idea get off the starting blocks?

Gordon Joly                                       +44 71 387 7050 ext 3716
Internet: G.Joly@cs.ucl.ac.uk          UUCP: ...!{uunet,ukc}!ucl-cs!G.Joly
Computer Science, University College London, Gower Street, LONDON WC1E 6BT

           Email: Les jeux sans frontiers du monde

mcgregor@hemlock.Atherton.COM (Scott McGregor) (02/01/91)

In article <87829@tut.cis.ohio-state.edu>,
weide@elephant.cis.ohio-state.edu (Bruce Weide) writes:

> >"Reusability! Why 'reuse' software, when any fool knows it is cheaper
> >to throw used bits away and copy more from a master as needed."
> 
> Seriously, now, have you really faced this sort of response to your
> ideas?  I knew we were having some trouble communicating with certain
> communities, but it never occurred to me that the problems might run
> so deep :-).

Two points.  First, copying more from a master IS a form of reusability.
 One of the things that
makes a "master" masterful is that they are able to churn out good code
real fast.  One trick of the trade
is to keep your old programs, and to copy related sections from old ones
to new ones and begin
modifying rather than writing from scratch.  Code is reused (with
modification), but of course
it is mainly the writer's own limited set of previously written code. 
Such masters also get
through test more quickly too, because they don't feel the need to
re-test the code they had
written before (and re-used with modifications); they feel they only
need to test the modifications
and other new code.  Any "master" who moves from an environment where
they have years worth of reliable
source to a new environment where that old source is entirely useless or
unavailable knows the
sinking feeling of discovering you are less productive than you used to
be.  (Mind you, I don't personally
claim that such reuse is practically equivalent to OO reuse, nor that
the attitude described above about
testing is admirable--I have however often observed many individuals who
do believe so, not merely 
due to trouble communicating with OO folks, but due to different
successful past experiences.

The second point is that a "problem" with OO for many existing
programmers is that it changes the
nature of development in a way that is often annoying to existing master
programmers.  In particular,
when you create a new object that inherits a lot of methods from a deep
class hierarchy, your testing
problem become significantly more complex.   You should test all the
inherited methods, which might number
orders of magnitude more than your number of new methods.  You must test
these inherited methods not simply
because they might be misimplemented in a way that only your new object
uncovers, but also because while you
may have thought you understood their behavior from reading the manual,
their actual behavior may
be different--due to a misunderstanding on your part.   Of course this
is a problem with reusable
components in general, not a failure limited to OO technology
implementations. Unfortunately, the kinds
of personality traits and interests that might be likely to make one
successful generating new
solutions to programming problems may not mesh well with the kind of
traits and interests that
will lead to success in such rigorous testing of other people's code--a
problem that I have personally
observed.  This illustrates a difficult and interesting
non-technological issue for project managers 
in the software industry who choose to adopt OO or other high-reuse
technologies.


Scott McGregor
Atherton Technology
mcgregor@atherton.com

P.s. Lest anyone misattribute various prejudices to me, let me point out
that I have been managing
S/W developers in various OO and other reuse technologies for many
years, and I continue to expect
to do so.  I think that various benefits of reusability are desirable,
but that these technologies
are not without their costs too, particularly as you consider the
developers as humans with
individual desires, goals, and skills rather than as  mechanical
interchangeable resources.  A challenge
I set for myself is to try to find a balance that gets a fair amount of
the technological benefits 
without significant human cost.  Success has varies with different cases. 

cwk@ORCRIST.GANDALF.CS.CMU.EDU (Charles Krueger) (02/01/91)

In article <6108@stpstn.UUCP>, cox@stpstn.UUCP (Brad Cox) writes:
> Could it be that we (reusability proponents) are shooting ourself in
> the foot with the word, "reusability", just as the AI community did
> themselves in with a term of their own choosing, "artificial
> intelligence"?

The problem with "artificial intelligence" was not so much the terminology
as it was the preposterous analogies, claims, and predictions that many AI
advocates were making.

Likewise, the problem with "software reuse" is not the name, which in fact
quite accurately describes the field.  The problem is with the Software
Evangelists who go around preaching the virtues of software reuse with
preposterous analogies, claims, and predictions.  This B.S.  does a great
dis-service to those researchers doing serious work on software reuse and
to the software engineering field in general.

> "Reusability! Why 'reuse' software, when any fool knows it is cheaper
> to throw used bits away and copy more from a master as needed."

Surely no one is that naive!?!?

> What do you think about substituting 'division of labor' for reusability
> across the board, on the grounds that it says precisely what is meant
> and nothing more?

"Division of Labor" is a vague reference to many computer engineering
activities, but it doesn't capture the essence of "software reuse".

chip@tct.uucp (Chip Salzenberg) (02/02/91)

According to G.Joly@cs.ucl.ac.uk (Gordon Joly):
>Can the tolerance idea get off the starting blocks?

"The strlen() function returns the number of characters in the
given string, plus or minus two."

Right.
-- 
Chip Salzenberg at Teltronics/TCT     <chip@tct.uucp>, <uunet!pdn!tct!chip>
 "I want to mention that my opinions whether real or not are MY opinions."
             -- the inevitable William "Billy" Steinmetz

EGNILGES@pucc.Princeton.EDU (Ed Nilges) (02/02/91)

In article <4639@mindlink.UUCP>, Nick_Janow@mindlink.UUCP (Nick Janow) writes:

>
>EGNILGES@pucc.Princeton.EDU (Ed Nilges) writes:
>
>> "Reusable" software components are very often ugly to use because they do
>> more at run time than the potential reuser wants them to do.
>
>Forth, with its low overhead for words (modules/subroutines), encourages reuse

I suppose that languages with spontaneous (that is, nonexistent) declarations
of variables encourage reuse, and FORTRAN is a case in point.  REXX is
another such language and it is easy to write and to use reusable
modules in REXX.

However, I believe a theory of reusability has to come from outside the
bits and bytes of programming languages.  A function makes sense as a
reusable tool when you can explain it in a simple (no compound phrases)
English sentence to a non-computer user.  Examples:


     This function returns the square root of its argument
     This function returns the nth root of its argument
     Calculate net pay from gross pay and deductions
     Produce voice stress analysis from waveform
     Identify out of balance tank condition
     .
     .
     .


Even in the realm of systems programming (producing functions for other
programmers) this rule applies, as long as the reusable function is
describable in terms that make sense, not just to the function maker
but also to the function user.

I believe that this simple rule provides a quasi sort of metric by
means of which you can distinguish good, modular code from what the
French would call "bricolage", or patchwork, worse in its way than
monolithic code.

murphyn@motcid.UUCP (Neal P. Murphy) (02/04/91)

oscar@cui.unige.ch (Oscar Nierstrasz) writes:

>cox@stpstn.UUCP (Brad Cox) writes:

>>Could it be that we (reusability proponents) are shooting ourself in
>>the foot with the word, "reusability", just as the AI community did
>>themselves in with a term of their own choosing, "artificial
>>intelligence"?

>There is another problem, which is that "reusability" is only part
>(albeit an important one) of the story.  That is why I feel that it
>is better to emphasize "software components" and even "component-oriented
>software construction".  Even if you don't reuse a thing, it is important
>to organize applications in terms of interlocking components as this
>enhances robustness, maintainability and portability (though one could
>argue that these are all instances of "micro-reusability").

Components that are interlocked with each other, as you put it, are not likely
to be very re-usable, because it will take too much effort to remove
the locks from the components; of course, if the locks are placed *around*
the components, then, perhaps, you might have some re-usable code. Looking
at this issue from another point of view: one must first learn how to re-use
things before he can know how to make them re-usable in the first place.

...
>So, by talking about components rather than just reusability, we suggest
>that this is the correct way to think about software at various levels
>of abstraction (and that there is more to the story).  By talking about
>reusability, however, we only point to an abstract goal that is very
>hard to realize in practice.  We are still looking for the right view
>of software components that will actually give us the degree of
>reusability that we seek.

Perhaps you could consider components in terms of their reusability, since
it seems rather clear that 'components' in and of themselves do not
necessarily lead to reusable code, and that reusability is still a ...
nebulous concept. If your code modules are all interlocked, it is likely
to be easier to simply start from scratch, because it might not be worth
the effort needed to unlock and decipher that code. However, if you have
designed your modules (and sub-modules within them) with reusability in
mind, you will stand a greater change of reusing portions of the code
later, because you already minimized inter-dependencies in the code.

Code reuse save a lot of time and money, provided the components were
written with reuse in mind from the start.

NPN

Nick_Janow@mindlink.UUCP (Nick Janow) (02/04/91)

EGNILGES@pucc.Princeton.EDU (Ed Nilges) writes:

> However, I believe a theory of reusability has to come from outside the bits
> and bytes of programming languages.  A function makes sense as a reusable
> tool when you can explain it in a simple (no compound phrases) English
> sentence to a non-computer user.  Examples:
> 
> 
>      This function returns the square root of its argument
>      This function returns the nth root of its argument
>      Calculate net pay from gross pay and deductions
>      Produce voice stress analysis from waveform
>      Identify out of balance tank condition
>      .
>      .
>      .

You're talking about another of Forth's strong points.  :)

The nature of Forth encourages factoring problems down to
single-word-descriptive modules (actually, these are appropriately called
"words" in Forth).  Forth is often thought of as unreadable, but in fact, good
Forth code--especially at the higher levels--is self-documenting.

Since the cost (programming time, run time and system resources) for writing
words in Forth is low, programmers tend to factor problems down to very short,
simple--and thus reusable--words.

I'm not trying to start a "my language is better than your language" war.  I
would like to point out that Forth might provide some useful insights into
reusability, since it is inherent in the philosophy of Forth.  Whenever talk of
reusability or OOP has come up, it's always made me think "they want to become
more Forth-like".  :)

ps.  "Thinking Forth", by Leo Brodie, is a good reference for Forth programming
philosophy, and modular (reusable) programming in general.

rcd@ico.isc.com (Dick Dunn) (02/06/91)

cox@stpstn.UUCP (Brad Cox) writes:
> What do you think of this notion?

> Could it be that we (reusability proponents) are shooting ourself in
> the foot with the word, "reusability", just as the AI community did
> themselves in with a term of their own choosing, "artificial
> intelligence"?

Depends on what group of people you're talking to.  I do think that, as far
as "programmers" (or whatever title you choose, be it exalted or humble--I
mean the people who create software) are concerned, it's too easy to
consider "reusability" a red herring.  Why?  Because they reuse software
all the time, and have been doing so for decades!  There is nothing new
about "reusability" in a broad sense...so, assuming that you mean something
more specific, you need a more specific term to identify what's new and/or
different.  Otherwise, I'm guessing that people assume you're preaching to
the choir, and tune you out.
-- 
Dick Dunn     rcd@ico.isc.com -or- ico!rcd       Boulder, CO   (303)449-2870
   ...Don't lend your hand to raise no flag atop no ship of fools.

sw@smds.UUCP (Stephen E. Witham) (02/07/91)

In article <4842@cui.unige.ch>, oscar@cui.unige.ch (Oscar Nierstrasz) writes:
> Furthermore,
> the emphasis on "software construction" gets us away from the idea that
> we must always be "programming" to build applications (another thing wrong
> with the term "object-oriented programming").

Hooray!  To paraphrase, the problem with object-oriented programming is the
programming.  It's only halfway to a new paradigm.  Even Brad Cox
constructs his software by programming.  But someday soon we'll have
"component software" (as distinct from software components) by analogy to
component stereo--software the user plugs together.  And maybe "software
composition" or "software compositing."

--Steve Witham
Not-the-fault-of: SMDS, Inc., Concord, MA 

ogden@seal.cis.ohio-state.edu (William F Ogden) (02/08/91)

In article <318@smds.UUCP> sw@smds.UUCP (Stephen E. Witham) writes:
    ....
>         To paraphrase, the problem with object-oriented programming is the
>programming.  It's only halfway to a new paradigm.  Even Brad Cox
>constructs his software by programming.  But someday soon we'll have
>"component software" (as distinct from software components) by analogy to
>component stereo--software the user plugs together.  And maybe "software
>composition" or "software compositing."

The question is whether large composite software objects are in any essential
way distinguishable from programs. Does programming consist of anything
but composing simpler objects to create more complex ones? The only thing
that seems to change from paradigm to paradigm is the collection of
composition mechanisms.

/Bill

cox@stpstn.UUCP (Brad Cox) (02/08/91)

In article <87829@tut.cis.ohio-state.edu> you write:
>Brad, in suggesting a replacement for the word "reusable" as
>applied to software components, you suggest that some opponents of the
>idea might argue:
>
>>"Reusability! Why 'reuse' software, when any fool knows it is cheaper
>>to throw used bits away and copy more from a master as needed."
>
>Seriously, now, have you really faced this sort of response to your
>ideas?  I knew we were having some trouble communicating with certain
>communities, but it never occurred to me that the problems might run
>so deep :-).

I threw that example out as one of many possible ways of misunderstanding,
not the only one. No one has made this particular argument, at least not to
my face. But I have sat thru a number of debates of the form "Reuse? Computers 
reuse code incessantly. Every operating system call, every pass through a 
loop, etc, etc".

I like "division of labor" because it focuses attention a change in
the *organization*, rather than a change in the *technology*.  It puts
the emphasis on specialization of labor (vertical), whereas reuse implies
a movement of code horizontally in a flat, homogeneous labor force.

Notice how easy it is for an organization to superficially buy into the 
idea of reusing code without putting into place the infrastructure required
to make it successful. For example, notice how difficult it is to convince
managers (and programmers) that reusing code effectively requires a stable
dedicated group responsible for building, testing, documenting, and
supporting this code, without distraction from other goals (i.e. building
product) 'Reuse' is easy to buy into at the lip service level because it 
does not impinge on ingrained value systems. Reusable code does not happen 
as a side effect of something else.

Reusable code results from a very deep change in an organization's
(and the individual programmer's) world view that I've tried to project
in the phrase 'Software Industrial Revolution'. To me, this phrase
means recognizing that people are different, programmers are different,
and the tools that they use are different too. 'Division of labor' tries
to capture the differences between the Ada philosophy (textual language,
tightly coupled), the Smalltalk philosophy (textual language, loosely coupled),
and ultra-high-level 'object-oriented languages' like Metaphor (coroutines,
lightweight tasks) and unix shell (heavyweight processes). Note that I'm
using object here in the broadest sense imaginable; encapsulation of state
and behavior with no requirement for inheritance.

Division of labor doesn't mean that programmers of these diverse types
operate independently of one another, as is required today given the
jihads separating adherents of the Ada (C++), Smalltalk (Objective-C), 
and Metaphor philosopies. With widespread adoption of division of labor,
technical means would arise that would make it possible for Ada or C++
devotees to specialize in building low-level components (gate- and
block-level objects) to be invoked (reused) by Smalltalk (i.e. Objective-C)
devotees in building higher-level chip-level objects (Software-ICs).

The division of labor notion recurses from there. Smalltalk or Objective-C
chip-level components could be used by end-users with no specialized 
programming skills at all if packaged as Metaphor-style card-level objects;
visual iconic objects that operate as coroutines, not subroutines.

Incidentally, I've been pushing this gate, block, chip, card, rack-level 
terminology for precisely the same reason that I'm pusing division of
labor. I've wondered why some programmers reject it as a controversial
statement of some kind of radical position, when I view it as unremarkable
common sense.

Puzzling. I've always regarded this terminology as only a way for reducing
the confusion when talking about matters that cross different levels of
integration. I don't view it as staking out some controversial new position,
but applying old and non-controversial terminology (from hardware engineering)
to highlight software architectural levels that most programmers take for
granted (i.e. the distinction of level between expressions, subroutines, 
instances, tasks, and processes).

>By the way, I applaud your recent emphasis (in a couple postings) on
>specification of external behavior, as an alternative to source code,
>as a way of explaining/understanding component behavior.  Maybe we
>could resurrect the discussion here (mostly flames) of a couple years
>ago when we suggested that software components should be sold as
>specification + object code, and that source code should remain
>hidden.  Talk about a hard sell...

By all means, do! I've stirred this pot hard enough and long enough
during the last several years to become convinced that there is no
technical obstacle to a specification/testing language as outlined
in my IEEE paper. The obstacles are not technical, but cultural. If
we can't get management to fund dedicated components groups (or 
equivalently, to buy components from external components groups like 
Stepstone), how will we ever get them to fund these groups to also 
build external specifications for the components and gauge their 
compliance to specification?

By the way, a specification/testing language would be a *WONDERFUL* 
research topic for an energetic young graduate student. If there are
any takers, I'd be delighted to help. 
-- 

Brad Cox; cox@stepstone.com; CI$ 71230,647; 203 426 1875
The Stepstone Corporation; 75 Glen Road; Sandy Hook CT 06482

rcd@ico.isc.com (Dick Dunn) (02/08/91)

sw@smds.UUCP (Stephen E. Witham) writes:
> ...To paraphrase, the problem with object-oriented programming is the
> programming.  It's only halfway to a new paradigm.  Even Brad Cox
> constructs his software by programming.  But someday soon we'll have
> "component software" (as distinct from software components) by analogy to
> component stereo--software the user plugs together...

If we buy your analogy to component stereo, note that the components are
numerous compared to the number of problems solved--e.g., there are
hundreds of cassette tape decks, many differing from one another in no more
than minor details.  The actual range of capabilities is trivially small.
The interfaces are conceptually narrow, which is good, but they're also
very limited, and the useful interaction among components is correspon-
dingly limited.  Is this what we want from software?

Do we want software which is as complicated and counterintuitive to operate
as a typical high-end VCR?  (OK, perhaps we've already got it...but I don't
think it's a desirable state of affairs.:-)

The construction of new stereo components continues; in fact, the pace is
increasing.  The creation of each new piece involves a process which is, to
that world, what programming is to ours.
-- 
Dick Dunn     rcd@ico.isc.com -or- ico!rcd       Boulder, CO   (303)449-2870
   ...Don't lend your hand to raise no flag atop no ship of fools.

cox@stpstn.UUCP (Brad Cox) (02/08/91)

In article <1401@ucl-cs.uucp> G.Joly@cs.ucl.ac.uk (Gordon Joly) writes:
>
>Can the tolerance idea get off the starting blocks?
>
I believe that it can, and that it must, for reasons stated near the end
of my Nov 90 IEEE Software article.

The whole question of tolerance for software is fascinating, but seeing
its richness requires dropping the academic notion that software is either
right or wrong (i.e. provable correctness), but an evolving product of
human labor.

I haven't tried to enumerate the full breadth of the tolerance issue, but
here are a couple of starting points: Is this component tolerably fast?
Tolerably small? Tolerably compliant with the previous release? Tolerably
functional? Tolerably close to what the customer wants? Tolerably priced?
Etc, etc, etc.
-- 

Brad Cox; cox@stepstone.com; CI$ 71230,647; 203 426 1875
The Stepstone Corporation; 75 Glen Road; Sandy Hook CT 06482

chip@tct.uucp (Chip Salzenberg) (02/09/91)

According to sw@smds.UUCP (Stephen E. Witham):
>Someday soon we'll have "component software" (as distinct from software
>components) by analogy to component stereo ...

That's already here -- cf. UNIX tools.  The question is, will _all_
programming eventually be cookbook work?  Only when all problems are
cookbook, i.e. never.
-- 
Chip Salzenberg at Teltronics/TCT     <chip@tct.uucp>, <uunet!pdn!tct!chip>
 "Most of my code is written by myself.  That is why so little gets done."
                 -- Herman "HLLs will never fly" Rubin

mcgregor@hemlock.Atherton.COM (Scott McGregor) (02/09/91)

In article <6248@stpstn.UUCP>, cox@stpstn.UUCP (Brad Cox) writes:

> Notice how easy it is for an organization to superficially buy into the 
> idea of reusing code without putting into place the infrastructure required
> to make it successful. For example, notice how difficult it is to convince
> managers (and programmers) that reusing code effectively requires a stable
> dedicated group responsible for building, testing, documenting, and
> supporting this code, without distraction from other goals (i.e. building
> product) 'Reuse' is easy to buy into at the lip service level because it 
> does not impinge on ingrained value systems. Reusable code does not happen 
> as a side effect of something else.

I think that this is because most software managers and engineers have
some past experience.  They've learned some things that worked for them
and some that didn't.  Those who weren't able to adapt to today's way
of doing things washed out of the business in frustration. It is hard
to support a new way of doing things that might invalidate your past
experience and reduce your mature judgements to the same level as
a novice.  This is threatening, and so resisted. That is why it
is difficult to change the way people do programming from rolling
their own, to leveraging other people's code.  It raises a bunch
of uncomfortable questions: Will I enjoy doing that as much as I like
what I am doing now?  Will I be as good as it as I am now?  Will
I be just as valuable (irreplaceable, high salaried) as I am now?
Will I make as good predictions on how long development will take?
Will I be as quick to spot misdesigns and misimplementations?  Will
I recognize the quick short cuts that are reasonable?

> ... I've stirred this pot hard enough and long enough
> during the last several years to become convinced that there is no
> technical obstacle to a specification/testing language as outlined
> in my IEEE paper. The obstacles are not technical, but cultural. If
> we can't get management to fund dedicated components groups (or 
> equivalently, to buy components from external components groups like 
> Stepstone), how will we ever get them to fund these groups to also 
> build external specifications for the components and gauge their 
> compliance to specification?

Of course, maybe this question is asked wrong.  Maybe you shouldn't 
get experienced software engineers and managers to embrace this kind
of change that undermines their own experience.  Maybe instead you should
look at how to convince non-software managers to stop turning to their 
MIS department to do the work, and rather do it themselves--saving all
the communication time and confusion. Nondevelopers have nothing to lose
since they don't already start with an experience base. They might like
the very different work inherent in the new approach, which might not
suit professional programmers at all.  In some sense, this is what happened
with 4GLs.  Most of the early 4GL adopters weren't long experienced
COBOL coders--it was often end users and new programmers.  Many
end users write very sophisticated Lotus 1-2-3 Macros, but never consider
themselves programmers,  but very few C coders have switched to write most
of their code in 1-2-3. At  the same time though fewer end users are
waiting for MIS groups to write programs for them that they can work 
out themselves in 1-2-3.

It may need to be the same for adoption of component based programming:
It may be the end users who don't have time to wait for an official
coding resource who turn to purchasing and using components.  If so,
this suggests substantial changes to user interfaces, training, etc.
to make component selection and configuration attractive to such 
inexperienced developers.


Scott McGregor
Atherton Technology
mcgregor@atherton.com

cox@stpstn.UUCP (Brad Cox) (02/09/91)

In article <318@smds.UUCP> sw@smds.UUCP (Stephen E. Witham) writes:
>In article <4842@cui.unige.ch>, oscar@cui.unige.ch (Oscar Nierstrasz) writes:
>> Furthermore,
>> the emphasis on "software construction" gets us away from the idea that
>> we must always be "programming" to build applications (another thing wrong
>> with the term "object-oriented programming").
>
>Hooray!  To paraphrase, the problem with object-oriented programming is the
>programming.  It's only halfway to a new paradigm.  Even Brad Cox
>constructs his software by programming.  But someday soon we'll have
>"component software" (as distinct from software components) by analogy to
>component stereo--software the user plugs together.  And maybe "software
>composition" or "software compositing."

We do need better terminology. How's this?

Hardware engineers distinguish assembly from fabrication. Assembly involves
loosely-coupled binding, where stereo system is constructed by assembly of
components, components (racks) by assembly of cards, and cards by assembly of
chips.  Below that level is fabrication; a tightly-coupled enterprise, where
chips are fabricated from cel libraries (blocks), blocks are fabricated 
from gates, and so forth to molecular and atomic levels.

The demarcation between fabrication and assembly is not precise, for 
the distinction between tight vs loose coupling (static vs dynamic
binding) involves shades of gray along a continuum from early to late
binding.

Mapping this back to software, most programming languages (Ada, Pascal, C,
C++) are fabrication technologies. I don't mean this in a perjorative sense,
but in a descriptive one; low-level technologies are properly and inevitably
oriented towards low-level interests, providing tightly-coupled integration, 
static binding, and strong type-checking appropriate to the relatively 
closed universe problems of characteristic of fabrication.

Examples of assembly technologies are Smalltalk and Objective-C (chip-level
integration), Fabrik and Metaphor (card-level integration), and the Unix
shell (rack-level integration).

-- 

Brad Cox; cox@stepstone.com; CI$ 71230,647; 203 426 1875
The Stepstone Corporation; 75 Glen Road; Sandy Hook CT 06482

cox@stpstn.UUCP (Brad Cox) (02/10/91)

In article <88106@tut.cis.ohio-state.edu> William F Ogden <ogden@cis.ohio-state.edu> writes:
>
>The question is whether large composite software objects are in any essential
>way distinguishable from programs. Does programming consist of anything
>but composing simpler objects to create more complex ones? The only thing
>that seems to change from paradigm to paradigm is the collection of
>composition mechanisms.

What varies along the continuum from large to small is late vs early binding.
By this, I mean the factors that manufacturing engineers consider when choosing
between early binding fabrication technologies like forging and casting
and late binding assembly technologies like bolting, welding, soldering,
mortising, screwing, glueing, etc, etc.

In case these distinctions seem irrelevant, consider opposing technologies
for the binding operation; skiier = skiis + person. With a late binding
assembly technology (such as many skiiers apparently prefer), binding
occurs late. With an early binding fabrication technology (binding at
conception time), the great potential advantages (greater skiier efficiency, 
no opportunity for binding errors, etc, etc) tend to succumb to the loss 
in reusability.

Since the terminology, early vs late binding, seems to becoming a matter
of religious belief these days, I find that the alternate terminology,
tight vs loose coupling, is advisable when hoping for rational consideration
of the rather obvious and non-controversial engineering tradeoffs involved
in choosing between them. The point is that it is silly to choose between
them as a matter of dogmatic principle regardless of the application domain.
Why not keep one's options open and choose the right tool for the job on hand?

This is the essence of the argument against purist approaches like Ada
on the one hand (pro tight coupling) and Smalltalk on the other (pro loose
coupling). This is why I believe so strongly in hybrid approaches like
Objective-C, CLOS, (and to a lesser extent due to its leanings toward
tight coupling) C++.

-- 

Brad Cox; cox@stepstone.com; CI$ 71230,647; 203 426 1875
The Stepstone Corporation; 75 Glen Road; Sandy Hook CT 06482

cwk@ORCRIST.GANDALF.CS.CMU.EDU (Charles Krueger) (02/10/91)

In article <318@smds.UUCP>, sw@smds.UUCP (Stephen E. Witham) writes:
> But someday soon we'll have
> "component software" (as distinct from software components) by analogy to
> component stereo--software the user plugs together.  And maybe "software
> composition" or "software compositing."

This was exactly the vision of McIlroy when he introduced the notion of
software reuse at the NATO Software Engineering Conference in 1968 (which
was also the birthplace of Software Engineering).  Meanwhile, 23 years
later...

djbailey@skyler.mavd.honeywell.com (02/12/91)

In article <6248@stpstn.UUCP>, cox@stpstn.UUCP (Brad Cox) writes:
> In article <87829@tut.cis.ohio-state.edu> you write:
>>Brad, in suggesting a replacement for the word "reusable" as
>>applied to software components, you suggest that some opponents of the
>>idea might argue:
>>
>>>"Reusability! Why 'reuse' software, when any fool knows it is cheaper
>>>to throw used bits away and copy more from a master as needed."
>>
>>Seriously, now, have you really faced this sort of response to your
>>ideas?  I knew we were having some trouble communicating with certain
>>communities, but it never occurred to me that the problems might run
>>so deep :-).
> 
> I threw that example out as one of many possible ways of misunderstanding,
> not the only one. No one has made this particular argument, at least not to
> my face.But I have sat thru a number of debates of the form "Reuse? Computers 
> reuse code incessantly. Every operating system call, every pass through a 
> loop, etc, etc".

Yes, the problem with software reuse is not that it seems too hard,
but that it seems too easy. Every programmer and every organization
reuses software on a local scale.  When your customers ask for an
enhancement, they are attempting to reuse old software and old
designs. Software Reuse advocates want to go beyond the local scale 
and there are some non-obvious technical problems in the way.

> Incidentally, I've been pushing this gate, block, chip, card, rack-level 
> terminology for precisely the same reason that I'm pushing division of
> labor. I've wondered why some programmers reject it as a controversial
> statement of some kind of radical position, when I view it as unremarkable
> common sense.

I am inclined to reject your terms because I believe you are not
addressing the right problems.  The analogy to hardware is useful if 
it is not carried too far.  The decision to build or reuse software is 
similar to the decision to make or buy hardware.  The cost of finding 
the right software is usually too high to permit more than very local 
reuse. This is partly a search problem and partly something else.
 
>>... Maybe we
>>could resurrect the discussion here (mostly flames) of a couple years
>>ago when we suggested that software components should be sold as
>>specification + object code, and that source code should remain
>>hidden.  Talk about a hard sell...
> 
> By all means, do! I've stirred this pot hard enough and long enough
> during the last several years to become convinced that there is no
> technical obstacle to a specification/testing language as outlined
> in my IEEE paper. The obstacles are not technical, but cultural. 

I haven't read your paper, but I would be interested in how your 
technique might apply to this real world example.  I worked on some 
flight control applications using assembly language for a special 
purpose microprocessor.  It was an embedded hard real time application 
using scaled fixed point arithmetic in all of its computations. We 
used a sine routine that was a polynomial approximation of the Taylor 
series for sine.  The sine routine was reused successfully on several 
projects, a case of local reuse.  A few years later, the sine routine 
was reused in a navigation system, another embedded hard real time 
application.  We discovered in testing that the sine approximation had 
it's largest error from the true sine at precisely the angle needed to 
align the gyroscopes of the navigation system. A simple, well defined, 
routine that had been reused successfully in one application domain 
failed in a very similar application domain.

A sine routine ought to be a very good candidate for a reusable
component, but we got bit by a subtle problem.  This is one case where
the algorithm selected was very important and I am interested in how a
"specification and object code" system would handle it. In real time
systems and probably in many others, the specific algorithmic details
of components can become very important. 

-- Don J. Bailey

lfd@cbnewsm.att.com (Lee Derbenwick) (02/12/91)

In article <27B2EADB.5840@tct.uucp>, chip@tct.uucp (Chip Salzenberg) writes:
> According to sw@smds.UUCP (Stephen E. Witham):
> >Someday soon we'll have "component software" (as distinct from software
> >components) by analogy to component stereo ...
> 
> That's already here -- cf. UNIX tools.  The question is, will _all_
> programming eventually be cookbook work?  Only when all problems are
> cookbook, i.e. never.

Exactly.  Component stereo does a very limited set of activities, with
a very simple interface.  As a result, you can just plug them in and
they work.  The UNIX tools (filters, anyway) have a similarly simple
interface: a stream of ASCII characters with newlines every so often.
They just plug together, too.

But I think a lot of people advocating "chip-level" and "board-level"
software components haven't been paying attention to what really
happens in hardware.

The simplest components (quad nand gates, etc.) just plug together, but
they are so simple as to be the equivalent of assembler language.  More
complex devices used to be tied together with lots of these "glue" chips
-- sort of the equivalent of writing a C program using a subroutine
library that does some of what you want, but not all, and with
incompatible data structures that require conversion.

But hardware has been moving much closer to taking general-purpose,
complex chips and just plugging them together, with relatively little
glue logic.  The key to this is that general-purpose, complex chips
are now usually programmable.

Microprocessors are obviously programmable.  But many I/O devices are
now general-purpose, with a bus interface over which they take commands
that will configure them into the desired behavior.  And programmable
gate arrays have taken over much of the function of random logic; you
either specify the programming and the manufacturer builds you 10,000
of them with your program built in, or you buy a user-programmable one
and burn your program into it.

What does this mean for software components?  If we want reasonably-
sized, plug-in components, they are going to have to be made more general,
then "programmed" or configured in some fashion either before or after
plugging them in.  Database systems are an example of this; so are the
Unix tools, which are general-purpose and become specialized to use in a
specific pipeline by command-line options.

The arguments over exactly what the semantics and implementation of a
stack should be might be subsumed by a "list application generator" that
gives the user their choice of stack, queue, and dequeue implementations
for a limited range of specifications (e.g., error-checking in the
application vs. in the stack itself; fixed-maximum-size vs. dynamically
allocated, etc.).  In that scenario, you wouldn't buy a _stack_ from the
Reusable Software Shop; you'd buy a _stack builder_.

 -- Speaking strictly for myself,
 --   Lee Derbenwick, AT&T Bell Laboratories, Warren, NJ
 --   lfd@cbnewsm.ATT.COM  or  <wherever>!att!cbnewsm!lfd

ogden@seal.cis.ohio-state.edu (William F Ogden) (02/13/91)

In response to:

>>The question is whether large composite software objects are in any essential
>>way distinguishable from programs.

Brad Cox writes:

>What varies along the continuum from large to small is late vs early binding.

>                           ...  I find that the alternate terminology,
>tight vs loose coupling, is advisable when hoping for rational consideration
>.... 

Late vs early binding (or tight vs loose coupling) is certainly an issue in
programming, but it seems independent of component size. Even in the
stereo component analogy that raised this question, engineers often opt
for the early-binding/tight-coupling solution of putting a popular collection
of `components' into a single product (thereby realizing one of the
obvious advantages of early binding -- namely cost saving).

/Bill

weide@elephant.cis.ohio-state.edu (Bruce Weide) (02/15/91)

In article <1991Feb11.103100.112@skyler.mavd.honeywell.com>
djbailey@skyler.mavd.honeywell.com writes:
>
>A sine routine ought to be a very good candidate for a reusable
>component, but we got bit by a subtle problem.  This is one case where
>the algorithm selected was very important and I am interested in how a
>"specification and object code" system would handle it.
>

Handling this problem (a sine routine that isn't too accurate for some
particular range of values) in a "specification and object code" reuse
scenario is based on the idea that a single abstract concept can have
multiple plug-compatible implementations.  Bill Ogden's recent note
about the specification of such an abstraction as a sine routine is
important.  The specification is relational, i.e., it doesn't say that
the routine must return the mathematical sine of its argument; it says
that the value returned is within some bound of the true sine.  (The
allowable error may even be a parameter to the reusable component that
exports the sine routine.  Call it a tolerance if you want :-).)

Now there are many possible implementations of a sine function that
satisfy this behavioral specification.  Any of them should work.
However, some may be more or less efficient, in one sense or another.
Perhaps some are faster for arguments near zero, others for arguments
away from zero, or whatever.  It is not necessarily true that one
implementation dominates the others in all relevant performance
dimensions.

If I sell you the behavioral specification along with object code (and
preformance information for each implementation) -- but NOT source
code -- you still have all the information you need in your example.
Of course, I should also guarantee that the object code works, but
that will be needed in any case.  Will you trust me if I say that,
even if I don't provide source code?  (Possibly not... do you trust,
say, the Macintosh toolbox?  Seems pretty robust to me, and I've never
seen the source code for it.)  But certainly in principle there is no
reason to believe that your own methods of certifying correctness of
implementations should be any better than those of, say, an
independent laboratory that offers its official seal of approval.

	-Bruce

dave@cs.arizona.edu (Dave P. Schaumann) (02/15/91)

In article <88431@tut.cis.ohio-state.edu> Bruce Weide <weide@cis.ohio-state.edu> writes:
>In article <1991Feb11.103100.112@skyler.mavd.honeywell.com>
>djbailey@skyler.mavd.honeywell.com writes:
>>
>>A sine routine ought to be a very good candidate for a reusable
>>component, but we got bit by a subtle problem.  This is one case where
>>the algorithm selected was very important and I am interested in how a
>>"specification and object code" system would handle it.
>>
>
>Handling this problem (a sine routine that isn't too accurate for some
>particular range of values) in a "specification and object code" reuse
>scenario is based on the idea that a single abstract concept can have
>multiple plug-compatible implementations.  [...]

Now I see the crux of the reusability issue.  What we need is well-defined
interfaces between code.  The sine function is a good example of this: you
pass it a floating point value, and you get a floating point value back.
Every language I've seen with sine in it had it defined this way.

Naturally, the more polymorphic your language is, the more powerful this idea
will be: pass a double (ala C) to the same code in a polymorphic language,
and you get a double back.

Here, you really don't need to know whether your stack is an array, a linked
list, or some other construct.  All you need to know is the interface.  When
you have polymorphism, you don't even need to specify what kind of data
elements you have.

Thus, I would propose that a necessary feature of any programming environment
generating reusable code would provide two features: strictly defined code
interfaces, and polymorphic parameters.  Naturally, it would be nice to have
your language support these features, but you still need the programmer to
use the features in a disciplined manner.

We already have languages with various combinations of these features: ML, CLU,
C++, Ada, etc.  What we really need now is to learn how to use these features
to enhance the reusability of our code.  Not just to understand the concepts
involved, but to actually use them in practice.  This, I think, points out a
major weakness in computer science education (at least in my experience).  I've
been taught structured programming, object oriented programming, algorithms,
analysis, and lots of theory.  But what has never really been stressed is the
discipline required to be a good programmer.  Discipline in style, structure,
and planning.  Ultimately, I believe that it is the discipline of the
programmer, as much as any language feature or advance in theory that makes the
difference in how reusable (and modifiable, and debuggable...) the code is.

In closing, let me leave you with an example mentioned in this group a few
weeks ago.  Someone had the odious task of maintaining a program that contained
a function consisting ofmore than 1000 lines of code.  The original
programmer(s) must have thought they were saving something by not abstracting
*any* of those 1000 lines, but how can any savings in development time or
savings in run time balance the headaches generated by trying to understand
such a beast?  This is really the essence of discipline: a bit more work now
will save volumes of work later.
-- 
Dave Schaumann      | DANGER: Access holes may tear easily.  Use of the access
		    | holes for lifting or carrying may result in damage to the
dave@cs.arizona.edu | carton and subsequent injury to the user.

jls@yoda.Rational.COM (Jim Showalter) (02/15/91)

>In that scenario, you wouldn't buy a _stack_ from the
>Reusable Software Shop; you'd buy a _stack builder_.

Disagree. A stack is not a sufficiently macro-scale abstraction to
require such overkill. A much more appropriate component requiring
configurability might be an entire message passing layer: this is
a large scale chunk of a system, highly reusable if implemented
properly, and greatly in need of "strapable" options in order to
be flexible enough to meet many different networking protocols,
communication requirements, etc. In this case, yes, it makes sense
to provide lots and lots of configuration options, which could be
supplied as arguments (to subprograms and/or generics), read in from
configuration files, etc. This is the strategy taken by one of our
more successful customers.

----

These are my opinions.

mcgregor@hemlock.Atherton.COM (Scott McGregor) (02/16/91)

In article <88431@tut.cis.ohio-state.edu>,
weide@elephant.cis.ohio-state.edu (Bruce Weide) writes:

> But certainly in principle there is no
> reason to believe that your own methods of certifying correctness of
> implementations should be any better than those of, say, an
> independent laboratory that offers its official seal of approval.

The problem is that even if an independet laboratory offers its seal of
approval, you still have to certify it yourself anyway.  There are two
reasons for this.  First, the possibility that your intended use would be
regarded as extreme or abberant by the original designers and laboratory
testers, in which case you will have to test just to verify that this
special case is correctly handled by the purchased object code.  Second,
there is always the possibility that you the purchaser misunderstood what
the vendor offered, and that the product you purchased won't suit your
needs. Since externally it may seem what you wanted, you may not notice
this until you use it. (E.g. you want a character sort routine that uses
ascii sort order, but the one you bought uses "dictionary rules" that sorts
caps and lowercase the same and sorts Mc* as if written Mac*...). 

So it is not the case that the one's own methods are necessarily better
at determining correctness to specification, but rather that they are
more specific for determining applicability to the situation at hand.
We use an object oriented system to do our development and inherit from
objects created by others.  The amount of testing necessary on the INHERITED
CODE boggles people's minds.  Not that the inherited code is necessarily
buggy, but rather not well understood in special circumstances.  By inheriting
a lot, one might be able to create a complex system with a day's coding and
testing on the new module.  But until the developer is completely familiar
with inherited objects there will need to be lots of testing with them!
If no source is available, and no  way to determine branch coverage in
the inherited modules, testing is purely black box and may need to be more
intensive than if the developer could see in and use some white box methods.

This imbalance in the huge reduction of coding but relatively little reduction
in testing astonishes people who assume that testing and coding efforts will
be linearly related.  It can also pose a problem in managing the internal
reward structures of the developers.  Many current  programmers find the
new code development the internally rewarding part, and find testing 
unrewarding work.  They can be frustrated in an environment that reduces
the source of internal rewards and increases the relative amount of 
unrewarding work.  Of course, you could fire the existing  programmers
and hire people with different internal reward structures who will enjoy
the testing work more. From a cold mechanical viewpoint this may seem
fine, but when you consider that there are real people out there already
doing programming work and contributing to the success of their companies,
and that this means huge dislocations for them, you can see that this
is a nasty human management problem, and is quite a challenge for
OO purveyors and supporters who go beyond theoretical benefits and look
into the actual problems of implementation of OO technologies in organizations.

One resulting observation is that perhaps OO technologies will work best not
in CS's most technical inner sanctums, but among end users themselves who
may have very different internal reward structures, career goals  and
desires. 

Scott McGregor
Atherton Technology
mcgregor@atherton.com

jls@yoda.Rational.COM (Jim Showalter) (02/18/91)

Your points about testing requirements are interesting, and there has
been a lot of discussion of this in the Ada community because Ada provides
generics, which can be reused indefinitely PROVIDED they are trusted.

The odd thing is, people worry about testing inherited code, but they
are looking at it wrong, I think. If you have gotten some software that
asserts it can be inherited from, you should treat that software like
an IC. You don't second-guess Intel, right? If the software DOES break,
it should be something you can take to the courts, just as a chip that
failed to perform to spec would be grounds for restitution.

Until people get comfortable with the idea of off-the-shelf software being
just as much of a black box as ANY OTHER COMMODITY, we will continue to
battle this weird behavior. Do you second guess anything else you buy?
No? Then why second-guess software modules?
--
***** DISCLAIMER: The opinions expressed herein are my own. Duh. Like you'd
ever be able to find a company (or, for that matter, very many people) with
opinions like mine. 
                   -- "When I want your opinion, I'll beat it out of you."

adams@aar.alcatel-alsthom.fr (Drew Adams) (02/18/91)

In article <7085@exodus.Eng.Sun.COM> donm@margot.Eng.Sun.COM 
(Don Miller) writes:

>... treat code intended for reuse with great respect.  
>    This ... means focused functionality.
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>    Code which tries to be all things to all people is unlikely
>    to be really useful to anyone.

I agree 100%.  However, how are we then to interpret `functionality'?
Normally, one would expect  the term  to refer  to the  use(s) of the
thing  being  defined.    If  so,  then  isn't  this  an argument for
function-oriented,  as   opposed  to   object-  or  datatype-oriented
organization?  What, then, about  Bertrand Meyer's  argument (I don't
know  if  he  was the  first) that  function (use,  purpose) tends to
evolve more quickly than (abstract) data structure etc.?  

In  type-  or  object-orientation,  which  make  maximum  use of data
abstraction, the functionality, or use, of instances of  a given type
or class is part of its definition.  

Perhaps a loose interpretation  of `functionality'  should be assumed
here, that would also apply to objects.  Certainly `focussed' objects
and  datatypes  are to  be preferred  over those  that try  to be all
things to everyone.  
-- 
Drew ADAMS:     adams@aar.alcatel-alsthom.fr       Tel. +33 (1) 64.49.11.54 
            ALCATEL ALSTHOM Recherche, Route de Nozay, 91460 MARCOUSSIS, FRANCE

jerry@TALOS.UUCP (Jerry Gitomer) (02/18/91)

jls@yoda.Rational.COM (Jim Showalter) writes:

:Your points about testing requirements are interesting, and there has
:been a lot of discussion of this in the Ada community because Ada provides
:generics, which can be reused indefinitely PROVIDED they are trusted.

:The odd thing is, people worry about testing inherited code, but they
:are looking at it wrong, I think. If you have gotten some software that
:asserts it can be inherited from, you should treat that software like
:an IC. You don't second-guess Intel, right? If the software DOES break,
:it should be something you can take to the courts, just as a chip that
:failed to perform to spec would be grounds for restitution.

:Until people get comfortable with the idea of off-the-shelf software being
:just as much of a black box as ANY OTHER COMMODITY, we will continue to
:battle this weird behavior. Do you second guess anything else you buy?
:No? Then why second-guess software modules?

Although I am comfortable with the idea I am not comfortable with
using inherited code that I do not completely understand.  To me,
it sounds like we need some standards that *thoroughly* describe
the nature and characteristics of the inherited code -- a set of
engineering specs, if you will.  Something that corresponds to
the chip vendors data book and fact sheets would probably be the
way to go.  
-- 
Jerry Gitomer at National Political Resources Inc, Alexandria, VA USA
I am apolitical, have no resources, and speak only for myself.
Ma Bell (703)683-9090      (UUCP:  ...{uupsi,vrdxhq}!pbs!npri6!jerry 

lfd@cbnewsm.att.com (Lee Derbenwick) (02/19/91)

In article <jls.666591427@yoda>, jls@yoda.Rational.COM (Jim Showalter) writes:
  [I wrote:]
> >In that scenario, you wouldn't buy a _stack_ from the
> >Reusable Software Shop; you'd buy a _stack builder_.
> 
> Disagree. A stack is not a sufficiently macro-scale abstraction to
> require such overkill.

That's likely, which is why I said a general-purpose list handler
(generating numerous flavors of stacks, queues, dequeues, etc.)
would be a more appropriate size.

That _is_ still pretty small, but it's big enough to be useful.
And much of this thread has dealt with reusable elements on the
size of _a single stack implementation_, and then gotten into
arguing about the exact features such a thing should have.

Consider this small-to-medium scale integration.  It won't become
practical until the emergence of good tools for building X-builders.

And even then, this is probably too small to _market_ separately; it
would probably come bundled with a bunch of similar-sized component
builders for different components.  A library of component builders,
just as you might today buy a library of statistical routines, or of
graphical routines.

> A much more appropriate component requiring
> configurability might be an entire message passing layer: this is
> a large scale chunk of a system, highly reusable if implemented
> properly, and greatly in need of "strapable" options in order to
> be flexible enough to meet many different networking protocols,
> communication requirements, etc. In this case, yes, it makes sense
> to provide lots and lots of configuration options, which could be
> supplied as arguments (to subprograms and/or generics), read in from
> configuration files, etc. This is the strategy taken by one of our
> more successful customers.

A good example of a larger-scale configurable component.  Such a
component is big enough on its own to justify a lot work on hand-
crafted configuration capabilities.  Smaller configurable components
will need to reuse much of the configuration and "strapping" code
before they are equally practical.

 -- Speaking strictly for myself,
 --   Lee Derbenwick, AT&T Bell Laboratories, Warren, NJ
 --   lfd@cbnewsm.ATT.COM  or  <wherever>!att!cbnewsm!lfd

lfd@cbnewsm.att.com (Lee Derbenwick) (02/19/91)

In article <1127@TALOS.UUCP>, jerry@TALOS.UUCP (Jerry Gitomer) writes:
> jls@yoda.Rational.COM (Jim Showalter) writes:
[ ... ]
> :The odd thing is, people worry about testing inherited code, but they
> :are looking at it wrong, I think. If you have gotten some software that
> :asserts it can be inherited from, you should treat that software like
> :an IC. You don't second-guess Intel, right? If the software DOES break,
> :it should be something you can take to the courts, just as a chip that
> :failed to perform to spec would be grounds for restitution.

You _always_ second-guess Intel (or any other manufacturer) and prototype
the circuit first.  Prototyping mostly catches your own design errors,
but it also catches the case where one particular chip has insufficient
noise immunity or just happens to oscillate _in your circuit_.

Sometimes you modify the circuit; sometimes you find a different
manufacturer whose chip (for the same function) doesn't have that
problem.

> :Until people get comfortable with the idea of off-the-shelf software being
> :just as much of a black box as ANY OTHER COMMODITY, we will continue to
> :battle this weird behavior. Do you second guess anything else you buy?
> :No? Then why second-guess software modules?

Do you buy a car without a test drive?  Do you buy a suit without trying
it on?  Most software is vastly more complex than most things we buy, but
there are still lots of things we test first.

> Although I am comfortable with the idea I am not comfortable with
> using inherited code that I do not completely understand.  To me,
> it sounds like we need some standards that *thoroughly* describe
> the nature and characteristics of the inherited code -- a set of
> engineering specs, if you will.  Something that corresponds to
> the chip vendors data book and fact sheets would probably be the
> way to go.  

The data book helps, but it still never does the complete job.  The
sine routine that someone else mentioned is a good example: its behavior
was good enough on average, but its worst-case error happened to be
around the most critical values for one application.  The spec sheet
is not normally going to give you a chart of error tolerance (or time
delay, or whatever) vs. input values.  And a routine that was
sufficiently accurate for _all_ values would presumably have been
more expensive to execute -- it might well not have been feasible
either.

One big difference is that, for reusing software, we normally have a
single sample that we must either reuse or not.  And even if there are
multiple vendors, we generally have to pay in full for the software if
it meets its published specs, whether or not we end up being able to
use it.

Whereas two or three samples of a hardware component are _much_ cheaper
(sometimes free) than what we will spend once we start manufacturing in
quantity.  So our prototyping lets us find out whether the chip is
useful to us _before_ we've paid for an order of 100,000 of them...

 -- Speaking strictly for myself,
 --   Lee Derbenwick, AT&T Bell Laboratories, Warren, NJ
 --   lfd@cbnewsm.ATT.COM  or  <wherever>!att!cbnewsm!lfd

mcgregor@hemlock.Atherton.COM (Scott McGregor) (02/20/91)

> The odd thing is, people worry about testing inherited code, but they
> are looking at it wrong, I think. If you have gotten some software that
> asserts it can be inherited from, you should treat that software like
> an IC. You don't second-guess Intel, right? If the software DOES break,
> it should be something you can take to the courts, just as a chip that
> failed to perform to spec would be grounds for restitution.

You may not second guess Intel, but I can assure you that when before you
commit to a particular hardware design you build a breadboard prototype
and test the joint suitability of the components you have selected. 
It is very likely that you will unit test some components even before that
stage.   The reason is not that you don't trust the vendor, but that
there are so many variables that might interact in unforseen ways, and
because your particular use may rely on a very special aspect of what the
IC can do.  The discussion of Tolerances is relavant, in that your 
particular design may be more or less tolerant to small differences in
voltage, capitance, etc.   Note that this most particularly the problem
for the many small infrequently chosen components. It is true that the
more you get in the habit of reusing the same component the more you
have already tested it, and so the more you can trust it. A 386 might
be the heart of many designs and so well understood and tested, but
how about various special purpose chips: DtoAs, AtoDs, board-to-bus linkages
chips for creating packets for networks, audio, video, pattern recognition
chips...  Many of the chips are of the mundane variety, but specially
chosen for that particular board, and the designer may have to refer to
many manuals to chose among many possible selections.  They won't be
sure until they test  it.  

The same situation holds for software.  Testing an inherited component
is necessary not because you don't trust (or because you second guess)
it's designer.  But because it is the only way to verify that it will
behave exactly the way you expect in the EXCEPTIONAL CIRCUMSTANCES of
your particular application, and be sure that you were correct in your
assumption of it's suitability.  Common things like "strcat" may be
easy to understand and verify their suitability for your use.  But
more complex things like "performs a branch flow coverage test over
software in question" have many more degrees of freedom to test and more
sources of confusion or misconnected expectations between software IC
developer and consumer.

> Until people get comfortable with the idea of off-the-shelf software being
> just as much of a black box as ANY OTHER COMMODITY, we will continue to
> battle this weird behavior. Do you second guess anything else you buy?
> No? Then why second-guess software modules?

My developers *do* treat inherited code much the same as other commodities.
Sometimes it gets us in trouble when it doesn't act the way we expected
it to (or said in a different way, when we don't expect it to act the
way it actually does).  So we have to test it to prevent later errors. 
In other more mature commodity markets there are established test labs
with publishing arms
(e.g. Consumer Reports) that can carry some of the burden.  But note that
when you get to a commodity with as much variation and complexity as an
automobile, then even Consumer Reports recommends that you test drive it first
and not just order one by phone from an autobroker and have it delivered.

The problem is not just getting people to treat inherited code like other
commodities, but  that people are tempted to assume that they can treat it
as even more homogenous than other commodities--tempting them to skip 
over necessary incoming verification for suitability of use. This leads
to many unfortunate design problems not detected until final QA or until
expensive failures in the field.

Scott McGregor
Atherton Technology
mcgregor@atherton.com

ogden@seal.cis.ohio-state.edu (William F Ogden) (02/20/91)

Lee Derbenwick writes:
    ....
#The data book helps, but it still never does the complete job.  The
#sine routine that someone else mentioned is a good example: its behavior
#was good enough on average, but its worst-case error happened to be
#around the most critical values for one application.  The spec sheet
#is not normally going to give you a chart of error tolerance (or time
#delay, or whatever) vs. input values.  ....

I say that if you really want reusable software components, then
you're going to view a spec for a sine routine that doesn't include
error tolerances (or execution times, etc.) as simply inadequately
specified.


#Do you buy a car without a test drive?  Do you buy a suit without trying
#it on?

For peace of mind, you may want to take it out for a test drive, but
you really can't afford to test whether it meets all its specs. Do
you check the oil capacity, the generator output, the compression ratio,
the horsepower rating, etc.? When buying clothing, do you check the 
durability, colorfastness, shrikage, wrinkle resistance, etc.?

/Bill

edwards@rutabaga.cis.ohio-state.edu (stephen edwards) (02/20/91)

In article <867@caslon.cs.arizona.edu> dave@cs.arizona.edu (Dave P. Schaumann) writes:
>
>Now I see the crux of the reusability issue.  What we need is well-defined
>interfaces between code.

Horray!  You're not the only one who believes this is a crucial issue.

>The sine function is a good example of this: you
>pass it a floating point value, and you get a floating point value back.

Yikes!  Wait a minute ... I thought you said well-defined interfaces were
crucial.  Saying "sine" takes a float and returns a float is about as ill-
defined as an interface can be!  (A sad statement, since you're right that
it's that way in most languages.)  In fact, if we're this lax with our
interface definitions, the sin(x), cos(x), sqrt(x), square(x), ....
all have the _same_ interface.  A simple syntactic interface description
does not constitute a "well-defined interface."  Semantics are crucial.

>Naturally, the more polymorphic your language is, the more powerful this idea
>will be [ ...]

Polymorphism can be a useful tool, but it adds _nothing_ to a purely syntactic
interface description.

>When you have polymorphism, you don't even need to specify what kind of data
>elements you have.

Nope.  This just doesn't fly.  Basically, any operation (e.g, sin(x),
or push(y, stack) to follow on your stack example) has certain semantic
requirements on the operations available for its arguments and the
behavior of those operations.  These are _semantic_ restrictions that
are part of (inherent in) the interface of sin(x), etc.  If you operation
is polymorphic, you can't put an object of "just any" type into it, you
can only put in objects on which the necessary operations (required by
sin(x), or whatever) (a) are defined, and (b) meet the required semantic
restrictions.

Languages which do not allow you to express these requirements simply
do not allow _fully defined_ interfaces.  Polymorphic systems which do
not enforce such constraints on parameters simply do not ensure conformance
to a _fully defined_ interface.  Of course, the latter point may be moot
if the fully defined interface can't even be described in the language
under question.

>We already have languages with various combinations of these features [...]
>What we really need now is to learn how to use these features [ ... ]

We may be farther away than you indicate.

>Ultimately, I believe that it is the discipline of the programmer, as much
>as any language feature or advance in theory that makes the difference in
>how reusable (and modifiable, and debuggable...) the code is.

Ah, with this I cannot disagree.  Even though well-defined interfaces are
crucial, simply the capability to describe (and enforce) such interfaces
is not enough to make software reuse a success.  These capabilities are
merely enabling steps, and it will still require disciplined programmers to
use such capabilities effectively.


				-- Steve

Stephen Edwards					U.S. mail: 372 Jones Tower
e-mail    : edwards@cis.ohio-state.edu	           	   101 Curl Drive
home phone: (614)-293-0842			 	   Columbus, OH  43210

lfd@cbnewsm.att.com (Lee Derbenwick) (02/20/91)

In article <88637@tut.cis.ohio-state.edu>,
ogden@seal.cis.ohio-state.edu (William F Ogden) writes:
> Lee Derbenwick writes:
>     ....
> #The data book helps, but it still never does the complete job.  The
> #sine routine that someone else mentioned is a good example: its behavior
> #was good enough on average, but its worst-case error happened to be
> #around the most critical values for one application.  The spec sheet
> #is not normally going to give you a chart of error tolerance (or time
> #delay, or whatever) vs. input values.  ....
> 
> I say that if you really want reusable software components, then
> you're going to view a spec for a sine routine that doesn't include
> error tolerances (or execution times, etc.) as simply inadequately
> specified.
> ...

Error tolerances will normally be expressed in terms of average or
RMS and worst-case errors.  They are _not_ going to tell you, "By
the way, the worst-case negative error is at 44 degrees and the
worst-case positive error at 46 degrees."  If you are concerned about
values near 45 degrees, this may well be a problem.  In fact, a
discontinuity in the error might be a serious problem: are you also
going to spec limits on the first derivative of the error?

If, for your application, you spec the derivative of the error, what will
you do when none of the spec sheets for available "sine-function parts"
happen to mention it?

In hardware spec sheets, you will probably find "typical" and "worst-
case" delays.  And you probably can't afford to design conservatively
enough to use only worst-case delays; someone else will undersell you
by half the price by figuring out how to avoid the worst-case conditions.
(The terminal you're reading this on would probably stop working if all
of its components suddenly started operating at their worst-case specs.)

In the sine-function example, the significant cost may be execution time.
You might have two sine function implementations readily available: a
single-precision one that meets your execution time spec with acceptable
RMS error; and a double-precision one whose worst-case error is guaranteed
to cause you no trouble, but that you can't use because it's too slow.

You have to try the single-precision one, but you may then discover that
its worst-case error is exactly at your operating point.  You can no
longer use it, and you may have to roll your own rather than get any
reuse.

In many cases a spec sheet will be adequate; in many it will not give
enough data about the exact operating conditions that concern you.

 -- Speaking strictly for myself,
 --   Lee Derbenwick, AT&T Bell Laboratories, Warren, NJ
 --   lfd@cbnewsm.ATT.COM  or  <wherever>!att!cbnewsm!lfd

mcgregor@hemlock.Atherton.COM (Scott McGregor) (02/20/91)

In article <88637@tut.cis.ohio-state.edu>, ogden@seal.cis.ohio-state.edu
(William F Ogden) writes:

> I say that if you really want reusable software components, then
> you're going to view a spec for a sine routine that doesn't include
> error tolerances (or execution times, etc.) as simply inadequately
> specified.

The flip side is that if data books are swamped with too much special
case information then they
may be overly complex to read and retrieve information from.  If that
occurs, the market may
indicate its preference for less complete information but easier to
read.  Moreover, the 
consumer may think in terms of a specific application question, and may
not know how that
translates to the general design specs.  E.g. User wants to know how
fast will the spec'ed car
go 0-60 while pulling a trailer weighing 1000 lbs; Datasheet only gives
engine displacements.
 
So, the consumer may not always be knowledgeable enough to convert the
general specs to their
application specific needs-- and the designer may not forsee all
possible applications.  The market
may need to mature significantly, and both consumers and designers
become more educated about
each other for a considerable amount of time before this kind of reuse
becomes pervasive.

> 
> #Do you buy a car without a test drive?  Do you buy a suit without trying
> #it on?
> 
> For peace of mind, you may want to take it out for a test drive, but
> you really can't afford to test whether it meets all its specs. Do
> you check the oil capacity, the generator output, the compression ratio,
> the horsepower rating, etc.? When buying clothing, do you check the 
> durability, colorfastness, shrikage, wrinkle resistance, etc.?

When someone buys a *fleet* of cars, they often *do* independent tests,
or pay for consulting from independent testing labs (Consumer Reports,
Road & Track...), that sometimes individuals do not do.  Similarly,
before purchasing large amounts of clothing appropriate features may be
frequently tested.
Important aspects determining whether products are pretested or not
include the product price, and
the number purchased, or amount of use.  Most software systems under
discussion here are large,
and are big ticket items from a product price standpoint.  They may be
used many times.  Purchasers
are often corporations who may indeed require some presales proof of
suitability before buying the
software.  It  is thus important for  the developers who reuse the
software to prove to themselves
that the inherited software they used works as expected--before an
embarassing situation is
discovered by a prospective customer. 

Scott McGregor
Atherton Technology				mcgregor@atherton.com

ogden@seal.cis.ohio-state.edu (William F Ogden) (02/21/91)

Lee writes:
  .....
>Error tolerances will normally be expressed in terms of average or
>RMS and worst-case errors.  They are _not_ going to tell you, "By
>the way, the worst-case negative error is at 44 degrees and the
>worst-case positive error at 46 degrees."  If you are concerned about
>values near 45 degrees, this may well be a problem.  ....

I don't believe that anyone has set out any standards for specifying
reusable numerical software, but it seems unlikely that anything as
simple as worst-case or RMS tolerances would be deemed adequate. Surely
you'd want at least to know an error bound for a sin_approx(x) component as
a function of x. Then you wouldn't have the nasty surprise at 45 degrees.

Numerical software is clearly a domain where you can't pretend that the
names of operations ( e.g. cos, log, etc. ) tell a potential client all
he really needs to know about what they do and where they work. Some
sort of specification standard for this type of software is needed
which takes into account the normal uses of such software -- such as
composing basic operations to make more complex ones. If we don't
figure out how to spec things adequately and just leave potential 
clients to test things out to see what they really do, then they'll
always find it easier to roll their own and reuse will never happen.
/Bill

weide@elephant.cis.ohio-state.edu (Bruce Weide) (02/23/91)

In article <34464@athertn.Atherton.COM> mcgregor@hemlock.Atherton.COM (Scott McGregor) writes:
>
>The problem is that even if an independet laboratory offers its seal of
>approval, you still have to certify it yourself anyway.  There are two
>reasons for this.  First, the possibility that your intended use would be
>regarded as extreme or abberant by the original designers and laboratory
>testers, in which case you will have to test just to verify that this
>special case is correctly handled by the purchased object code.  Second,
>there is always the possibility that you the purchaser misunderstood what
>the vendor offered, and that the product you purchased won't suit your
>needs. Since externally it may seem what you wanted, you may not notice
>this until you use it. (E.g. you want a character sort routine that uses
>ascii sort order, but the one you bought uses "dictionary rules" that sorts
>caps and lowercase the same and sorts Mc* as if written Mac*...). 
>

We must be talking about slightly different things.  You're talking
about some particular programming language or paradigm that you use in
practice (apparently), while I'm talking about how software reuse
OUGHT to be done.

For example, your remarks further highlight why reusable software
components need to have formal specifications of their behavior as
ABSTRACT components.  The vendor's specification says what the
component is supposed to/guaranteed to do; precisely under what
conditions it works and precisely what it does under those conditions.
What ordering is used by a sort routine, for example, certainly
belongs in the specification (or should be a parameter to it).  It's
not clear why you inherently need source code for the sorting
algorithm to determine this.

>
>So it is not the case that the one's own methods are necessarily better
>at determining correctness to specification, but rather that they are
>more specific for determining applicability to the situation at hand.
>We use an object oriented system to do our development and inherit from
>objects created by others.  The amount of testing necessary on the INHERITED
>CODE boggles people's minds.  Not that the inherited code is necessarily
>buggy, but rather not well understood in special circumstances.  By inheriting
>a lot, one might be able to create a complex system with a day's coding and
>testing on the new module.  But until the developer is completely familiar
>with inherited objects there will need to be lots of testing with them!
>If no source is available, and no  way to determine branch coverage in
>the inherited modules, testing is purely black box and may need to be more
>intensive than if the developer could see in and use some white box methods.
>

Now you're getting into a serious problem.  Inheritance (of code, at
least, which is what you get in most OO languages) causes major
technical problems in terms of certifying correctness, either by
formal verification or by testing.  Code inheritance is inherently a
"white box" phenomenon... you'd better have source code for the
inherited component if you expect to use code inheritance for much
more than name overloading (and you don't really need inheritance for
this anyway).

Having -- indeed needing -- source code of reused components for
subsequent re-testing is no big deal, then, if you assume a paradigm
in which you need the source code of reused components in any case.
My comments were directed to programming paradigms in which component
reuse occurs not as a result of inheritance, but as a result of reuse
of encapsulated components without violation of abstraction.

	-Bruce

jls@yoda.Rational.COM (Jim Showalter) (02/24/91)

>What ordering is used by a sort routine, for example, certainly
>belongs in the specification (or should be a parameter to it).  It's
>not clear why you inherently need source code for the sorting
>algorithm to determine this.

Indeed, not only do you not need source code for this, in Ada this would
be done by providing a generic sort routine to which you could supply
your own "<" operation (lexicographic or whatever you prefer). In addition,
this parameter could be defaulted to the most likely to be used "<".

>Now you're getting into a serious problem.  Inheritance (of code, at
>least, which is what you get in most OO languages) causes major
>technical problems in terms of certifying correctness, either by
>formal verification or by testing.

Substantiate this: I see no reason why this need be true.

>Code inheritance is inherently a
>"white box" phenomenon...

I'm even more perplexed by this statement. One of Stroustrup's objectives
in designing C++ was to be able to supply BINARY inheritance trees to which
others could add their own inherited code later on. Clearly this not only
does not require white-box visibility, it specifically PROHIBITS it, by
design (it makes it easy to supply code without a source license that is
still extensible by end users).

> you'd better have source code for the
>inherited component if you expect to use code inheritance for much
>more than name overloading (and you don't really need inheritance for
>this anyway).

Again, this makes no sense to me. And I find this particularly vexing because
I'm NOT a big fan of inheritance, so I usually find myself on the OTHER side
of such arguments. But these statements just don't track with my own experience
using (at gunpoint, I'd like to add...) C++ and its inheritance capabilities.
--
***** DISCLAIMER: The opinions expressed herein are my own. Duh. Like you'd
ever be able to find a company (or, for that matter, very many people) with
opinions like mine. 
                   -- "When I want your opinion, I'll beat it out of you."

weide@elephant.cis.ohio-state.edu (Bruce Weide) (02/26/91)

In article <jls.667345738@yoda> jls@yoda.Rational.COM (Jim Showalter)
asks why code inheritance is problematical for verification, etc., and
why I called it an "inherently white-box" phenomenon.

Briefly, what I mean by code inheritance is a situation in which an
heir may directly manipulate the internal representational details of
its ancestor(s).  That is, unlike an ordinary client of a component --
which must rely on an abstract description of the component's behavior
and may use only the interface operations/methods in order to
manipulate it -- an heir using code inheritance may see and directly
manipulate the ancestor's internal representational details, bypassing
the interface operations/methods.  If an heir is not permitted to
violate abstraction like this, what is the use of code inheritance?
The heir might as well be an ordinary client.

The difficulties with verification, testing, etc., arise because of
implementation "conventions" that were used by the ancestor's
implementor, but which are not stated explicitly in the code itself
(because most languages don't have any constructs in which to express
them).  The problems arise even when the heir is permitted only to
manipulate the current internal representation of its ancestor.  It is
not necessary that the heir be able to add "representation features"
(or whatever you want to call them) in order for these problems to
occur.

For example, the implementor of the ancestor might be relying on some
particular relation (a representation invariant) holding at all times.
If an heir comes along and manipulates the representation in such a
way that this invariant is violated then the ancestor's operations may
be broken.  No one has touched the code of the ancestor, but they need
to be reverified, retested, whatever.  This is a disaster.

For a specific example and more information, you might see papers in
Proceedings 8th Annual National Conference on Ada Technology, 1990,
pp. 515-524; and in Journal of Object-Oriented Programming, Jan-Feb
1990, pp. 13-19.

	-Bruce

mcgregor@hemlock.Atherton.COM (Scott McGregor) (02/26/91)

In article <88744@tut.cis.ohio-state.edu>,
weide@elephant.cis.ohio-state.edu (Bruce Weide) writes:
>
>>The problem is that even if an independent laboratory offers its seal of
>>approval, you still have to certify it yourself anyway.  There are two
>>reasons for this.  First, the possibility that your intended use would be
>>regarded as extreme or abberant by the original designers and laboratory
>>testers, in which case you will have to test just to verify that this
>>special case is correctly handled by the purchased object code.  Second,
>>there is always the possibility that you the purchaser misunderstood what
>>the vendor offered, and that the product you purchased won't suit your
>>needs. Since externally it may seem what you wanted, you may not notice
>>this until you use it... 

> We must be talking about slightly different things.  You're talking
> about some particular programming language or paradigm that you use in
> practice (apparently), while I'm talking about how software reuse
> OUGHT to be done.

Perhaps we are talking about slightly different things.  I am not however
talking about a particular programming language or paradigm.  I am however
concerned about the problems that people face in communicating complex
information--not simply how it OUGHT to be done, but how it ACTUALLY 
IS OR IS NOT POSSIBLE to do it. In particular, in the following
comment, it is suggested that formal specification of behavior is sufficient
to solve the problems of misunderstanding without testing that I
described above. I claim it will not as I will attempt to explain. First
the comment:

> For example, your remarks further highlight why reusable software
> components need to have formal specifications of their behavior as
> ABSTRACT components.  The vendor's specification says what the
> component is supposed to/guaranteed to do; precisely under what
> conditions it works and precisely what it does under those conditions.
> What ordering is used by a sort routine, for example, certainly
> belongs in the specification (or should be a parameter to it).  It's
> not clear why you inherently need source code for the sorting
> algorithm to determine this.

I believe that this does not solve the problem I alluded to, although
it may manifest itself in different ways.  First, we must assume that
the formal specifications of behavior correctly capture the what the
actual code does, and not merely what it was intended by its developers
to do.  This is in fact a dangerous assumption, unless it is automatically
generated from the source code--in which case it is merely a translation
and is logically equivalent to having the source code. But people make
mistakes in creating source code, and so while the formal spec may
exactly describe what the code does, this may not in fact be what was
intended by its creator.  To the extent that the formal spec is comprehensive
and complex, it is quite possible that the error will not be discovered
any more than it was discovered in the original code.   Moreover, to
ensure  a correct map between the users requirement and the reusable code,
both will have to not only be in a logical specifications forms
but they both will have to be testable specs, which can be tested to
see if they are equivalent/congruent.  This just brings us
back to the need to test reused objects anyway (now you can presumably
test the spec instead of the actual module, but this does not seem to
me to be inherently different in any important way).  This also still
overlooks the whole possibility that the user's spec is consistent
but flawed from the standpoint of ultimate use--due to inadequate
understanding of the writer of the user's formal specification.

It also ignores the fact that if specifications are lengthy and must
be read to determine if they are appropriate, then only a small number
will be read, and consequently reused. Perhaps it ought not be this 
way, but observation of human behavior suggests that people do act this
way.  Most people consult a small amount of the relavant books in a
library, software in a software library, etc. in order to solve their
problems.

I am afraid I am belaboring this point, but it is an important one. 
In the end, business decisions can only be effectively grounded on
how the people who implement them actually act, and not merely how they
OUGHT to act. Humans are wonderous and yet imperfect creatures.  Theories
that conveniently ignore their failures overlook critical features that
will affect actual real life experience. People are great at communicating
much succinctly, but unfortunately think often think they have communicated
more accurately than they really have.  This leads to all sorts of
design errors.  To the extent that a particular formal specification
language helps people understand certain aspects that are often miscommunicated
then I believe that it helps address some of the problems that I am
discussing.  But that means that a lot of its value is in the ease with
which people grasp it, rather than its mathematical underpinnings, and 
I think that this is where a number of formal specification languages
have fallen down in the past. 

> Now you're getting into a serious problem.  Inheritance (of code, at
> least, which is what you get in most OO languages) causes major
> technical problems in terms of certifying correctness, either by
> formal verification or by testing.  Code inheritance is inherently a
> "white box" phenomenon... you'd better have source code for the
> inherited component if you expect to use code inheritance for much
> more than name overloading (and you don't really need inheritance for
> this anyway).

I believe that this analysis is correct.  Even in environments where
formal correctness and provability are not required, this sort of
testing seems to dominate the reuse considerations.

> Having -- indeed needing -- source code of reused components for
> subsequent re-testing is no big deal, then, if you assume a paradigm
> in which you need the source code of reused components in any case.
> My comments were directed to programming paradigms in which component
> reuse occurs not as a result of inheritance, but as a result of reuse
> of encapsulated components without violation of abstraction.

I see that you distinguish inheritance from encapsulation of abstractions,
and while I admit they are different, I am not sure that I can detect
any ways in which the latter is likely to be more free from the problems
of human communication that I raise than the former is. Rather, it seems
that both are subject to fundamental human limitations of our memory
and communication systems, which is one reason focus on applications which
can aid these human tasks seems an appropriate one for people interested
in software engineering practice.

Scott McGregor
mcgregor@atherton.com
Atherton Technology

		Better Technology, through Living...

jls@yoda.Rational.COM (Jim Showalter) (02/27/91)

>Briefly, what I mean by code inheritance is a situation in which an
>heir may directly manipulate the internal representational details of
>its ancestor(s).  That is, unlike an ordinary client of a component --
>which must rely on an abstract description of the component's behavior
>and may use only the interface operations/methods in order to
>manipulate it -- an heir using code inheritance may see and directly
>manipulate the ancestor's internal representational details, bypassing
>the interface operations/methods.

I can't speak for other inheritance-oriented languages, but it is
certainly the case in C++ that heirs do NOT have direct access to
the private data of the ancestor, any more than does any other client.
Heirs read/modify said private data only through the exported operations
provided by the ancestor. (Protected data and friend classes are another
matter entirely, but we strongly discourage their use for just that
reason.) In short, there are some things you don't even let your
children see!

>If an heir is not permitted to
>violate abstraction like this, what is the use of code inheritance?
>The heir might as well be an ordinary client.

Not true. The value of code inheritance is 1) getting ancestor operations
for free and 2) polymorphism. There has never to my knowledge been a claim
made that inheritance is neat because it allows heirs to diddle ancestors'
private data.

>The difficulties with verification, testing, etc., arise because of
>implementation "conventions" that were used by the ancestor's
>implementor, but which are not stated explicitly in the code itself
>(because most languages don't have any constructs in which to express
>them).  The problems arise even when the heir is permitted only to
>manipulate the current internal representation of its ancestor.  It is
>not necessary that the heir be able to add "representation features"
>(or whatever you want to call them) in order for these problems to
>occur.

>For example, the implementor of the ancestor might be relying on some
>particular relation (a representation invariant) holding at all times.
>If an heir comes along and manipulates the representation in such a
>way that this invariant is violated then the ancestor's operations may
>be broken.  No one has touched the code of the ancestor, but they need
>to be reverified, retested, whatever.  This is a disaster.

All moot if heirs are limited to ancestor's exported operations.

Please excuse this idiotic text here. I am putting it here because
my first attempt to post this was met by the incredibly idiotic
message "Article rejected: news included more text than new text".
So here is some more text blah blah blah blah blah blah blah blah, etc.
I sure wish I could disable this "feature" (any feature that cannot
be disabled is a bug). And here is even more idiotic text. Followed
by some more of it. Blah blah yadda dadda da. Arglebargle ishkabibble
iggeldy diggeldy do. Am I done yet? Do I have enough yet? Is that
enough idiotic text to pacify the newsreader gods?

If not, here is another paragraph of this swill. Blah blah blah blah
what a stoopid feature... Argh!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


--
***** DISCLAIMER: The opinions expressed herein are my own. Duh. Like you'd
ever be able to find a company (or, for that matter, very many people) with
opinions like mine. 
                   -- "When I want your opinion, I'll beat it out of you."

djbailey@skyler.mavd.honeywell.com (02/28/91)

In article <34523@athertn.Atherton.COM>, mcgregor@hemlock.Atherton.COM (Scott McGregor) writes:
> I am afraid I am belaboring this point, but it is an important one. 
> In the end, business decisions can only be effectively grounded on
> how the people who implement them actually act, and not merely how they
> OUGHT to act. Humans are wonderous and yet imperfect creatures.  Theories

When I first thought about the sine routine example I described, I came
to two conclusions. The first conclusion, which has been adequately 
defended by others, is that reusable components have to be tested in 
the context of the new application. There's no other way to be sure 
you've picked the right component.

My second conclusion is that specifying or describing reusable 
components is much harder than it seems. We can't reasonably expect 
the component designer to know every possible application for the 
component.

Every time one considers reusing a component, there is a make/buy 
decision.  When the effort required to make the decision is close to 
the effort to make the component, reuse will not happen. This puts 
some very practical limits on how detailed your specification can be.

I don't know if delivering source code is necessary but it is 
necessary to describe the algorithms and processing in detail. It 
would also be very useful to provide a test suite to help the user 
evaluate the software. The test suite would help the user determine if 
some additional special tests are needed.

-- Don J. Bailey