Path: utzoo!attcan!uunet!tut.cis.ohio-state.edu!pt.cs.cmu.edu!sei!ajpo!eberard
From: eberard@ajpo.sei.cmu.edu (Edward Berard)
Newsgroups: comp.lang.smalltalk
Subject: Re: Teaching object oriented programming
Summary: More Observations on OODIL and Reuse
Message-ID: <552@ajpo.sei.cmu.edu>
Date: 12 Aug 89 18:39:24 GMT
References: <1318@massormetrix.ida.liu.se> <80500067@p.cs.uiuc.edu>
Lines: 300

In article <80500067@p.cs.uiuc.edu>, johnson@p.cs.uiuc.edu writes:
> The point
> I was trying to make is that OO provides solutions to the problems
> of DIL, it does not introduce any.  (Other than the problem of learning
> to use the solutions.)

Perhaps Ralph and I can agree on the following points:

	- Software engineering in-the-large (e.g., software
	  engineering efforts which require two, or more, interacting
	  people, usually involve six, or more, months of calendar
	  time, and involve software products which are at least
	  16K lines of code) presents a different, and more difficult,
	  set of problems, than does software engineering
	  in-the-small.

	  See, for example, F. DeRemer and H.H. Kron's landmark 1976
	  article, "Programming-In-the-Large Versus
	  Programming-In-the-Small," (IEEE Trans. On Software
	  Enginering, June 1976), or Barry Boehm's book: Software
	  Engineering Economics (Prentice Hall, 1981), or Capers
	  Jones's IEEE tutorials on Programmer Productivity.

	  Software engineering research tells us that as the size of
	  the effort goes up:

		- software engineering productivity (using any
		  metrics) goes down

		- the "error density" (i.e., the number of errors per
		  unit of output) also increases

		- new activities begin to appear, e.g., configuration
		  management might be considered overkill for a 500
		  line-of-code program, but is an absolute necessity
		  for projects of the size of 16K lines of code, or
		  larger

		- the size of the largest units of software increases

		- the need for rigor in the actual engineering process
		  becomes mandatory

	- As one might suspect, object-oriented software engineering
	  in-the-large is different from object-oriented software
	  engineering in-the-small. Since object-oriented software
	  engineering in-the-large is still a _human_ activity, we
	  would still notice all of the above problems. However, if
	  done well, an object-oriented approach should mitigate these
	  problems to some degree.

	- What type of differences would we see in a large,
	  object-oriented software engineering effort, as opposed to a
	  small object-oriented software engineering effort?
	  Experience tells us to expect the following:

		- As both Ralph and myself have mentioned, there will
		  be a definite need to create (at least logically, if
		  not physically) and manage entities larger than a
		  single class.

		- There will be a significant increase in the number
		  of composite classes.

		- Functional decomposition approaches emphasize
		  decomposition, and small object-oriented approaches
		  have always emphasized composition (i.e.,
		  identification and creation of the components, then
		  assembling of the components into the application).
		  However, as the size of the overall product
		  increases, the necessity of using an approach which
		  includes _both_ composition and decomposition
		  increases. The (object-oriented) decomposition
		  techniques should help us to better manage
		  complexity.

		- The importance of stable, well-defined interfaces
		  increases dramatically. Even something as simple as
		  the change in the interface to a single class can
		  have a disastrous ripple effect on the entire
		  system.

> 
> A language for building large systems needs a mechanism for limiting
> the visibility of names.  There is nothing in Smalltalk to implement
> exporting and importing in the way Ed describes.  Some people think
> that classes provide sufficient modularity, but they are wrong.

I agree, and I would like to add that this problem is hardly unique to
Smalltalk.

> 
> The goal of object-oriented design is a large library of reusable
> components that can be used to quickly build applications.

While reusability is an important goal of an object-oriented approach,
it is not the only important goal. The following are also goals:

	- Increased ease of modification. If done correctly,
	  object-oriented approaches produce the software equivalent
	  of "pin compatible" and "plug compatible" hardware.
	  Specifically, it becomes relatively easy to remove one, or
	  more, components (objects) from a system and to substitute
	  new (different) ones, or to extend the existing system.

	- Facilitation of interoperability. Consider a computer
	  network containing potentially different computer systems at
	  each node. Instead of viewing each node as a monolithic
	  entity, each node should be viewed as a collection of
	  (hardware and software) resources. Interoperability is the
	  degree to which an application running on one node in the
	  network can take advantage of a (hardware or software)
	  resource on a different node in the same network. The
	  emphasis on polymorphism in an object-oriented approach,
	  helps to reduce the overall complexity of network software,
	  and thus facilitates interoperability. (Without a
	  polymorphic approach, for example, "name space" would
	  quickly become unmanageable, and the number and size of
	  composite operations would also undesirably increase.)

	- Easing of configuration management problems, per our earlier
	  discussions.

	- In addition, a report produced by Debbie Boehm-Davis and Lyle
	  Ross for General Electric indicated that, when compared to
	  solutions for the same problem using SASD and Jackson System
	  Development, object-oriented solutions appeared to be:

		- smaller (using lines of code as a metric)
		- simpler (using McCabe's and Halstead's metrics)
		- better suited for real-time systems
		- more quickly finished.

	  All of the above are also desirable goals.

> >> At the other end of
> >> the life-cycle, I find that code is not reusable until it has been
> >> reused, and this implies that you have to redesign software after it
> >> has been used in a couple of projects.
> 
> >If you study software reusability technology, you find that you do not
> >have to approach software reusability in a "trial and error" manner.
> >You really can design software so that it is reusable _without_
> >_modifications_ later. There are techniques, rule, methods, and
> >guidelines which can be used at all levels of abstraction to ensure
> >and enhance software reusability. (I incorporate many of these items
> >into the courses on object-oriented technologies that I teach.)
> 
> I strongly disagree with Ed on this point.  I have studied the literature
> on software reusability, and I don't think much of it.

I have to agree that there is a lot of "froth" in reusability
literature, and quite a few "content free" articles. However, if you
do quite a lot of reading, and attempt to apply what little good
technology there is, your efforts will be handsomely rewarded. 

[I am struck by a powerful analogy. Many of the people that I come into
contact with, have a great many misconceptions about what
"object-oriented" means, e.g., it's another name for a data-driven
approach. These people have an unrealistic "fantasy" about what
object-oriented means. This is made worse by the number of articles
which "document" these fantasies.

The same phenomenon occurs in the reuse arena. Many people have a
fantasy about what reuse should be, e.g., a library of reusable
functions. Some of these people even write articles about their
fantasies.]

I have been able to document and successfully apply techniques for
making classes resuable when they are first created. We can remove
about 80% to 90%, and, in some cases, all, of the guesswork.
Unfortunately this documentation currently exists chiefly in the form
of "class notes."

> We use good design techniques, and the more experienced people do a fairly
> good job of making reusable designs.  However, there are ALWAYS surprises.  
> It is not possible to predict all the ways that software will need to be 
> reused. However, experience shows that experience will show the range of 
> uses of software.  Thus, it is relatively straightforward to produce
> reusable software if you expect that it will be the RESULT of the project,
> not something that gets produced in the first phase.
> 

Here we are in general agreement. As I said earlier, it is not
possible to remove all the guesswork, all the time. But you have made
some observations which many others can also support:

	- It is much easier to create reusable software if that is
	  your main intention, as opposed to "reuse being a 'minor'
	  goal of a development effort." This finding not only has
	  been documented countless times, but is one of the primary
	  motivations for a branch of software engineering called
	  "domain analysis." Domain analysis is the study of an
	  application domain with the intent of discovering, and
	  creating, reusable components. (This has been a research
	  topic of mine, and, per usual, I have a lot to say on the
	  topic.) One of the landmark documents on domain analysis is
	  the 1980 doctoral thesis of Jim Neighbors, a graduate of UC
	  Irvine.

	- Reuse permeates everything. It impacts coding practices,
	  design and analysis approaches, testing, maintenance, and
	  software quality assurance, standards and practices,
	  database schema, CASE tool selection and usage, management
	  practices, and customer relations. Is it any wonder, with
	  the number of items which must be coordinated, why it is
	  difficult to produce reusable software?

	- Reuse must be a conscious effort. Too often you see courses
	  on the syntax and semantics of a programming language, and
	  _separate_ courses on software reusability. If you want
	  reuse to work, you have to incorporate it into everything you
	  do. 

Notice that reuse is the norm in the computer hardware industry.
Further, notice that the concept of reuse is incorporated into much of
the coursework, and day-to-day practices, of you typical EE.

> > It is not the purpose of OORA to identify _all_ of the code
> >  software objects and classes in the system. It is perfectly
> >  normal, healthy, and _expected_ to uncover additional
> >  objects and classes during an OOD process.
> 
> I distinguish between problem domain objects and solution domain
> objects.  The problem domain objects are the ones that are identified
> during the analysis and are the ones that the users think about.
> As Ed says, these often include parts of the environment that do not
> need to be represented as classes in the final solution.  The solution
> domain objects are the ones that turn up during design and implementation.
> Of course, sometimes you discover problem domain objects later than you
> would like, since the users often don't tell you everything you need
> to know.  That's life!

One of the things Larry Constantine wondered about, and which later
led him to be driving force behind structured design, was "could you
_systematically_ engineer good software the first time, and further
could you _know_ that you had engineered good software?". Someone
named Graham had observed:

	"We build system the way the Wright Brothers built airplanes.
	Build the whole thing, push it off a cliff, watch it crash,
	and start all over again."

Harlan Mills has stated:

	"Programs do not acquire bugs the way people do germs --
	simply by hanging around other buggy programs. ...

	Errors in logic and construction should be extremely rare,
	because we can prevent them through positive efforts on our
	own part."

Software engineers are often more fatalistic than they have to be. We
are the classic examples of self-fulfilling prophesies. You don't
expect it to compile clean the first time or run the first time? No
problem, you got it. 

Forgive me, Ralph. I am in no way implying that you advocate a
lackadaisical approach to software engineering. I just want others to
know that you are really saying, "do the best job you can, and
consciously strive to avoid the introduction of errors, but realize
that even the best laid plans ..." [I would cite the Scottish poet
Robert Burns, but software types are not supposed to be literate. ;-)] 

> The most important reason

[to reuse interfaces]

> is that it makes it possible to provide
> a set of components that you can connect together to build an application.
> For example, a user interface framework like InterViews lets you build
> an interface by connecting buttons, text viewers, scrollers, etc. together.
> Unless you need customized graphics there is unlikely to be any need to
> define any new components.  This is impossible unless you are able to
> connect any component to any other component, i.e. unless there are
> shared interfaces.  Moreover, this also requires a kind of polymorphism
> that cannot be simulated with generics.

[I don't want to be drawn into a discussion of the capabilities of the
often misunderstood language, Ada. However, ...] Let me just say that
my old company constructed just such a system (i.e., like InterViews)
in Ada. This system _did_ allow you to connect any component to any
other component. (Although, in truth, certain limitations on this
capability were designed in, to enforce some prestated rules about
which combinations of objects made sense, and which combinations
didn't.) 

Polymorphism in Ada involves more than just using generics, e.g., it
requires a heavy dose of limited private types. The overall thinking
is the same, but the implementation is different.

Please. If Ralph, or anyone else, wants to engage in a discussion of
object-oriented concepts in Ada, either contact me direct via e-mail,
or move the discussion to comp.lang.ada. After all, this is
comp.lang.smalltalk. 

As usual, my message runneth over. Thanks.

				-- Ed Berard
				   (301) 353-9652