comp.lang.ada
 help / color / mirror / Atom feed
From: Tucker Taft <stt@averstar.com>
Subject: Re: Help me to chose between ADA 95 and C++
Date: 1999/12/14
Date: 1999-12-14T00:00:00+00:00	[thread overview]
Message-ID: <38567806.FD1F4232@averstar.com> (raw)
In-Reply-To: 38561A6C.5DE3D901@rdel.co.uk

Chris Powell wrote:
> 
> Matthew Heaney wrote:
> >
> > In article <385112AE.7E2CFA9@rdel.co.uk> , Chris Powell
> > <chris.powell@rrds.co.uk>  wrote:
> >
> > > I would not recommend Ada 95 for OO development. Okay, it has all the
> > > benefits of Ada 83 for type safety, etc, but the syntax of its class
> > > programming constructs seems to make the code long winded, obscure and
> > > error prone.  I can give examples if anyone is interested/disagrees.
> >
> > Please do so, especially any examples that you think are "error prone."
> >
> > Perhaps there is just a misunderstanding about how to properly declare a
> > type.
> 
> Okay, this is where I find out that I have been getting it wrong for the
> last year! But here goes:

Thanks for taking the time to post these examples.  I will give some
of the rationale for the choices made...

> package body Example is
> 
>    procedure Dispatching_Method (This : access Object) is
>    begin
>       -- This call correctly redispatches to Another_Dispatching_Method
>       Another_Dispatching_Method (This => Object'Class
> (This.all)'Access);
> 
>       -- This (probably incorrectly) calls this object's
>       -- Another_dispatching_Method directly, without dispatching
>       Another_Dispatching_Method (This => This);

This choice of "static" over "dynamic" binding was very explicit
in the language design.  By making static binding the default,
you minimize unexpected coupling between a parent type and a derived
type.  I'll say more below...

>    end Dispatching_Method;
> 
>    procedure Class_Method (This : access Object'Class) is
>    begin
> 
>       -- This call correctly dispatches, since this is already
>       -- classwide in this case
>       Another_Dispatching_Method (This => This);
> 
>    end Class_Method;
> 
>    procedure Another_Dispatching_Method (This : access Object) is
>    begin
>       null;
>    end Another_Dispatching_Method;
> 
> end Example;
> 
> It has proven to be a common mistake to neglect to convert an object to
> its class wide type before attempting a redispatch.

I would have said that a common mistake in most OO languages
is to use dynamic binding between dispatching methods
when static binding would have been better.

This will not happen in Ada 95 because static binding between
dispatching methods is the default, and you have to work a little
harder and be explicit if you want redispatching.

 
> Passing 'This' as an access parameter is common (since references to
> objects are often stored by an object, but further complicates the
> syntax.
> 
> By contrast, C++ provides redispatching as the default behaviour which
> makes more sense to me. If a function is declared virtual (ie
> dispatches) you would normally want dispatching to occur and then have
> to use special syntax to prevent dispatching. In Ada, it is the other
> way round. 

Here we have a difference of opinion.  I agree when calling from the
"outside" use want dispatching to occur, and that is what happens in
Ada (and C++).  However, when calling from one dispatching operation
to another, static binding has a lot of advantages.  In particular,
if you inherit one operation and override the other, the one you
inherit continues to work as it used to, rather than having some
unspecified change in behavior due to redispatching.

The critical point to recognize is that any redispatching within
a dispatching operation affects the *external* behavior of the operation
upon inheritance.  So you can't inherit an operation as a black box
if it has internal redispatching.  You basically have to look at the
source of the inherited operation (i.e. this means "white box" reuse), 
or have unusually good documentation on exactly what redispatching
is happening inside and when.

I remember attending a panel session at OOPSLA several years ago where
essentially all of the panel members were griping about the difficulties
of doing maintenance and enhancement on class libraries when users are
taking advantage of this internal redispatching (also called "self
dependencies").  Users were overriding some but not all of the operations, 
and then relying on this overriding to subtly affect the semantics of the
inherited operations.  When the next version of the class library came out,
these users were very annoyed if the subtle effects were different.  

This problem would not occur in a language like Ada 95 where the default
binding between dispatching operations is static.  The developer of the class
library would only use redispatching if they felt it were part of the
*specification* of the operation, and hence would be intending to
document it.  By contrast, in C++, Java, Eiffel, Smalltalk, etc., 
redispatching is the default (and except for C++, static binding
is not even an option), so these kinds of self dependencies are produced
everywhere and anywhere there are calls between dispatching operations.
Quite often these were calls made out of convenience of implementation
of the operation, not out of an intent to create a subtle linkage
between the operations from an inheritance point of view.

So it is the collective experience of class providers like these that
reconfirmed (at least for me) our decision to make static binding the
default, while still providing a way for the programmer to redispatch
if that is what the specification of the routine requires.

> ...
> This is one example, perhaps a bit verbose. I can try and think of more
> if anyone is interested, or please set me straight!
> 
> Other Ada quibbles:
> 
> C++ encapsulates methods and data in a single structure. In Ada, class
> methods are defined outside the object type so do not appear to 'belong'
> to the type.

This is clearly a matter of taste and background.  The notion of
an abstract data type, like "complex numbers" and a set of operations
defined along side them has a long history.  Ada 83 was built around
this notion of abstract data type, where a type and its operations
were all defined in a package, where the package provided the
encapsulation.  Ada 95 was designed to allow the extension of abstract
data types, providing both inheritance between abstractions and/or
their implementations, and polymorphism between multiple implementations 
of an abstraction.  This preserves the heritage of "abstraction" orientation,
while providing the extensibility and dynamism associated with the
object-oriented model.  It also means that binary operations are very
natural in Ada 95, whereas they are awkward and somewhat arbitrarily
asymmetric in languages like C++ and Java (e.g. the nasty need to
write "if S1.equal(S2) {" in Java, rather than "if S1 = S2 then" in
Ada 95, or the awkward connection between operator "friends" in C++
and the "associated" class).

Admittedly, Ada 95 is a bit less natural in the heavily "state"-oriented
model, where all operations "do things" to an object, and is a bit more 
natural in a "value"-oriented/functional model where (abstract) operations 
take in one or more values of a given ADT and produce a result.
Personally the problem I have with the "state"-oriented model is
for various operations that have two or more objects involved,
and it is not at all obvious which one is the "primary" object.
With the symmetric Ada (and Common Lisp Object System/CLOS) approach, 
they are all operands of the operation, and no unique "primary" object
need be identified.

> Having to explicitly pass the object instance as a parameter (the
> implicit 'this' in C++) further separates the logical association
> between methods and objects.

Again, the C++ syntax is useful for clearly "one-primary-operand" operations,
and somewhat arbitrary for "two-or-more-significant-operand" operations.

> I am a Multiple Inheritance fan, because I think I know how to use it
> properly. I do not believe it (always) indicates a bad design, as some
> do. Ada 95 has some constructs to allow different types of MI, but not
> all provided by the more general approach of C++, and again, the syntax
> is obscure involving tagged types within generics, access discrimiated
> records, etc. In C++ you simply define an X as a Y and a Z. In Ada, the
> syntax would have been (if allowed):
> 
>    type Object is new X.Object and new Y.Object with record ....

We certainly debated multiple inheritance.  I think we were reluctant
to build in syntax for a feature that seemed in some cases a
solution looking for a problem.  Also the fact that the designers of
C++ couldn't decide  between "virtual" and "non-virtual" base classes,
and felt obliged to support both, and that many Eiffel uses of
multiple inheritance seemed to represent "uses" rather than "is-a"
relationships, made us feel that multiple inheritance was still in an awkward
stage of development.  

The one thing I would add now to Ada 95 would probably
be something more akin to the Java multiple inheritance of interfaces.
Inheriting implementations from multiple parents seems quite error prone,
but inheriting interfaces is pretty clean.  However, there is still
the annoying name clash possibility, where two interfaces happen to use
the same name for otherwise unrelated methods.  You also can't implement
an interface in multiple ways with a single type, which could be useful
for things like the "observer" pattern where a single object wants to
observe multiple other objects.  

For Ada 95, a solution built more around the notion of explicitly implementing
an interface, using something like the syntax of a generic instantiation, 
would give more flexibility and power (including multiple implementations
of the same interface), while avoiding the annoyances
associated with name clashes.  We have begun moves toward an Ada 200X, so some
ideas like these may emerge...
> 
> Comments?

See above.

> 
> Chris.

-- 
-Tucker Taft   stt@averstar.com   http://www.averstar.com/~stt/
Technical Director, Distributed IT Solutions  (www.averstar.com/tools)
AverStar (formerly Intermetrics, Inc.)   Burlington, MA  USA




  parent reply	other threads:[~1999-12-14  0:00 UTC|newest]

Thread overview: 67+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1999-11-26  0:00 Help me to chose between ADA 95 and C++ Robert
1999-11-26  0:00 ` Preben Randhol
1999-11-26  0:00   ` Preben Randhol
1999-11-26  0:00 ` Harald Schmidt
1999-11-26  0:00   ` Andreas Winckler
1999-11-26  0:00     ` Florian Weimer
1999-12-04  0:00   ` Richard D Riehle
     [not found]     ` <01bf3e32$0b9dc880$022a6282@dieppe>
1999-12-10  0:00       ` Chris Powell
1999-12-13  0:00         ` Marin D. Condic
1999-12-13  0:00         ` Richard D Riehle
1999-12-14  0:00           ` Chris Powell
1999-12-14  0:00             ` Simon Wright
1999-12-15  0:00               ` Chris Powell
1999-12-15  0:00                 ` Robert A Duff
1999-12-14  0:00             ` Larry Kilgallen
1999-12-15  0:00               ` Robert A Duff
2000-01-12  0:00                 ` Richard Pinkall-Pollei
1999-12-14  0:00             ` Ray Blaak
1999-12-14  0:00             ` Richard D Riehle
1999-12-14  0:00               ` Matthew Heaney
1999-12-15  0:00             ` Ted Dennison
1999-12-20  0:00               ` Stefan Skoglund
1999-12-16  0:00             ` Pascal Obry
1999-12-16  0:00               ` Rakesh Malhotra
1999-12-21  0:00                 ` Geoff Bull
1999-12-16  0:00               ` Aidan Skinner
1999-12-16  0:00               ` Lutz Donnerhacke
1999-12-21  0:00             ` Robert Dewar
1999-12-21  0:00               ` Chris Powell
1999-12-21  0:00               ` Ted Dennison
1999-12-21  0:00                 ` Robert Dewar
1999-12-13  0:00         ` Brian Rogoff
1999-12-14  0:00           ` Chris Powell
1999-12-14  0:00             ` Brian Rogoff
1999-12-14  0:00             ` Preben Randhol
1999-12-14  0:00               ` Stephen Leake
1999-12-14  0:00                 ` Tucker Taft
1999-12-15  0:00                   ` Stephen Leake
1999-12-15  0:00                 ` Preben Randhol
1999-12-15  0:00           ` Richard Pinkall-Pollei
1999-12-15  0:00             ` Richard Pinkall-Pollei
1999-12-21  0:00             ` Geoff Bull
1999-12-21  0:00               ` Tucker Taft
1999-12-22  0:00                 ` Ted Dennison
1999-12-13  0:00         ` DuckE
1999-12-14  0:00           ` Matthew Heaney
1999-12-14  0:00         ` Matthew Heaney
1999-12-14  0:00           ` Chris Powell
1999-12-14  0:00             ` Matthew Heaney
1999-12-15  0:00               ` Hyman Rosen
1999-12-14  0:00             ` Tucker Taft [this message]
1999-12-14  0:00               ` Matthew Heaney
1999-12-23  0:00               ` Chris Powell
1999-12-27  0:00                 ` Robert A Duff
1999-12-14  0:00             ` Stephen Leake
1999-12-23  0:00               ` Chris Powell
1999-11-26  0:00 ` Andreas Winckler
1999-11-27  0:00 ` Lionel Draghi
  -- strict thread matches above, loose matches on Subject: below --
1999-12-14  0:00 Robert C. Leif, Ph.D.
1999-12-15  0:00 ` Richard D Riehle
1999-12-15  0:00 Robert C. Leif, Ph.D.
1999-12-16  0:00 ` Richard D Riehle
1999-12-16  0:00   ` Matthew Heaney
1999-12-17  0:00     ` Richard D Riehle
1999-12-18  0:00       ` Matthew Heaney
1999-12-20  0:00         ` Richard D Riehle
1999-12-22  0:00 Help me to chose between ADA 95 and C++ ( Ehud Lamm
replies disabled

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