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