[comp.lang.c++] Critique of Wiener/Pinson

dan@Apple.COM (Dan Allen) (04/13/88)

A brief critique of:

        "An Introduction to Object-Oriented Programming and C++"
        (Richard S. Wiener & Lewis J. Pinson.  Addison-Wesley.
        ISBN 0-201-15413-7.)

follows.

Wiener & Pinson is definitely a needed book, as Stroustrup's book is
somewhat hard to read, a fact admitted by many on the network.  However,
Wiener & Pinson (W&P) has a few flaws itself...

My main concerns are with some of the definitions of object-oriented
programming.  At the last main conference on object-oriented
programming, OOPSLA '87, Peter Wegner's paper entitled "Dimensions of
Object-Based Language Design" gave the following definition of what it
means for a language to be object-oriented:

  object oriented = objects + classes + inheritance

Further definitions of these terms define objects to be instances of a
class, and classes to be an organizational tool that allows inherited
qualities to be passed to subclasses, etc.

Now for the problems.  Wegner goes on to define data-abstraction as an
ORTHOGONAL attribute to object-orientedness, for the following
reason(s):  data abstraction and the notion of abstract data types
provide for the description of a data structure and some associated
function and procedures that have sole access to the data structure.
Wegner's point is that object-oriented languages allow access to the
underlying data structures BY DIRECT REFERENCE rather than only through
the (to use OO language) associated methods of the class.  OO languages
can also use functions and procedures to access the data structure as
well.

Well, W&P do not make this distinction.  Pages 1,2, and 57-58
particulary are full of definitions that are not in keeping with the
main body of OO language designers.

Now, what is C++ then?  Well, C++ is interesting in that its classes
are, by default, supportive of abstract data types and the data
abstraction paradigm by making fields of a class private.  (Remember,
private data = Data Abstraction.)

C++ also supports object-oriented programming by allowing fields to be
declared public.  (Public data = Object-Oriented if inheritance is also
supported, which it is in C++).

Now there is a definitional problem at hand: what if some fields are
public and some fields are private?  C++ has created a new definitional
problem.

I must point out that W&P is fairly consistent internally with the
definitions that are used.  My gripe is that they are using the same
terms as the mainline Object-Oriented world, but with new and changed
definitions.

A few more guidelines with the definitions that I subscribe to:

**	Ada is NOT object-oriented.  Ada does support data abstraction.

**	Object Pascal IS object-oriented, but does NOT support data ab.

**	Modula-2 is NOT object-oriented.  It does support ADTs.

**	C++ supports both object-oriented programming & ADTs, though not
	at the same time.  (Stroustrup's definitions are more in line,
	by the way, with mine and Wegner's than with W&P.)

Sorry for the long flame about definitional problems, but I have been
working with object-oriented languages for several years here at Apple
and have found them a little hard to teach to people because of problems
such as these.

When Stroustrup came to Apple recently, he spoke about such matters and
he seems to have a good understanding of these issues.  His talk also
was much more understandable than his book, so if you ever get the
chance to hear him, make sure to take advantage of it.  You'll enjoy it.
I did.

Dan Allen
Software Explorer
Apple Computer

johnson@uiucdcsp.cs.uiuc.edu (04/13/88)

I think it is unfair to criticise Wiener and Pinson because they didn't
follow Wegman's terminology.  First, they wrote their book before he
wrote his paper.  Second, Wegman's classification is not at ALL considered
standard.  It may become standard, but it isn't yet.

I disagree 100% with the notion that object-oriented programming and
data-abstraction are orthogonal.  Actually, object-oriented programming
is data-abstraction carried to extremes.  Data-abstraction means that
the programmer does not know how the "object" is implemented.  O-o
programming means that even the compiler does not know how the object is
implemented!  In other words, when the compiler "sends a message" (calls
a virtual function) it doesn't know exactly which procedure is being
called, but must depend on some kind of run-time binding.

While I agree that inheritance is important, I think that message
sending is more important.  Thus, Emerald is object-oriented even
though it doesn't have inheritance.  Message sending can be used to
fake inheritance with delegation.  Of course, I prefer inheritance.
Object-oriented languages most definitely do not have to allow direct
access to their structure.  In fact, I think that they should not.
Smalltalk does not allow direct access to the instance variables of
objects, except through instVar:at:, which is a kludge used for debugging.
We never make C++ member variables public, but instead access them
through member functions declared to be in-line.  This means that we can
easily reimplement the data structures in the class.

So, I am disagreeing with the notion that the object-oriented world thinks
that you should be able to directly access the fields of an object.  Maybe
your part of the world does, but mine does not, and mine is pretty big, too!

I certainly agree that Ada and Modula-2 are not object-oriented but do
support ADTs.  The reason that they are not object-oriented is primarily
because they do not support message passing (the Ada rendezvous doesn't
count) and secondarily because they do not support inheritance.

I am primarily a Smalltalk programmer, and am involved with several large
Smalltalk projects, but I am also involved with the CHOICES operating
system here at Illinois, which is an object-oriented o.s. written in C++.
I use both languages in teaching.  I probably think more like a Smalltalk
programmer than like a C++ programmer, so that might explain my point of view.

Ralph Johnson

dan@Apple.COM (Dan Allen) (04/15/88)

I am glad that we agree that Ada (and Modula-2) are not object-oriented.
I suppose that this was a major thrust of my flame about the book,
mainly because more and more people are both using Ada and are hearing
the object-oriented buzzwords, and then think that they are programming
in an object-oriented manner.

I personally do NOT entirely agree with Wegner, but I DO think that it
would be nice if we all shared a few common definitions of these terms,
so that the incoming masses to object-oriented programming will get a
clearer understanding of what the heck it all means...

Which is what I am STILL trying to do myself...  Thanks for your
comments.

Dan Allen
Apple Computer

jima@hplsla.HP.COM ( Jim Adcock) (04/16/88)

I don't buy the idea that instance variables of an object must always
be accessed via an access method.  I think there are good cases for
violating this "rule".

The simplest case that comes to mind is the overused example of complex
numbers.  To suggest that:

x = myComplexNumber.re();
y = myComplexNumber.im();

is in any way better than:

x = myComplexNumber.re;
y = myComplexNumber.im;

seems ludicrous to me.  In fact, I believe that in many situations similar to
the complex number example, allowing direct access is preferrable to forcing
the class's user to always tag on the "meaningless" () parenthesis.

In any case, I believe the important operative rule that's in effect here
is that the class definer define the public portion of the interface
to his/her class in a way that is not going to change in future revisions
of the class.

If you, the designer, are willing to "guarantee" that those portions of 
your object that you allow access to directly are not going to change in
future revisons of your class, then I say, "no problem, give the class
user direct access."

If you don't feel you can make such a guarantee, then please make sure to
supply access functions instead of allowing direct access to those
instance variables that may be changed in future revisions.

[If in doubt, use access functions]

johnson@uiucdcsp.cs.uiuc.edu (04/16/88)

Simon Kaplan, who has an office two doors down from mine, has a sign
on his door that reads

	Ada is good.
	Object oriented is good.

	Therefore, Ada is object oriented.


I think that is the best argument for why Ada is object-oriented!

shopiro@alice.UUCP (04/17/88)

In article <6590037@hplsla.HP.COM>, jima@hplsla.UUCP writes:
> I don't buy the idea that instance variables of an object must always
> be accessed via an access method.
> To suggest that:
> 
> 	x = myComplexNumber.re();
> 	y = myComplexNumber.im();
> 
> is in any way better than:
> 
> 	x = myComplexNumber.re;
> 	y = myComplexNumber.im;
> 
> seems ludicrous to me.

Here are two reasons you might prefer access functions.

1) Access functions allow you to change the internal representation.
You might someday want to represent complex numbers in polar
coordinates.  Admittedly, rectangular coordinates are usually
preferred, but there undoubtedly are applications in which polar
coordinates would be better.  Use access functions and all your code
will continue to run.

2) Access functions support read-only access to instance variables.
You might someday want a redundant represention of complex numbers
using both rectangular and polar coordinates.  You then need to
preserve the consistency of the two parts of the representation.  If
you allowed the user direct access to the instance variables, that
consistency could be destroyed by any code that accessed a complex
number.  If you use access functions, you only have to worry about
member functions.

I should also mention that there is no performance penalty for access
functions.  If they are expanded inline the generated code is exactly
the same as reading a public instance variable.

On the other hand C++ does allow public instance variables, so you can
make your own decision.

> In fact, I believe that in many situations similar to
> the complex number example, allowing direct access is preferrable to forcing
> the class's user to always tag on the "meaningless" () parenthesis.

I will agree that the required () for access functions may seem annoying,
but if you agree with me that all syntax is painful, then I hope you'll
also agree that this is only a minor turn of the screw.  (:-)
-- 
		Jonathan Shopiro
		AT&T Bell Laboratories, Murray Hill, NJ  07974
		research!shopiro   (201) 582-4179

ark@alice.UUCP (04/17/88)

In article <6590037@hplsla.HP.COM>, jima@hplsla.UUCP writes:

> To suggest that:
 
> x = myComplexNumber.re();
> y = myComplexNumber.im();
 
> is in any way better than:
 
> x = myComplexNumber.re;
> y = myComplexNumber.im;
 
> seems ludicrous to me.

Not at all.  If you allow MyComplexNumber.re without parentheses,
you're stuck if you ever decide to start using polar coordinates.

jima@hplsla.HP.COM ( Jim Adcock) (04/20/88)

|1) Access functions allow you to change the internal representation.
|You might someday want to represent complex numbers in polar
|coordinates.  Admittedly, rectangular coordinates are usually
|preferred, but there undoubtedly are applications in which polar
|coordinates would be better.  Use access functions and all your code
|will continue to run.

If you refuse to stick to your original definition of blah,
and you make blah public, and someone uses blah, and then you change
your definition of what blah means, then that user of your class is
going to be hosed.

BUT this is true whether or not blah is an access function or a public
instance variable.  If you change your definition of what a public
anything means, you will hose your users.

So the penalty for using access functions "everywhere" comes down to:

1) "Needlessly" writing access methods to instance variables that 
   you, the class writer, are committed to never changing.

2) The class user gets more exposure to the use of the "noise characters"
   ()  And like other cases of "noise characters" in computer languages
   this is stuff that is easy to forget, since its meaningless.  
   Meaning more failed compiles.  And a few more characters to type.

3) The obscuring of an important, practical engineering issue -- namely
   that if a class designer changes the meaning of ANY PART of his/her
   public interface, in general that class's users are going to be hosed --
   by the use of a blanket "religious" statement: "Use access functions 
   everywhere and you can change your class without your users."

Again, not true -- the issue is public vs non-public, it is not an issue
of access functions or not access functions.  Change the meaning of 
any part of your public interface, either instance variable or function, 
and your class's users will be hosed.

shopiro@alice.UUCP (04/22/88)

In article <6590039@hplsla.HP.COM>, jima@hplsla.UUCP writes:
> If you refuse to stick to your original definition of blah,
> and you make blah public, and someone uses blah, and then you change
> your definition of what blah means, then that user of your class is
> going to be hosed.
> 
> BUT this is true whether or not blah is an access function or a public
> instance variable.  If you change your definition of what a public
> anything means, you will hose your users.

(This should be obvious, but ... )

Suppose you have

	class Complex {
		double	re, im;
	public:
		double real() { return re; }
		// ...
	};

and you decide you want to switch to polar coordinates.  Then you
can write

	class Complex {
		double	rho, theta;
	public:
		double real() { return <trig expression>; }
		// ...
	};

and users will not be affected.

> ...  Change the meaning of 
> any part of your public interface, either instance variable or function, 
> and your class's users will be hosed.

But use access functions so you can change the internal structure of your
class without changing the meaning of its public interface.
-- 
		Jonathan Shopiro
		AT&T Bell Laboratories, Murray Hill, NJ  07974
		research!shopiro   (201) 582-4179

chip@ateng.UUCP (Chip Salzenberg) (04/22/88)

In article <6590037@hplsla.HP.COM> jima@hplsla.HP.COM (Jim Adcock) writes:
>I don't buy the idea that instance variables of an object must always
>be accessed via an access method.  I think there are good cases for
>violating this "rule".

Sometimes.  Maybe.  But when it's debugging time, It's _so_ easy to insert:

	cerr << "I'm being changed!\n";

into the modification function.

>[If in doubt, use access functions]

Amen.
-- 
Chip Salzenberg                "chip@ateng.UU.NET" or "codas!ateng!chip"
A T Engineering                My employer may or may not agree with me.
  "I must create a system or be enslaved by another man's." -- Blake