comp.lang.ada
 help / color / mirror / Atom feed
From: jgv@swl.msd.ray.com (John Volan)
Subject: Subject/Object Confusion Syndrome [was: Ada Objects Help]
Date: Mon, 30 Jan 1995 22:50:31 GMT
Date: 1995-01-30T22:50:31+00:00	[thread overview]
Message-ID: <D38q48.3yM@swlvx2.msd.ray.com> (raw)
In-Reply-To: milodD34xtK.9u1@netcom.com

milod@netcom.com (John DiCamillo) writes:

>ka@socrates.hr.att.com (Kenneth Almquist) writes:
>>swdecato@cs.nps.navy.mil wrote:
>>> Many Ada folks have demonstrated how Ada objects are created and deleted.
>>> My argument against the Ada style was that I felt that the C++ syntax more
>>> accurately modelled the englist language.
>>
>>I don't know about you, but when I issue a command in English I place the
>>verb before the noun, as in "Mow the lawn."  This translates naturally to
>>the C or Ada code:
>>
>>	mow(lawn);
>>
>>The C++ alternative,
>>
>>	lawn->mow();
>>
>>is backwards.
>
>Actually, your example is backwards.  An imperative in English has
>an implicit subject (usually 'you', that is, the person being commanded)
>and an explicit object (in this case, 'lawn').  So the Ada code would
>be:
>
>  mow(robot, lawn);
>
>and the C++ would be:
>
>  robot.mow(lawn);
>

Actually, in the first C++ example, I'd say that the lawn is the
*subject* of the command, not the *object*!  The trouble here is that,
although C++ is deemed to be "object-oriented" -- it implements inheritance,
polymorphism, dynamic binding, etc. -- nevertheless, its method-calling
syntax is really *subject* oriented!  Let me explain:

If you want to interpret a C++ member-function call such as

	lawn->mow();

as an English imperative sentence, you really have to translate it as:

	"Hey, Mr. Lawn! Go mow yourself! (Uh, no offense. :-)
	(Oh, by the way, mow yourself in whatever fashion is
	appropriate for whatever type of lawn you are.)"

As whimsical and anthropomorphic as this sounds, I seriously believe
that this represents the kind of mindset you need to adopt in order to
program effectively in any language that uses this kind of syntax --
e.g., C++, Smalltalk, Eiffel, etc.  The fact that this sort of thing
sounds so whimsical and counter-intuitive is, in my view, a serious
problem, something which I call "Subject/Object Confusion Syndrome."
The ironic thing is that this confusion only arises because of a
choice of *programming language* syntax, yet, in my experience, it's
resulted no end of difficulties for engineers trying to grasp the
concepts of object-oriented *design*.

Every computer program has responsibilities to perform certain actions
and computations with respect to the "objects" in its problem domain.
A good object-oriented design will take all the responsibilities that
pertain to a given class of real-world objects and encapsulate them
into a single, cohesive software module.  But in order to render that
into a programming language that uses this "subject-oriented" syntax,
you have to imagine that the objects *themselves* are responsible for
the actions that the computer has to "do" to them.  Now, we all know
that it's really the *computer* that's going to "do" these things --
in other words, the computer is really the "subject" of our program's
imperative commands.  However, because of the syntax involved, you
have to pretend that it's actually the "objects" that are the
"subjects" of these commands.

In the example above, we know that we're really telling the computer
to invoke the "mow" function, and the "lawn" object is really an
implied parameter to this function (passed in through the so-called
"this" pointer).  This parameter has some special semantics -- its
run-time type information is used to dynamically dispatch to the
appropriate implementation of "mow" -- but it's still just a
parameter.  However, because of the syntax of the call, we're left
with the impression that it's the lawn that is the subject that is
doing the mowing.

In my experience, this confusion between "subject" and "object" is the
single most difficult conceptual hurdle you have to overcome in order
to master the object-oriented paradigm, whenever you work in languages
like C++ or Smalltalk.  Because of this confusion, it can be difficult
at times to decide where a certain responsibility should go.  For instance,
in deciding which object should have the responsibility to "mow", you 
have to keep remind yourself that the "lawn" object is not really the
"lawn" itself.  It's just the "part-of-the-computer-responsible-for-doing-
things-to-the-lawn" -- including, perhaps, mowing it.  

However, it is very easy to fall into the trap of inventing spurious
"functional" objects, whose only role is to "do" things to your
objects of interest.  For instance, it may seem perfectly reasonable
to argue that lawns don't mow themselves in the real world.  Don't you
need someone or something to actually do the job?   Like, maybe, 
some kind of "robot" object:

>  robot.mow(lawn);

This may sound okay at first: A "robot" object is chunk of software
that knows how to mow a lawn.  When we want a lawn mowed, we'll just
tell a "robot" object to do it.  But in reality this design is
horrible!  The premise was that there are different kinds of lawn that
have to be mowed in different ways.  Does this "robot" object now have
to know about all these different lawn types?  Does it have to do some
kind of switch-statement to discriminate among them?  Or do we now
need to have different classes of robot, one for each type of lawn?
If so, then what's the point of having different lawn classes anyway?
They seem to be just passive data now.  The object-oriented goal of 
encapsulating data and processing together seems to have been lost.

The answer, of course, is that this this "robot" idea just doesn't
work.  The "lawn" object itself is *already* the "thing-that-knows-
how-to-mow-a-lawn."

Contrast this with languages like CLOS or Ada95.  They also implement
inheritance, polymorphism, and dynamic binding, so they are also
deemed "object-oriented."  However, there was no attempt to adopt a
"subject-oriented" method-invoking syntax.  Instead, these languages
took the old, tried-and-true, imperative subprogram-invoking syntax,
and added whatever semantic enhancements were needed in order to
support polymorphic dynamic dispatching.  Consider the Ada95 example:

	Mow (The_Lawn);

Assuming that The_Lawn is a class-wide (polymorphic) tagged-type
variable, this could be translated into an English imperative sentence
as follows:

	"Computer! Go mow the lawn! (Shades of Star Trek? :-)
	(Oh, by the way, mow the lawn in whatever fashion is
	appropriate for whatever class of lawn it is.)"

Here, "the lawn" is the *object* of the sentence -- it is the thing to
which the action of the sentence is directed.  In the corresponding
Ada code, "The_Lawn" is the "object" to which the action of the "Mow"
procedure is directed.  The "subject" perfoming this action is, of
course, the computer itself, just as in every other imperative
programming statement.  In fact, you could view the exclamation 
"Computer!" as an implicit part of every single line of code.

The only difference between this subprogram call and an "ordinary"
subprogram call are semantic differences, not syntactic ones.
"The_Lawn" is a special, polymorphic, "controlling" parameter. It has
a run-time tag that will be used to dynamically dispatch to the
appropriate implementation of Mow.

IMHO, using this traditional imperative syntax is much easier to grasp
than "subject-oriented" syntax.  When used for dynamic dispatching, it
achieves exactly the same semantics as C++'s member-function call.  Yet 
it's much clearer what's "really" going on.  There's no phantom "this"
parameter that you have to know about in order to explain things.

There's still the issue of object-oriented encapsulation:  How do we
convey the fact that the "Mow" procedure is just an integral part of a single
cohesive idea known as the "Lawn" class?  C++ makes it a "member function" of a
class type, with the confusing effect of making it look like a structural
component of every single instance object of that class.  Ada95 uses packaging
to do encapsulation:  We can devote a package to describe the "Lawn" class,
encapsulating within it everything that pertains to lawns, including
an object-oriented (tagged) type and its primitive operations:

	package Lawn is
	  type Object is tagged private;
	  procedure Mow (The_Lawn : in out Lawn.Object);
	  ... other primitive operations ("member functions" in C++)
	private
	  type Object is tagged
	    record
	      ... -- lawn components ("member data" in C++)
	    end record;
	end Lawn;

So, in actuality, a call to the Mow procedure needs to include the package name
as context:

	Lawn.Mow (The_Lawn);  -- assuming The_Lawn is of type Lawn.Object'Class

It's clear that this "Mow" procedure is a modular part of package
Lawn, which encapsulates the *class* of Lawns. "Mow" is *not* a
structural part of The_Lawn *object* that is being passed into it.

Don't confuse this dotted notation with C++'s dotted member notation.
"Lawn.Mow" doesn't mean that "Lawn" is some kind of subject for the
verb "Mow".  The "subject" of the command is still the computer.  If
anything, "Lawn" here could be interpreted as an *adverb* qualifying
the verb "Mow".  All it's indicating is the *scope* in which the Mow
procedure is defined. The closest equivalent to this in C++ is using a
*scope operator*:

	lawn->Lawn::mow();

assuming:

	class Lawn {
	public:
	  void mow ();
	  ... other members
	};

	Lawn lawn;


>>Not to make too big a deal about this--either order (noun before verb or
>>verb before noun) is readable once you get used to it.  I doubt that one
>>order is inherently "better" than the other. 
>
>Agreed.
>
>>However, using both orders
>>in the same program seems like a bad idea if you are concerned about
>>readability.
>
>Oh, no.  Here I must disagree.  The two syntaxes (in C++) represent
>operations with different properties, so having a single syntax is
>potentially confusing.  Note:  I don't believe that the amount of
>confusion in either case is significant, but I am satisfied with the
>C++ (and Eiffel, and Smalltalk, and...) syntax.


I agree that, looking at things mechanically, syntax doesn't really
matter much, because the semantics wind up being the same anyway.  But
I'd say that choice of syntax in a language can have a tremendous
impact on how readily software engineers can internalize good
object-oriented design techniques, without getting confused and
falling into semantic traps.  Sure, if you're a "guru," you can get
used to whimsical things like lawns mowing themselves, or employees
paying themselves their salaries, or enemy missiles engaging and
destroying themselves.  But should every object-oriented software
engineer have to be a "guru" in order to be an effective designer?

Well, that's just some food for thought, I don't really want to start
a language war over this.  Don't mow me down! :-)

				-- John Volan

--------------------------------------------------------------------------------
 Me : Person :=
   (Name => "John G. Volan",  E_Mail_Address => "jgv@swl.msd.ray.com",
    Employer => "Raytheon",   Affiliation => "Enthusiastic member of Team-Ada!",
    Shameless_Controversial_Marketing_Slogan_For_Favorite_Language =>
      "<<<< Ada95: The World's *FIRST* Internationally-Standardized OOPL >>>>" &
      "Inheritance, hierarchical name-space, generic templates, type-safety, " &
      "readability, C/C++/COBOL/FORTRAN interoperability, numeric precision, " &
      "multi-threading, distributed systems, real-time, safety-critical ...  " &
      "<< A d a 9 5  :  Y o u   n a m e   i t ,  i t ' s   i n   t h e r e >>",
    Humorous_Language_Lawyerly_Disclaimer =>
      "These opinions are undefined by my employer, so using them would be "  &
      "totally erroneous ... or would that be a bounded error? :-) ");
--------------------------------------------------------------------------------





  parent reply	other threads:[~1995-01-30 22:50 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <3f9g1u$j4m@nps.navy.mil>
     [not found] ` <D2H5un.FEr@nntpa.cb.att.com>
     [not found]   ` <3fcs59$70s@nps.navy.mil>
     [not found]     ` <3ff186$c19@gnat.cs.nyu.edu>
1995-01-17 17:57       ` ADA Objects Help! Mats Weber
1995-01-18 17:47         ` Robert Dewar
1995-01-20 16:04           ` Mats Weber
1995-01-21 18:59             ` Robert Dewar
1995-01-23 12:03               ` Robb Nebbe
1995-01-25 20:44                 ` Mats Weber
1995-01-25 20:44               ` Mats Weber
1995-01-27  4:03                 ` Robert Dewar
1995-01-26  3:36           ` swdecato
     [not found]         ` <3fhggr$11dp@watnews1.watson.ibm.com>
     [not found]           ` <Mats.Weber-1901951739360001@mlma11.matrix.ch>
1995-01-20 17:22             ` Norman H. Cohen
1995-01-23 16:37               ` Mats Weber
1995-01-25 20:44               ` Mats Weber
1995-01-27  4:05                 ` Robert Dewar
1995-01-19 11:57   ` Robert M. Wilkinson
1995-01-22 18:06     ` Robert Dewar
1995-01-24 22:18       ` Norman H. Cohen
1995-01-25  1:26         ` swdecato
1995-01-25 18:18           ` Bob Kitzberger
1995-01-25 20:11             ` Bob Kitzberger
1995-01-26 15:31           ` Norman H. Cohen
     [not found]           ` <D330pK.M1@nntpa.cb.att.com>
1995-01-28 21:46             ` John DiCamillo
1995-01-30 14:13               ` David Emery
1995-01-30 22:50               ` John Volan [this message]
1995-02-01 14:33                 ` Subject/Object Confusion Syndrome [was: Ada Objects Help] Norman H. Cohen
     [not found]                   ` <D3DpJu.4nK@swlvx2.msd.ray.com>
     [not found]                     ` <D3H7J3.B2x@inmet.camb.inmet.com>
1995-02-06 10:32                       ` Robb Nebbe
     [not found]                     ` <3gu21g$ch@portal.gmu.edu>
1995-02-06 14:01                       ` John Volan
1995-02-01 22:37                 ` Maarten Landzaat
     [not found]                   ` <3h1ahp$gf5@gnat.cs.nyu.edu>
     [not found]                     ` <3h3jmp$1h1@Starbase.NeoSoft.COM>
1995-02-07 14:39                       ` John Volan
1995-02-09  2:25                         ` David Weller
1995-01-29 18:19             ` ADA Objects Help! mat
     [not found]               ` <1995Feb5.180601@hobbit>
1995-02-07 23:04                 ` Subject/Object Confusion Syndrome [was: Ada Objects Help] John Volan
1995-01-25  9:48       ` ADA Objects Help! mat
1995-01-23 10:01     ` calling syntax (was Re: Ada Objects) Robb Nebbe
1995-01-23 18:08       ` John DiCamillo
1995-01-23 23:47     ` ADA Objects Help! Ed Osinski
1995-01-25  6:19       ` David O'Brien
     [not found] ` <1995Jan16.132400@lglsun.epfl.ch>
     [not found]   ` <131279@cup.portal.com>
1995-01-20 16:52     ` Ada " Robert Dewar
1995-01-22 18:30       ` Tucker Taft
1995-01-24 22:09         ` Jacob Sparre Andersen
1995-01-26 16:20           ` Robert A Duff
1995-01-27 17:04             ` Robert A Duff
1995-01-27 19:58             ` Tucker Taft
1995-01-20 17:41   ` Mark S. Hathaway
1995-01-23 10:41     ` Robb Nebbe
1995-01-23 11:53     ` Stephane Barbey
     [not found] <3gtai2$3mq@horus.mch.sni.de>
     [not found] ` <3gudf1$ia1@network.ucsd.edu>
     [not found]   ` <132301@cup.portal.com>
1995-02-06 15:37     ` Subject/Object Confusion Syndrome [was: Ada Objects Help] Fergus Henderson
1995-02-07 14:43       ` John Volan
1995-02-09 20:58     ` Mike Bates
     [not found]     ` <9503802.3538@mulga.cs.mu.oz.au>
1995-02-10 15:19       ` Jules
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox