comp.lang.ada
 help / color / mirror / Atom feed
From: jgv@swl.msd.ray.com (John Volan)
Subject: Re: Mutual Recursion Challenge
Date: Mon, 24 Oct 1994 20:32:14 GMT
Date: 1994-10-24T20:32:14+00:00	[thread overview]
Message-ID: <1994Oct24.203214.4967@swlvx2.msd.ray.com> (raw)
In-Reply-To: EACHUS.94Oct24114925@spectre.mitre.org

eachus@spectre.mitre.org (Robert I. Eachus) writes:

>    There are many features in Ada 9X which lead to a better approach
>to OOP.  In particular, the mindset problem here is that the mutual
>recursion must be between peers.  Ada 9X does a nice job on recursion
>between objects at different levels of abstraction, and most of
>difficulty in the examples comes from constructing two types at the
>same level of abstraction and in different packages.

>    In my (so far limited, as is everyone's) experience in Ada 9X, you
>are much more likely to be adding an abstraction, using a generic
>mixins, when the need for recursion occurs.  In those cases, all the
>baggage discussed is either there for other reasons or not necessary.

Could you clarify this a bit, and elaborate on how using mixins would
work here?  I think I understand what you're driving at, but perhaps
other folks won't.  What, precisely, do you mean by the "baggage" that
would be there anyway?  Also, how well does the mixin technique really
scale up, when you imagine many classes, many associations, and each
class participating in many associations?

>It may seem that creating a dozen abstract types which are only there
>as placeholders is a problem, but in fact the only problem I have
>found with it is coming up with names.  (The best strategy I have
>found is to use the base class name joined with the generic package
>name as the name of the package instance:

>    package Persons_Office_Assignment is new Office_Assignment(Person);

>    and elsewhere:

>    package Office_Staff_Assignment is new Staff_Assignment(Office);

>    As this particular instantiation should make clear, package
>Staff_Assignment may also be used to add staff to projects, to
>departments, etc.

I take it that Persons_Office_Assignment would declare a derived type
inheriting from Person, with an extension supporting the association
with Office.  Likewise, Office_Staff_Assignment would declare a
derived type inheriting from Office, with an extension supporting the
association with Person.  One problem I see with this particular
formulation is that a Person-who-can-occupy-an-Office can point to any
Office, not necessarily only an Office-that-can-be-occupied; likewise,
an Office-that-can-be-occupied can point to any Person, not
necessarily only a Person-who-can-occupy-an-Office.  Is there a way
of putting this together that guarantees the invariant that if a
Person occupies an Office, then that Office is occupied by that
Person?

>And in fact it might be better to have the
>assignment package defined as a double generic as a much higher level
>and instanced down, or just as a generic with two type parameters as
>suggested earlier in this discussion.  (In such a model, Person and
>Office would be instances of Objects, and Assignment would create a
>relationship.)

Do you mean something like this?

    generic
      type Former_Base is tagged limited private;
      type Latter_Base is tagged limited private;
    package One_To_One_Association is

      type Former is new Former_Base with private;
      type Former_Pointer is access all Former'Class;

      type Latter is new Latter_Base with private;
      type Latter_Pointer is access all Latter'Class;

      ... -- Subprograms supporting association.  Some may be primitives for
          -- either Latter or Former type, but none may be primitive for both.

    private

      type Former is new Former_Base with
        record
          Its_Latter : Latter_Pointer;
        end record;

      type Latter is new Latter_Base with
        record
          Its_Former : Former_Pointer;
        end record;

   end One_To_One_Association;

There would be something similar for One_To_Many_Association and
Many_To_Many_Association.  Then we could instantiate it something
like this:

   package Person is
     type Object is tagged limited private;
     ... -- primitives for ordinary attributes not involving associations
   end Person;

   package Office is
     type Object is tagged limited private;
     ... -- primitives for ordinary attributes not involving associations
   end Office;

   package Building is
     type Object is tagged limited private;
     ... -- primitives for ordinary attributes not involving associations
   end Building;

   ... etc.

   with Person;
   with Office;
   with One_To_One_Association;
   package Person_Occupies_Office is new
     One_To_One_Association (Person.Object, Office.Object);

   with Person_Occupies_Office;
   with Building;
   package Building_Contains_Office is new
     One_To_Many_Association (Building.Object, Person_Occupies_Office.Latter);

   ... etc.

   with Building_Contains_Office;
   package Total_Office is
     type Object is new Building_Contains_Office.Latter with null record;
   end Total_Office;

   with Building_Contains_Office;
   package Total_Building is
     type Object is new Building_Contains_Office.Former with null record;
   end Total_Buidling;

   with Person_Occupies_Office;
   package Total_Person is
     type Object is new Person_Occupies_Office.Former;
   end Total_Person;

   ... etc.

Of course, the actual immediate parent type for each "Total" object
type would depend on the particular mix of classes and associations in
the specific application.  If the requirements of the problem changed
to add a new association to a class, we'd have to change where the
given "Total" type derived from.

And now for the "acid test":  Can this technique meet the "Challenge"
of getting a class into a mutually-recursive association with one of its
own subclasses?

    with Person_Occupies_Office;
    package Manager is
      type Object is new Person_Occupies_Office.Former with private;
      ... -- primitives for ordinary attributes not involving associations
    end Manager;

    with Person_Occupies_Office;
    with Manager;
    with One_To_Many_Association;
    package Manager_Supervises_Person is new
      One_To_Many_Association (Manager.Object, Person_Occupies_Office.Former);


    with Manager_Supervises_Person;
    package Total_Manager is
      type Object is new Manager_Supervises_Person.Former with null record;
    end Total_Manager;

    -- Oh, and now we have to change how we define Total_Person:

    with Manager_Supervises_Person;
    package Total_Person is
      type Object is new Manager_Supervises_Person.Latter with null record;
    end Total_Person;

But there's a problem here: Total_Manager.Object inherits from
Manager_Supervises_Person.Former, which inherits from Manager.Object,
which inherits from Person_Occupies_Office.Former.  But
Total_Manager.Object does not inherit from
Manager_Supervises_Person.Latter.  So a Total_Person can have a
supervising Manager, but a Total_Manager is not a Total_Person, so it
cannot have a supervising Manager of its own.  It looks like this
mixin technique results in "inheritance collision".  Is there a way
around this?

At the very least, this mixin technique seems a very confusing way to
build up classes.  Even barring any "Challenging" situation, my gut
feeling is that this technique sooner or later will collapse under its
own weight.  But at this point, I can't prove this rigorously.  One
thing that bothers me is that you have to pick some arbitrary order to
build up all the associations, so that in the end the total view of
each class includes all the associations it will participate in.  This
introduces arbitrary dependencies among the association instantiations
that don't seem to mean anything within the problem domain, but which
might have a detrimental impact on the software's resilience in the
face of requirements change.

If I'm totally mixed-up about mixins :-), please help me out.  Thanks.

-- John Volan

--------------------------------------------------------------------------------
--  Me : Person := (Name                => "John Volan",
--                  Company             => "Raytheon Missile Systems Division",
--                  E_Mail_Address      => "jgv@swl.msd.ray.com",
--                  Affiliation         => "Enthusiastic member of Team Ada!",
--                  Humorous_Disclaimer => "These opinions are undefined " &
--                                         "by my employer and therefore " &
--                                         "any use of them would be "     &
--                                         "totally erroneous.");
--------------------------------------------------------------------------------



  reply	other threads:[~1994-10-24 20:32 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1994-10-12 22:49 SOLVED! Decoupled Mutual Recursion Challenger John Volan
1994-10-17 15:48 ` John Volan
1994-10-17 17:55   ` Bob Duff
1994-10-17 20:52     ` John Volan
1994-10-17 22:10       ` Bob Duff
1994-10-18 22:17         ` John Volan
1994-10-19  1:01           ` Bob Duff
1994-10-19  4:45             ` Jay Martin
1994-10-19 14:38               ` Mark A Biggar
     [not found]                 ` <38fi4r$l81@oahu.cs.ucla.edu>
1994-10-24 11:49                   ` Mutual Recursion Challenge Robert I. Eachus
1994-10-24 20:32                     ` John Volan [this message]
1994-10-26 11:42                       ` Generic association example (was Re: Mutual Recursion Challenge) Robert I. Eachus
1994-10-26 23:21                         ` John Volan
1994-10-27 10:53                           ` Robert I. Eachus
1994-10-31 17:34                             ` John Volan
1994-10-27 14:37                           ` Mark A Biggar
1994-10-24 17:42                   ` SOLVED! Decoupled Mutual Recursion Challenger John Volan
1994-10-24 22:37                     ` Jay Martin
1994-10-25  5:47                       ` Matt Kennel
1994-10-25 10:04                         ` David Emery
1994-10-25 16:43                         ` John Volan
1994-10-27  4:25                           ` Rob Heyes
1994-10-28  9:03                             ` Mutual Recursion (was Re: SOLVED! Decoupled Mutual Recursion Challenger) Robert I. Eachus
1994-10-28 15:04                             ` SOLVED! Decoupled Mutual Recursion Challenger Robb Nebbe
1994-10-25 15:54                       ` John Volan
1994-10-26  1:24                         ` Bob Duff
1994-10-28  4:28                         ` Jay Martin
1994-10-28 10:52                           ` Robert I. Eachus
1994-10-28 18:46                             ` Jay Martin
1994-11-02 14:56                               ` Robert I. Eachus
1994-10-29  0:38                           ` Bob Duff
1994-10-29  7:26                             ` Jay Martin
1994-10-29 11:59                             ` Richard Kenner
1994-10-31 13:17                               ` Robert Dewar
1994-10-31 14:13                               ` gcc distribution (was: SOLVED! Decoupled Mutual Recursion Challenger) Norman H. Cohen
1994-11-02 14:14                                 ` Richard Kenner
1994-11-04 23:56                                   ` Michael Feldman
1994-10-31 18:44                           ` SOLVED! Decoupled Mutual Recursion Challenger John Volan
1994-10-20 11:25               ` Robb Nebbe
1994-10-20 19:19                 ` John Volan
1994-10-26  0:07                 ` Mark S. Hathaway
1994-10-26 18:48                 ` gamache
1994-10-27  2:15                   ` John Volan
     [not found]           ` <CxwGJF.FwB@ois.com>
1994-10-19 16:35             ` John Volan
1994-10-17 22:54   ` Cyrille Comar
replies disabled

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