comp.lang.ada
 help / color / mirror / Atom feed
* circular unit dependency
@ 1997-05-24  0:00 jdlopez
  1997-05-24  0:00 ` Michael F Brenner
                   ` (3 more replies)
  0 siblings, 4 replies; 28+ messages in thread
From: jdlopez @ 1997-05-24  0:00 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 458 bytes --]


     I am making a program with 2 classes that each one depends on the
other:

--class1.ads
with class2;
package class1 is
--...

--class2.ads
withc class1;
package class2 is
--...

     When I compile class1.ads or class2.ads with the freeware gnat
ADA 95 (301a) a error appears:

     circular unit dependency

     I see what is happening but:

1- �Is there any way of solving this?
2- �Could it be compiled with any compiler different from gnat?




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: circular unit dependency
  1997-05-24  0:00 circular unit dependency jdlopez
@ 1997-05-24  0:00 ` Michael F Brenner
  1997-05-25  0:00 ` Jon S Anthony
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 28+ messages in thread
From: Michael F Brenner @ 1997-05-24  0:00 UTC (permalink / raw)



jdlopez@caminos.recol.es asks about 2 classes that each depend on the other

    with class2;
    package class1 is
    ... 
    withc class1;
    package class2 is
    ...
This gives gnat ADA 95 (301a) error: circular unit dependency

1- ?Is there any way of solving this?
     Sometimes, there is. Perhaps the WITH statements could be moved to
     the body of packages class1 and class2. If both visible parts REALLY
     need to import each other then perhaps the part that is common
     could be put into a common CLASS3, and each of the existing classes
     could import the common class. If this is REAALLY impossible, then
     your circle appears not to be able to be broken. Sorry, if this is true.

2- ?Could it be compiled with any compiler different from gnat?
     No other compiler will let you do those 4 lines. You must approach
     the problem in a slightly different way without a circular dependency
     in the visible parts (the package specifications). However, circular
     dependencies ARE permitted in the package BODIES. This is good, and
     making you break the circle will lead you down the quickest path to
     making your code work. Not sorry about this one.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: circular unit dependency
  1997-05-24  0:00 circular unit dependency jdlopez
  1997-05-24  0:00 ` Michael F Brenner
@ 1997-05-25  0:00 ` Jon S Anthony
  1997-05-26  0:00   ` John G. Volan
  1997-05-28  0:00 ` circular unit dependency John G. Volan
  1997-05-31  0:00 ` Kevin Cline
  3 siblings, 1 reply; 28+ messages in thread
From: Jon S Anthony @ 1997-05-25  0:00 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1367 bytes --]


In article <3386d96f.171920@noticias.ibernet.es> jdlopez@caminos.recol.es writes:

>      I am making a program with 2 classes that each one depends on the
> other:
> 
> --class1.ads
> with class2;
> package class1 is
> --...
> 
> --class2.ads
> withc class1;
> package class2 is
> --...
> 
>      When I compile class1.ads or class2.ads with the freeware gnat
> ADA 95 (301a) a error appears:
> 
>      circular unit dependency
> 
>      I see what is happening but:

Uh-Oh.  The recursive types across package boundaries issue again!
Run for it!!  :-)

This is an old issue that (rightly, I suppose) keeps coming up now and
again.  John Volan has a kind of generally agreed upon idiom for
getting around this issue using generics.  Maybe he will post his old
notes on the reasons he got where he did.  Or maybe it should be put
out on www.adahome.com??  Or you can read it in the Ada=>IDL mapping
document (where we used it to get around the problem of mapping
recursive IDL specs...)


> 2- �Could it be compiled with any compiler different from gnat?

Not if it is correct.

BTW, whatever happened to Tucker's plan for the fix for this?  The
"with P.T" solution?  I thought that was going to be an ACE thing or
some such, but haven't heard anything about it since.

/Jon
-- 
Jon Anthony
Organon Motives, Inc.
Belmont, MA 02178
617.484.3383
jsa@organon.com





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: circular unit dependency
  1997-05-25  0:00 ` Jon S Anthony
@ 1997-05-26  0:00   ` John G. Volan
  1997-05-26  0:00     ` Fergus Henderson
                       ` (2 more replies)
  0 siblings, 3 replies; 28+ messages in thread
From: John G. Volan @ 1997-05-26  0:00 UTC (permalink / raw)



Jon S Anthony wrote:
> 
> In article <3386d96f.171920@noticias.ibernet.es> jdlopez@caminos.recol.es writes:
> 
> >      I am making a program with 2 classes that each one depends on the
> > other:
...
> Uh-Oh.  The recursive types across package boundaries issue again!
> Run for it!!  :-)
> 
> This is an old issue that (rightly, I suppose) keeps coming up now and
> again.  John Volan has a kind of generally agreed upon idiom for
> getting around this issue using generics.  Maybe he will post his old
> notes on the reasons he got where he did.

Well, this time instead of posting the whole darn FAQ on comp.lang.ada,
I thought I'd take a couple of days, polish it up, turn it into HTML,
and publish it as a website, something I've been meaning to do for a
long time...it looks real spiffy in my browser now...but...I have just
discovered that my ISP doesn't provide personal web space!! (Huh?? I'm
sure I asked about that when I signed up! Arggh!) Oh well, I know
someone who might set me up with a quickie website cheap...will let
everyone know shortly...

> Or maybe it should be put out on www.adahome.com??

I'd love it if it were on adahome or someplace comparable.  Ages ago I
did mail my whole FAQ to Magnus Kempe in hopes he would install it into
adahome somewhere, or maybe the Ada Programmer's FAQ...but he refused.
He said it was because I stuck the LGPL on the generic Identity package.
(By the way, I've dropped the whole "object class identity" discussion
as being too abstruse, so I've changed the name of my generic package to
"Forward", signifying "forward declarations.")

Magnus is apparently allergic to the LGPL (or maybe he's just allergic
to my little generic gizmo, I dunno... :-) ).  At the risk of
resurrecting another monster thread, anyone have any advice on what
license verbiage I should use instead? I don't want to place any
restrictions on the use of my Forward package (i.e., I want to let
proprietary commercial stuff incorporate it without catching the free
software virus). But on the other hand, I want to keep copyright control
over it to prevent anyone from turning it proprietary and keeping others
from using it.  I thought the LGPL was good enough for that but now it
seems I'm wrong...

> Or you can read it in the Ada=>IDL mapping
> document (where we used it to get around the problem of mapping
> recursive IDL specs...)

Yeah, you might be able to puzzle out the generic forward declaration
pattern by looking at the CORBA.Forward package (since it directly
incorporated my idea). But unless you're actually doing distributed
programming with CORBA tools, you're not going to be able to use that
directly.  Better to look at my FAQ...as soon as I can put it
somewhere... :-)

> BTW, whatever happened to Tucker's plan for the fix for this?  The
> "with P.T" solution?  I thought that was going to be an ACE thing or
> some such, but haven't heard anything about it since.

Yeah, whatever did happen to Tucker's "with type" proposal?  I remember
he said this was something that really did need to be addressed "sooner
rather than later" -- i.e., before AdaOY.

(By the way, I've added a description of Tucker's "with type" notion
into my FAQ.)

-----------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name => "John G. Volan",  Home_Email => "johnvolan@sprintmail.com",
   Slogan => "Ada95: The World's *FIRST* International-Standard OOPL",
   Disclaimer => "These opinions were never defined, so using them " & 
     "would be erroneous...or is that just nondeterministic now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: circular unit dependency
  1997-05-26  0:00   ` John G. Volan
@ 1997-05-26  0:00     ` Fergus Henderson
  1997-05-27  0:00     ` Jon S Anthony
  1997-06-02  0:00     ` Ada95=>Ada0Y Process? [was: circular unit dependency] John G. Volan
  2 siblings, 0 replies; 28+ messages in thread
From: Fergus Henderson @ 1997-05-26  0:00 UTC (permalink / raw)



"John G. Volan" <johnvolan@sprintmail.com> writes:

>I'd love it if it were on adahome or someplace comparable.  Ages ago I
>did mail my whole FAQ to Magnus Kempe in hopes he would install it into
>adahome somewhere, or maybe the Ada Programmer's FAQ...but he refused.
>He said it was because I stuck the LGPL on the generic Identity package.
...
>Magnus is apparently allergic to the LGPL (or maybe he's just allergic
>to my little generic gizmo, I dunno... :-) ).  At the risk of
>resurrecting another monster thread, anyone have any advice on what
>license verbiage I should use instead? I don't want to place any
>restrictions on the use of my Forward package (i.e., I want to let
>proprietary commercial stuff incorporate it without catching the free
>software virus). But on the other hand, I want to keep copyright control
>over it to prevent anyone from turning it proprietary and keeping others
>from using it.  I thought the LGPL was good enough for that but now it
>seems I'm wrong...

Nope, you're right, the LGPL does satisfy those goals
(although the LGPL does impose some requirements that may
be an _inconvenience_ to proprietry software developers).
If Magnus Kempe is allergic to the LGPL, that's his problem.

[Followups redirected to gnu.misc.discuss.]

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: circular unit dependency
  1997-05-26  0:00   ` John G. Volan
  1997-05-26  0:00     ` Fergus Henderson
@ 1997-05-27  0:00     ` Jon S Anthony
  1997-06-02  0:00     ` Ada95=>Ada0Y Process? [was: circular unit dependency] John G. Volan
  2 siblings, 0 replies; 28+ messages in thread
From: Jon S Anthony @ 1997-05-27  0:00 UTC (permalink / raw)



In article <33898C78.27D3@sprintmail.com> "John G. Volan" <johnvolan@sprintmail.com> writes:

> (By the way, I've added a description of Tucker's "with type" notion
> into my FAQ.)

Excellent.  That would be a nice addition and keeps things wrapped in
a central discussion.

/Jon

-- 
Jon Anthony
Organon Motives, Inc.
Belmont, MA 02178
617.484.3383
jsa@organon.com





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: circular unit dependency
  1997-05-24  0:00 circular unit dependency jdlopez
  1997-05-24  0:00 ` Michael F Brenner
  1997-05-25  0:00 ` Jon S Anthony
@ 1997-05-28  0:00 ` John G. Volan
  1997-06-01  0:00   ` John G. Volan
  1997-05-31  0:00 ` Kevin Cline
  3 siblings, 1 reply; 28+ messages in thread
From: John G. Volan @ 1997-05-28  0:00 UTC (permalink / raw)



jdlopez@caminos.recol.es wrote:
> 
>      When I compile class1.ads or class2.ads with the freeware gnat
> ADA 95 (301a) a error appears:
> 
>      circular unit dependency

Okay, folks, you can find the FAQ for this at:

http://bluemarble.net/~jvolan/WithingProblem/FAQ.html

Enjoy! :-)

------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name => "John G. Volan",  Home_Email => "johnvolan@sprintmail.com",
   Slogan => "Ada95: The World's *FIRST* International-Standard OOPL",
   Disclaimer => "These opinions were never defined, so using them " & 
     "would be erroneous...or is that just nondeterministic now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: circular unit dependency
  1997-05-24  0:00 circular unit dependency jdlopez
                   ` (2 preceding siblings ...)
  1997-05-28  0:00 ` circular unit dependency John G. Volan
@ 1997-05-31  0:00 ` Kevin Cline
  1997-05-31  0:00   ` Matthew Heaney
  1997-05-31  0:00   ` John G. Volan
  3 siblings, 2 replies; 28+ messages in thread
From: Kevin Cline @ 1997-05-31  0:00 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 574 bytes --]


jdlopez@caminos.recol.es wrote:

>     I am making a program with 2 classes that each one depends on the
>other:
>
>--class1.ads
>with class2;
>package class1 is
>--...
>
>--class2.ads
>withc class1;
>package class2 is
>--...
>
>     When I compile class1.ads or class2.ads with the freeware gnat
>ADA 95 (301a) a error appears:
>
>     circular unit dependency
>
>     I see what is happening but:
>
>1- �Is there any way of solving this?

Put them both in the same package, since neither is useful without the other.
You are attempting to separate the inseparable.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: circular unit dependency
  1997-05-31  0:00 ` Kevin Cline
  1997-05-31  0:00   ` Matthew Heaney
@ 1997-05-31  0:00   ` John G. Volan
  1997-06-01  0:00     ` Kevin Cline
  1997-06-02  0:00     ` John G. Volan
  1 sibling, 2 replies; 28+ messages in thread
From: John G. Volan @ 1997-05-31  0:00 UTC (permalink / raw)



Woops, here we go again!  :-)

Kevin Cline wrote:
> 
> Put them both in the same package, since neither is useful without the other.

Au contraire, mon frere! Class1 may be useful in contexts 1, 2, 3 and 4;
class2 in contexts 3, 4, 5 and 6.  If I am writing client code in
context 1 or 2, why should I care a whit about Class2?  In context 5 or
6, why should I care about Class1?  Only in context 3 and 4 are both
needed together.  For more on this, see my FAQ, section [4]:

http://bluemarble.net/~jvolan/WithingProblem/FAQ.html#whybad

> You are attempting to separate the inseparable.

Said the irresistible force to the immovable object: "Inseparable, they
are not!" :-)  See my FAQ, section [6]:

http://bluemarble.net/~jvolan/WithingProblem/FAQ.html#workaround

... uh, but not today. BlueMarble had a disk crash, won't be back up
until this evening.

------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name       => "John G. Volan",
   Employer   => "Texas Instruments Advanced C3I Systems, San Jose, CA",
   Work_Email => "johnv@ti.com",
   Home_Email => "johnvolan@sprintmail.com",
   Slogan     => "Ada95: World's *FIRST* International-Standard OOPL",
   Disclaimer => "My employer never defined these opinions, so using" & 
                 "them would be totally erroneous ... or is that"     &
                 "just nondeterministic behavior now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: circular unit dependency
  1997-05-31  0:00 ` Kevin Cline
@ 1997-05-31  0:00   ` Matthew Heaney
       [not found]     ` <33932F31.4399@sprintmail.com>
  1997-05-31  0:00   ` John G. Volan
  1 sibling, 1 reply; 28+ messages in thread
From: Matthew Heaney @ 1997-05-31  0:00 UTC (permalink / raw)



In article
<9A7E8196B8D7EE83.E6C868B798076E45.6F1AD9E8B3E01F66@library-proxy.airnews.ne
t>, clines@delete_this.airmail.net (Kevin Cline) wrote:


>Put them both in the same package, since neither is useful without the other.
>You are attempting to separate the inseparable.

Wonderful advice!  At last, someone who is sympathetic to the idea that,
yes, different types can go in the same Ada package.   What a concept,
using the language as it was designed to be used!

Mutual dependency of specs is often an indication that you really should
have only a single spec, containing the entities from both packages.

It's very simple, really.  :-)

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: circular unit dependency
  1997-05-31  0:00   ` John G. Volan
@ 1997-06-01  0:00     ` Kevin Cline
  1997-06-01  0:00       ` John G. Volan
  1997-06-02  0:00     ` John G. Volan
  1 sibling, 1 reply; 28+ messages in thread
From: Kevin Cline @ 1997-06-01  0:00 UTC (permalink / raw)



"John G. Volan" <johnvolan@sprintmail.com> wrote:

>Woops, here we go again!  :-)
>
>Kevin Cline wrote:
>> 
>> Put them both in the same package, since neither is useful without the other.
>
>Au contraire, mon frere! Class1 may be useful in contexts 1, 2, 3 and 4;
>class2 in contexts 3, 4, 5 and 6.  If I am writing client code in
>context 1 or 2, why should I care a whit about Class2?  

It doesn't matter which ones you "care" about.  To use either, you have to
link both package bodies.  The package interface and package body are two
separate aspects of a single software component.  Circular dependencies
between components should be avoided.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: circular unit dependency
  1997-06-01  0:00     ` Kevin Cline
@ 1997-06-01  0:00       ` John G. Volan
  0 siblings, 0 replies; 28+ messages in thread
From: John G. Volan @ 1997-06-01  0:00 UTC (permalink / raw)



[Looks like one of my posts got lost, so let me try it again. Apologies
if it appears after all...]

Kevin Cline wrote:
> 
> "John G. Volan" <johnvolan@sprintmail.com> wrote:
> 
> >Au contraire, mon frere! Class1 may be useful in contexts 1, 2, 3 and 4;
> >class2 in contexts 3, 4, 5 and 6.  If I am writing client code in
> >context 1 or 2, why should I care a whit about Class2?
> 
> It doesn't matter which ones you "care" about.  To use either, you have to
> link both package bodies.  

Well, of course they both have to be _linked_ together. After all, the
premise is that Class1 and Class2, in some aspect of their
functionality, collaborate with each other. So of course they had both
better exist within the same executable. But the issue is not whether
these two classes have to be _linked_ together; the issue is whether
they have to be _used_ together, by all of their various clients within
that executable.

In other words, does the fact that Class1 and Class2 happen to be
clients of each other necessarily mean that every _other_ client of
Class1 is _always_ going to be a client of Class2 as well (and vice
versa)?  What if their mutual collaboration is only one small aspect of
their respective functionalities?  What if, in particular, Class1
participates in collaborations with other classes that Class2 is not
directly involved with (and vice versa)?

For instance, suppose Class2 mutually collaborates with Class3, but that
Class3 does not collaborate directly with Class1.  In other words, the
designer of Class3 should be able to write all the Class3 operations
that involve Class2 entirely in terms of a subset of Class2 operations
that only involve Class3.  According to the design of the application,
there is absolutely no need for Class3 to mention Class1 at all. 
According to you, however, we are forced to put Class3 in the same
package with Class2.  But Class2 (according to you) is already in the
same package with Class1.  So Class3 is now in the same package with
Class1.  This package is starting to get a bit hefty now.

What if, meanwhile, Class1 is collaborating with Class4, and this aspect
of its functionality is independent of its involvement with Class2? 
Your package has to swallow up Class4 as well.  This, despite the fact
that the connection between Class3 and Class4 is quite tenuous, there
being no less than three layers of abstraction between them:
 
	Class3<-->Class2<-->Class1<-->Class4

Or at least, there would have been, if we hadn't been so busy pointedly
dissolving those layers of abstraction.

As we expand our viewpoint to take in more and more of the classes in
our class-association diagram, what if we find that Class2 has another
association, with Class5, and Class5 has a totally independent
association with Class6?  Yup -- those puppies get tossed right into the
ravenous maw of our class-eating monster package.

> The package interface and package body are two
> separate aspects of a single software component.

Yeah, so? What's your point?

>  Circular dependencies
> between components should be avoided.

Why?  This sounds like a religious statement. Or rather, it sounds like
the kind of statement that was once made by various authorities in the
Ada world back in the early days of Ada83. I should point out that, in
this object-oriented age, those very same authorities have since come
around to the viewpoint that, well, sometimes circular dependency -- or
rather, mutual client-server dependency between object-classes -- is not
only okay, but in fact is downright necessary.  Even Tucker Taft has
said that Ada95 ought to be modified to help enable that.

What exactly is so bad about mutual dependency?  Class1 is a client of
Class2. Why should the way I implement that be different depending on
whether or not Class2 also coincidentally happens to be a client of
Class1?

Isn't co-encapsulation worse than mutual dependency?  Consider: Suppose,
as I advocate, we separately encapsulate Class1, Class2, Class3, and
Class4, despite their various mutual dependencies.  Now suppose the
interface to Class4 has to change. (Let's say we discover that we need
Class7 to collaborate with Class4, so we introduce some operations to
cover that aspect of Class4's functionality.)  The body of Class1 has to
be recompiled, yes, but (if the association is really independent)
Class1 shouldn't have to be modified.

In particular, the interface of Class1 shouldn't have to be modified. In
fact, the whole point to any workaround to the "withing" problem is that
Class1's interface isn't dependent on the full interface for Class4, but
only on some kind of "forward declaration" of Class4.  So the Class1
package spec shouldn't have to change, and it shouldn't have to be
recompiled.

This means that Class2 doesn't have to be recompiled, and Class3 doesn't
have to be recompiled, and so on and so on.  More important than just
the CPU time we don't have to spend running the compiler, is the human
time we don't have to spend worrying whether Class2, Class3, and so on
need to be re-written.  After all, Class1 is supposed to be an
abstraction, and nothing about that abstraction has changed as far as
Class2 is concerned.  And Class3, etc. haven't even _heard_ of Class1!

But if, as you suggest, all these classes have been sucked down a black
hole into a single-package singularity, then recompiling one class means
recompiling them all.  Worse than the CPU time spent running the
compiler is the human time that needs to be spent making sure that the
changes we made in introducing Class7 don't somehow affect any of the
other classes in the package.  With no clear package boundaries
separating them, we can't be sure unless we do some deep analysis -- and
that takes human mental effort, which means $$$.

------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name       => "John G. Volan",
   Employer   => "Texas Instruments Advanced C3I Systems, San Jose, CA",
   Work_Email => "johnv@ti.com",
   Home_Email => "johnvolan@sprintmail.com",
   Slogan     => "Ada95: World's *FIRST* International-Standard OOPL",
   Disclaimer => "My employer never defined these opinions, so using" & 
                 "them would be totally erroneous ... or is that"     &
                 "just nondeterministic behavior now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: circular unit dependency
  1997-05-28  0:00 ` circular unit dependency John G. Volan
@ 1997-06-01  0:00   ` John G. Volan
  0 siblings, 0 replies; 28+ messages in thread
From: John G. Volan @ 1997-06-01  0:00 UTC (permalink / raw)



John G. Volan wrote:
> 
> Okay, folks, you can find the FAQ for this at:
> 
> http://bluemarble.net/~jvolan/WithingProblem/FAQ.html
> 
> Enjoy! :-)

A little update since I first released my FAQ web page: I've spiffed it 
up a bit more, modified some parts, and added some new content. In
particular:

- I've also added section 5.4, which compares the situation in C++ with
the proposed Ada0Y solutions to the "withing" problem. (Which I discuss
in sections 5.1-5.3. I just added those sections last week, so they
weren't originally in my FAQ on comp.lang.ada.)

- I've taken the LGPL off the Forward package and substituted the "Ada
Community License" devised by David Weller.  The ACL seems to be just
what I was looking for to guarantee this would be free software, but
without all the dogma. :-)
 
------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name       => "John G. Volan",
   Employer   => "Texas Instruments Advanced C3I Systems, San Jose, CA",
   Work_Email => "johnv@ti.com",
   Home_Email => "johnvolan@sprintmail.com",
   Slogan     => "Ada95: World's *FIRST* International-Standard OOPL",
   Disclaimer => "My employer never defined these opinions, so using" & 
                 "them would be totally erroneous ... or is that"     &
                 "just nondeterministic behavior now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: circular unit dependency
  1997-05-31  0:00   ` John G. Volan
  1997-06-01  0:00     ` Kevin Cline
@ 1997-06-02  0:00     ` John G. Volan
  1 sibling, 0 replies; 28+ messages in thread
From: John G. Volan @ 1997-06-02  0:00 UTC (permalink / raw)



John G. Volan wrote:
> 
> Kevin Cline wrote:
> >
> > Put them both in the same package, since neither is useful without the other.
> 
> Au contraire, mon frere! Class1 may be useful in contexts 1, 2, 3 and 4;
> class2 in contexts 3, 4, 5 and 6.  If I am writing client code in
> context 1 or 2, why should I care a whit about Class2?  In context 5 or
> 6, why should I care about Class1?  Only in context 3 and 4 are both
> needed together.  For more on this, see my FAQ, section [4]:
> 
> http://bluemarble.net/~jvolan/WithingProblem/FAQ.html#whybad

Sorry, that should have been:

http://bluemarble.net/~jvolan/WithingProblem/FAQ.html#why_bad

------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name       => "John G. Volan",
   Employer   => "Texas Instruments Advanced C3I Systems, San Jose, CA",
   Work_Email => "johnv@ti.com",
   Home_Email => "johnvolan@sprintmail.com",
   Slogan     => "Ada95: World's *FIRST* International-Standard OOPL",
   Disclaimer => "My employer never defined these opinions, so using " & 
                 "them would be totally erroneous...or is that just "  &
                 "nondeterministic behavior now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Ada95=>Ada0Y Process? [was: circular unit dependency]
  1997-05-26  0:00   ` John G. Volan
  1997-05-26  0:00     ` Fergus Henderson
  1997-05-27  0:00     ` Jon S Anthony
@ 1997-06-02  0:00     ` John G. Volan
  1997-06-04  0:00       ` Ada95 packages, C++ namespaces, & circular dependencies John G. Volan
  1997-06-07  0:00       ` Ada95=>Ada0Y Process? [was: circular unit dependency] Robert Dewar
  2 siblings, 2 replies; 28+ messages in thread
From: John G. Volan @ 1997-06-02  0:00 UTC (permalink / raw)



Jon S Anthony wrote:
> BTW, whatever happened to Tucker's plan for the fix for this?  The
> "with P.T" solution?  I thought that was going to be an ACE thing or
> some such, but haven't heard anything about it since.

I (John G. Volan) replied:
> 
> Yeah, whatever did happen to Tucker's "with type" proposal?  I remember
> he said this was something that really did need to be addressed "sooner
> rather than later" -- i.e., before AdaOY.

It has been a week and there has been utter silence on this. Tucker, are
you there?  I guess if there's no answer, then it must mean that
nobody's doing anything about this.

If I remember correctly, the last time this came up, Tucker said he was
experimenting with some kind of pragma trick, but it didn't really sound
as satisfying to me as his "with type" proposal.  Tucker, your proposal
was a bold stroke (especially your oblique suggestion that it be adopted
_before_ Ada0Y), but now it seems like you've backed off on it. What
gives?

My question for comp.lang.ada as a whole is this:  What mechanism, if
any, is currently established for evolving the Ada language standard? 
Since I haven't heard the trumpet fanfare yet, obviously the Ada0Y
process has not yet begun (and is not due to begin for a few years yet).
However, is there an interim Rapporteur Group or something that is
administering Ada95 Interpretations and/or extension requests and
what-not?  Maybe they'd like to have a look at the hypothetical language
rules for with-type clauses described in
http://bluemarble.net/~jvolan/WithingProblem/FAQ.html#forward_incompletes

------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name       => "John G. Volan",
   Employer   => "Texas Instruments Advanced C3I Systems, San Jose, CA",
   Work_Email => "johnv@ti.com",
   Home_Email => "johnvolan@sprintmail.com",
   Slogan     => "Ada95: World's *FIRST* International-Standard OOPL",
   Disclaimer => "My employer never defined these opinions, so using " & 
                 "them would be totally erroneous...or is that just "  &
                 "nondeterministic behavior now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: circular unit dependency
       [not found]     ` <33932F31.4399@sprintmail.com>
@ 1997-06-02  0:00       ` Matthew Heaney
  1997-06-03  0:00         ` John G. Volan
  1997-06-03  0:00         ` W. Wesley Groleau (Wes)
  0 siblings, 2 replies; 28+ messages in thread
From: Matthew Heaney @ 1997-06-02  0:00 UTC (permalink / raw)



In article <33932F31.4399@sprintmail.com>, johnvolan@sprintmail.com wrote:

>> Mutual dependency of specs is often an indication that you really should
>> have only a single spec, containing the entities from both packages.
>
>An old, old fallacy, totally obviated by real experience with today's
>object-oriented client/supplier applications.  Consider distributed OO
>software using CORBA: Mutual dependency of IDL interfaces happens all
>the time.  All the other OO languages out there have no trouble mapping
>to that, why should Ada be hobbled in this regard?

I'm not sure what you mean by "totally obviated," because obviate means "to
make unnecessary."  Do you mean "to show to be untrue"?  Perhaps you meant
"gainsay" or "belie."

Oh, yes, I realize the CORBA's IDL allows mutual dependency of modules, but
this a really dumb thing to do.  

But we're comparing apples and oranges.  In IDL, an module is a type.  That
IDL "modules" are allowed to be mutually dependent means that "types" are
allowed to by mutually dependent.  So be it.  To have mutually dependent
types in Ada, just put them together in the same package, as you yourself
stated.

The guys that wrote the Ada IDL binding made a common mistake: they mapped
an IDL module (type) to an Ada package.  This was a poor choice, and
suffers exactly from the problem you describe: how do you have mutual
dependencies now, across package boundaries?  This is an IDL-to-Ada mapping
problem, not a problem with Ada the language.  The authors of the mapping
made a mistake.   What they should have done was to map an IDL type to an
Ada type.

But no, they didn't do that, and seemed to have C++ on-the-brain when they
wrote the mapping document.  If the developers of that binding were
thinking in Ada, using its "a module is not a type" paradigm, then they
should have realized any binding must detect mutual dependencies across
types, and properly colocate the mutually dependent types together.

Because they failed to do that, they had to solve the mutual dependency
problem that they themselves created, and so came up with a klunky scheme
whereby each type designates the other through a pointer to a common
ancestor.  So we've reduced Ada to the typeless paradigm proffered by
Smalltalk and Objective-C.

They also used the horrible convention of naming types "Object," in a
misguided attempt to "fix" Ada by pretending that a package is a type. 
Well, I have news for you, in Ada a package is not a type, so you better
get used to it.  If you don't like that, then you're definately using the
wrong language, and it does not good for you (nor for the maintenance
programmer unlucky enough to inherit your code) to pine for the language to
be some other way.  To try to separate mutually dependent types across
package boundaries will only obfuscate the code, as evidenced by the
pointer-to-common-ancestor technique, which wouldn't have been necessary
had they done the mapping properly.

Would allowing dependencies across package boundaries be better?  Sure! 
I'm all for it.  But that's a far different thing from saying that Ada has
some kind of "with'ing problem" (which it does not).  Somehow I manage to
program every day in Ada, thank you very much, in spite of Ada's
"difficiencies."

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: circular unit dependency
  1997-06-02  0:00       ` Matthew Heaney
  1997-06-03  0:00         ` John G. Volan
@ 1997-06-03  0:00         ` W. Wesley Groleau (Wes)
  1997-06-03  0:00           ` John G. Volan
  1 sibling, 1 reply; 28+ messages in thread
From: W. Wesley Groleau (Wes) @ 1997-06-03  0:00 UTC (permalink / raw)



Matthew:
Did you read John's treatise?  It presents a _reasonable_ example
of two types that
1. do not depend on each other, 
2. have _no_ particular reason for co-encapsulation of abstraction,
   except...
3. have subprograms that must refer to the other type.

John,
Your example is reasonable, and a solution would be a good thing, 
but the problem is not a disaster.  I can only remember once in 
over ten years that I wished I could separately package two types 
but couldn't.

----------------------------------------------------------------------
    Wes Groleau, Hughes Defense Communications, Fort Wayne, IN USA
Senior Software Engineer - AFATDS                  Tool-smith Wanna-be

Don't send me your advertisements!  I'll proofread and return them for 
$50.00 (US) per hundred words (plus a small fee per correction). 
----------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: circular unit dependency
  1997-06-02  0:00       ` Matthew Heaney
@ 1997-06-03  0:00         ` John G. Volan
  1997-06-05  0:00           ` Matthew Heaney
  1997-06-03  0:00         ` W. Wesley Groleau (Wes)
  1 sibling, 1 reply; 28+ messages in thread
From: John G. Volan @ 1997-06-03  0:00 UTC (permalink / raw)



Matthew Heaney wrote:
> 
> Oh, yes, I realize the CORBA's IDL allows mutual dependency of modules, but
> this a really dumb thing to do.
> 
> But we're comparing apples and oranges.  In IDL, an module is a type.  That
> IDL "modules" are allowed to be mutually dependent means that "types" are
> allowed to by mutually dependent.  So be it.  To have mutually dependent
> types in Ada, just put them together in the same package, as you yourself
> stated.

Nope. I admitted that there was a certain subset of mutually dependent
types that are very highly coupled and so belong in the same package
with each other, primarily because they must share implementation
details. But I also defended the fact that this subset did not
constitute the entire set of mutually-dependent types.  There are a
great many cases where the types are very loosely coupled and fall into
a client/supplier pattern.  It is unwise to co-encapsulate in this kind
of situation, because of the transitivity effect and because the types
are not intended to share implementation details--they present
abstractions to each other. If you can't see that, well, you can't see
that, too bad.

> The guys that wrote the Ada IDL binding made a common mistake: they mapped
> an IDL module (type) to an Ada package.  This was a poor choice, and
> suffers exactly from the problem you describe: how do you have mutual
> dependencies now, across package boundaries?  This is an IDL-to-Ada mapping
> problem, not a problem with Ada the language.  The authors of the mapping
> made a mistake.   What they should have done was to map an IDL type to an
> Ada type.

They did that. :-) But they also recognized that an IDL _interface_
(catch that: _interface_, not _type_) is an _abstraction_ that
_encapsulates_ distributed object services.  This concept _includes_ the
notion of modularity, as well as the notion of data abstraction.

It was not a poor choice, it was a necessary one. The problem is with
Ada, and it either needs a workaround or a fix.

> But no, they didn't do that, and seemed to have C++ on-the-brain when they
> wrote the mapping document.  

Oh come on.  Ada is the only language I know of that is unable to fully
modularize object classes in the most general case. If you're trying to
make your point by belittling C++, you're going to have to take on
Eiffel, Smalltalk, CLOS, Java, and in short the whole wide OO world...

> If the developers of that binding were
> thinking in Ada,  

What is this "thinking in Ada" thing?  Sounds like religious bigotry to
me, nothing to do with the design principles of Ada.  (I'm one of the
biggest Ada advocates around, but I'm not so blinded by zeal that I
can't see the warts, the places where something  was missed that could
have fit naturally into Ada's design principles.)

> using its "a module is not a type" paradigm,

Of course a module is not a type. That's one of the great things about
Ada: The fact that types and packages are orthogonal constructs.  Which
means they can be composed in a variety of ways.  Including a pattern in
which each type is separately encapsulated.  Which is one of many
legitimate design choices.  A _design choice_, which is justified for a
certain set of domains under a certain set of design criteria.  There is
no "one true Ada way."

There are kinds of modules that go beyond object classes. Ada packages
(and especially child hierarchies) are great for that.  But it is a
legitimate option to choose to have object-classes act as base-level
units of modularity.

> then they
> should have realized any binding must detect mutual dependencies across
> types, ...

That's silly. You take something that should be a simple,
straightforward mapping, something that should be easy to build a
mapping-compiler for, and instead superimpose this extra complexity,
requiring the mapping-compiler to do this unnecessary extra analysis and
make an arbitrary distinction between one kind of client and another. 
I'm glad the IDL-to-Ada mapping folks didn't listen to you; the solution
they chose made the job of constructing an IDL-to-Ada compiler _much_
simpler and more orthogonal that they feared it would be.

> ... and properly colocate the mutually dependent types together.

Make that: Improperly colocate (because the types don't need access to
each other's implementation details).  And make that improperly colocate
_many_ types together -- _all_ your types, in the worst case.  How many
times do I have to describe the transitivity effect before the light
dawns?

> Because they failed to do that, they had to solve the mutual dependency
> problem that they themselves created, and so came up with a klunky scheme
> whereby each type designates the other through a pointer to a common
> ancestor.  So we've reduced Ada to the typeless paradigm proffered by
> Smalltalk and Objective-C.

You really don't know what you're talking about.  My generic forwarding
scheme preserves type safety, because it establishes a one-to-one
correspondence between a class and a reference type responsible for
designating that class. It is nothing at all like Smalltalk and
Objective-C.  It is very much like the way Ada does access types:
They're all treated as distinct types by the compiler, but they share a
common underlying implementation.

The common ancestor pointer you criticize is just a hidden
implementation detail -- one possible implementation scheme for those
abstract reference types, but not the only one.  That particular
implementation choice was a convenient one for the IDL-to-Ada folks,
because -- get this -- _they_ _already_ _had_ _a_ _common_ _ancestor_
_type_ _anyway_, for reasons that had nothing to do with mutual
dependency: These are all CORBA distributed object classes, after all.
They're supposed to share common mechanisms and resources that make them
distributed object classes.  Inheriting from a root type that
establishes those resources is a very smart design.

> They also used the horrible convention of naming types "Object," in a
> misguided attempt to "fix" Ada by pretending that a package is a type.
> Well, I have news for you, in Ada a package is not a type, so you better
> get used to it.  

This is supposed to be news to _me_?  Are you kidding me?

> If you don't like that, then you're definately using the
> wrong language, and it does not good for you ... to pine for the language to
> be some other way...

Does this statement have anything to do with engineering, or is it just
religiously based?

> (nor for the maintenance
> programmer unlucky enough to inherit your code)

I feel sorry for the maintenance programmer who's faced with a package
containing a dozen object classes, who has to puzzle out the fact that
each one is only directly collaborating with 2-4 others, and not _all_
the others. Who also has to somehow magically realize that, despite
their being in the same package, they all carefully refrain from
touching each other's private declarations -- and if he doesn't realize
that and starts ignoring the abstractions, poof goes the original
design.  This, because all of the abstraction boundaries that should
have been there, weren't, because of this co-encapsulation dogma.

This dogma is so ironic, because one of the design principles behind Ada
was that different abstractions would be encapsulated into different
packages, and the collaborations between the abstractions would be
obvious, because you'd see them in the "with" clauses.  All of that is
lost when you co-encapsulate.

> To try to separate mutually dependent types across
> package boundaries will only obfuscate the code, as evidenced by the
> pointer-to-common-ancestor technique, which wouldn't have been necessary
> had they done the mapping properly.

How can the pointer-to-common-ancestor obfuscate, when it is hidden
inside an abstraction, and the abstraction presents exactly the proper
concept: A reference type that designates one and only one object-class.

I find it far more obfuscatory to take a object-oriented analysis and
design model that has nice, clean abstraction boundaries and then
dissolve those abstractions into package soup!
 
> Would allowing dependencies across package boundaries be better?  Sure!
> I'm all for it.  But that's a far different thing from saying that Ada has
> some kind of "with'ing problem" (which it does not).

Make up your mind: How can you be all for something that you claim is
totally unnecessary?

> Somehow I manage to
> program every day in Ada, thank you very much, in spite of Ada's
> "difficiencies."

I guess you meant "deficiencies". (Hey, if you're going to nit-pick over
word usage...)

Perhaps you just haven't worked on the kinds of problems where this
issue arises.  There are a lot of ways to skirt the issue (see section 3
of my FAQ for a few).  But there are just some domains where this
pattern is the most straightforward one, the one that preserves the most
abstractions.

------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name       => "John G. Volan",
   Employer   => "Texas Instruments Advanced C3I Systems, San Jose, CA",
   Work_Email => "johnv@ti.com",
   Home_Email => "johnvolan@sprintmail.com",
   Slogan     => "Ada95: World's *FIRST* International-Standard OOPL",
   Disclaimer => "My employer never defined these opinions, so using" & 
                 "them would be totally erroneous ... or is that"     &
                 "just nondeterministic behavior now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: circular unit dependency
  1997-06-03  0:00         ` W. Wesley Groleau (Wes)
@ 1997-06-03  0:00           ` John G. Volan
  0 siblings, 0 replies; 28+ messages in thread
From: John G. Volan @ 1997-06-03  0:00 UTC (permalink / raw)



W. Wesley Groleau (Wes) wrote:
> 
> John,
> Your example is reasonable, and a solution would be a good thing,
> but the problem is not a disaster.  I can only remember once in
> over ten years that I wished I could separately package two types
> but couldn't.

Of course it's not a disaster. There are, after all, a variety of
avoidance techniques, some of which I enumerate in section [3] of my
FAQ.  I think what happens is that most Ada programmers naturally fall
into the technique suggested by [3.2]: Arbitrarily choose one class to
be client-only and the other to be supplier-only, force the association
to be one-way.  I suspect many Ada programmers are not even conscious
that they are doing that. I exploit it whenever I can.  It can let you
go quite a long time without ever facing the Day of Mutual Reckoning.
:-)  However, this kind of one-way biasing is somewhat artificial and
stilted when, conceptually, the object classes are really peers.  The
alternative, mutually dependent packages, only _seems_ awkward because
of this quirk (or rather, this hole) in the language. If Ada already had
one of the enhancements that have been suggested (see section [5]), I
wager we wouldn't be having any of these religious debates about how
packages were "meant" to be used.

I just think, as we begin entering an era of increasingly large and
complex domains (e.g., distributed client/server object systems), these
kinds of situations will increase in frequency.  It would be a good idea
to have all our ducks in a row. I believe that separately encapsulated
yet mutually dependent object classes are a legitimate design pattern,
one that ought to be available as an option within every engineer's
repertoire.

------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name       => "John G. Volan",
   Employer   => "Texas Instruments Advanced C3I Systems, San Jose, CA",
   Work_Email => "johnv@ti.com",
   Home_Email => "johnvolan@sprintmail.com",
   Slogan     => "Ada95: World's *FIRST* International-Standard OOPL",
   Disclaimer => "My employer never defined these opinions, so using " & 
                 "them would be totally erroneous...or is that just "  &
                 "nondeterministic behavior now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Ada95 packages, C++ namespaces, & circular dependencies
  1997-06-02  0:00     ` Ada95=>Ada0Y Process? [was: circular unit dependency] John G. Volan
@ 1997-06-04  0:00       ` John G. Volan
  1997-06-07  0:00       ` Ada95=>Ada0Y Process? [was: circular unit dependency] Robert Dewar
  1 sibling, 0 replies; 28+ messages in thread
From: John G. Volan @ 1997-06-04  0:00 UTC (permalink / raw)



David Weller wrote:
> 
> John,
> here's an interesting thought.  WIth the advent of namespaces in C++,
> which generally mimic packages (the "old" non-child type a la Ada83),
                                  ^^^^^^^^^^^^^^^^^^^^^^^^
                                  See [***] NOTE: below

> what is the result of mutual dependencies on classes in separate
> namespaces?  I wonder if that has an effect in C++?  I don't know if
> you've pondered that one or not.

-----

I'm cross-posting this to comp.lang.c++, because it's pertinent, and
because I would like to get some confirmation on my understanding of
C++.  For those of you on comp.lang.c++, here's the background on this
thread: I've written up an FAQ concerning an apparent "hole" in the
design of Ada95 known as the "with-ing" problem, which has to do with
circular dependencies between packages. You can find this FAQ at the
following URL:

    http://bluemarble.net/~jvolan/WithingProblem/FAQ.html

You might want to peruse this before reading further.  In particular,
section [5.4] compares proposed Ada0Y solutions for this problem with
the current situation in C++

    http://bluemarble.net/~jvolan/WithingProblem/FAQ.html#cplusplus
    
Please do not use this thread as an excuse for Ada-bashing. In comparing
Ada95 with C++, I've tried to be fair to both languages. Please extend
the same courtesy.

-----    

Here's my response to David Weller:

It's only been in the past couple days that I've managed to find the URL
for the online C++ draft standard working paper

    http://www.maths.warwick.ac.uk/c++/pub/wp/html/cd2/

and read the straight dope on namespaces. From what I can glean from the
verbiage there, it doesn't look like namespaces introduce any new
problems for C++ with regard to separate encapsulation/mutual
dependency.

In fact, to me they seem most reminiscent of Norman Cohen's "package
parts" idea for Ada0Y. It appears that you can scatter as many sections
of the same namespace as you want through any given C++ compilation. 
So, for instance, you could have the following (but see the [**]
DISCLAIMER below).

  // let this be all in one file, or perhaps all in
  // one output from the C++ preprocessor:

  namespace Doctors {  // initial definition of namespace
    class Doctor;      // forward class declaration
  }

  namespace Patients { // initial definition of namespace
    class Patient;     // forward class declaration
  }
  ...

  namespace Doctors {  // extension providing "interface"
    class Doctor {     // full class declaration
      ...
    public:
      ...
      void treatPatient (Patients::Patient& patient);
      void billPatient  (Patients::Patient& patient);
      ...
    };
  }

  namespace Patients { // extension providing "interface"
    class Patient {    // full class declaration
      ...
    public:
      ...
      void visitDoctor (Doctors::Doctor& doctor);
      void payDoctor   (Doctors::Doctor& doctor);
      ...
    };
  }
  ...
  //----- See [*] NOTE: below. -----

  namespace Doctors {  // extension providing "implementation"

    // definitions of Doctor member functions:

    void Doctor::billPatient (Patients::Patient& patient) {
      ...
      Doctor& doctor = *this;
      patient.payDoctor (doctor);
    }
    ...
  }

  namespace Patients { // extension providing "implementation"

    // definitions of Patient member functions:

    void Patient::visitDoctor (Doctors::Doctor& doctor) {
      ...
      Patient& patient = *this;
      doctor.treatPatient (patient);
    }
    ...
  }

This arrangement seems a lot like my "package abstracts" proposal (see
section [5.1] of my FAQ, at URL:

    http://bluemarble.net/~jvolan/WithingProblem/FAQ.html#abstracts 

It also appears that namespace sections can be sliced up and scattered
through as many source files as you wish.  Remember that C++ still does
not define any notion of "semantic dependency" between "compilation
units" comparable to Ada's "with" clauses (at least, as near as I can
tell).  All it provides is a mechanism for preprocessor textual
inclusion between source files.  It's up to the programmer to make sure
that the source files that are #included into a given compilation get
assembled into some kind of meaningful order within the preprocessor,
before being fed into the compiler proper. And it's still up to the
programmer to specify what object files go into a link, and to ensure 
that those object files are semantically consistent with each other--or
at least they are all based on the same versions of the same #included
source files (usually with assistance from some tool outside the
language, e.g. "make").

But this allows a C++ programmer to do something like the following:

  ////////////////////////////////////////////////////////////
  // Doctors_forward.h
  ////////////////////////////////////////////////////////////
  #ifndef _DOCTORS_FORWARD_H
  #define _DOCTORS_FORWARD_H
  namespace Doctors {      // initial definition of namespace
    class Doctor;          // forward class declaration
  }
  #endif  _DOCTORS_FORWARD_H

  ////////////////////////////////////////////////////////////
  // Doctors.h
  ////////////////////////////////////////////////////////////
  #ifndef _DOCTORS_H
  #define _DOCTORS_H
  #include "Doctors_forward.h"
  #include "Patients_forward.h"
  ...                      // other *_forward.h inclusions
  namespace Doctors {      // extension providing "interface"
    class Doctor {         // full class declaration
      ...
    public:
      ...
      void treatPatient (Patients::Patient& patient);
      void billPatient  (Patients::Patient& patient);
      ...
    };
  }
  #endif  _DOCTORS_H

  ////////////////////////////////////////////////////////////
  // Doctors.cc
  ////////////////////////////////////////////////////////////
  #include "Doctors.h"
  #include "Patients.h"
  ...                  // other *.h inclusions
  namespace Doctors {  // extension providing "implementation"

    // definitions of Doctor member functions:

    void Doctor::billPatient (Patients::Patient& patient) {
      ...
      Doctor& doctor = *this;
      patient.payDoctor (doctor);
    }
    ...
  }

The source files for the sections of the Patients namespace would be
similar.

[*] NOTE: The sequence of #include directives in the Doctors.cc file

  #include "Doctors.h"
  #include "Patients.h"

when textually expanded in the C++ preprocessor, would generate the
interleaving of Doctors and Patients namespace sections I showed above,
up to the "See [*] NOTE:" comment.  The sequence of #includes that might
appear in the Patients.cc file

  #include "Patients.h"
  #include "Doctors.h"

would generate a similar interleaving, but with the corresponding
Doctors and Patients sections interchanged.  Both interleavings should
compile successfully. It just goes to show you: It really doesn't matter
whether the chicken comes first, or the egg! :-)

[**] DISCLAIMER:  The Doctors/Patients namespace example above is a bit
contrived.  I'm not sure you'd want to bother wrapping e.g. a "Doctor"
class inside a "Doctors" namespace, since the class itself, being a kind
of module as well as a type, already provides a level of scope analogous
to a "Doctors" package containing a "Doctor_Type". A more realistic
scenario might be to use a namespace for a subsystem, with various
classes nested inside it (but possibly scattered over many source
files).  For instance, you might have a "Providers" subsystem
implemented as a namespace, with "Doctor" as one of the classes inside
it; likewise, a "Consumers" subsystem as a namespace, with "Patient" as
one of the classes inside it.)

[***] NOTE: David, I think you may be underestimating what namespaces
can do. Because you are allowed to extend a namespace as many times as
you like within a given compilation, and because the C++ preprocessor
can stitch together a compilation from any arbitrary set of source file
inclusions, it looks like namespaces will in fact be able to mimic the
functionality of Ada95 child hierarchies after all.

------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name       => "John G. Volan",
   Employer   => "Texas Instruments Advanced C3I Systems, San Jose, CA",
   Work_Email => "johnv@ti.com",
   Home_Email => "johnvolan@sprintmail.com",
   Slogan     => "Ada95: World's *FIRST* International-Standard OOPL",
   Disclaimer => "My employer never defined these opinions, so using" & 
                 "them would be totally erroneous ... or is that"     &
                 "just nondeterministic behavior now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: circular unit dependency
  1997-06-05  0:00           ` Matthew Heaney
@ 1997-06-05  0:00             ` John G. Volan
  1997-06-06  0:00             ` Stephen Schmid
  1 sibling, 0 replies; 28+ messages in thread
From: John G. Volan @ 1997-06-05  0:00 UTC (permalink / raw)



Matthew Heaney wrote:
> 
> In article <3393D0E1.AC9@sprintmail.com>, johnvolan@sprintmail.com wrote:
> 
> >Perhaps you just haven't worked on the kinds of problems where this
> >issue arises.  There are a lot of ways to skirt the issue (see section 3
> >of my FAQ for a few).  But there are just some domains where this
> >pattern is the most straightforward one, the one that preserves the most
> >abstractions.
> 
> Perhaps that's true.  Bob Eachus and those guys gave examples the last time
> we...um..."discussed" this ...um.. "issue" in the language, where recursive
> packages neatly solved the problem.

What is a "recursive" package? Do you mean a package encapsulating two
types that are mutually dependent?  Yes, that is a legitimate coding
pattern too, but I disagree that it is always appropriate for every case
of mutually-dependent types (i.e., types whose primitive operations
include parameters of the other type).  I even disagree that it is
always appropriate for mutually _recursive_ types (types whose
structures must contain references (e.g. access values) designating the
other type).  I think the key question is whether the types need access
to each other's implementation details or just each other's interfaces.

With regard to the past discussion of this topic: Although it became
heated at times, I believe it always remained civil.  I did make a point
of criticizing all those conservative voices that kept denying there was
a problem. I will continue to challenge anyone who continues to deny the
problem.  But I viewed it then, and I view it still, as an intellectual
debate, not a personal or political one.  This is why I chafed at those
who tried to make it personal or political.

I especially chafed at those who dogmatically repeated the litany: "Do
it our way, or go program in something else."  I stubbornly refused to
do that, and instead proposed an Ada0Y solution (thus goading Norman
Cohen and Tucker Taft to propose other comparable solutions), and kept
pushing until I found a workaround that can be used today (and is). Now,
who do you think has gone further to promote Ada, me or the dogmatics?

> Right now I'm doing a job for a client who insisted that each ADT get its
> own package (even if it were a nested one), even when colocating the types
> would have been the most natural solution.  The result is a bloody mess.

This is why I have been trying to promote "1 package = 1 type" as a
design pattern _among_ design patterns.  Neither this pattern, nor the
co-encapsulation pattern, should be viewed as the "One True Way".  Each
has _appropriate_ applications.  Those who are dogmatic for one or the
other, without weighing the design tradeoffs, are just displaying poor
engineering judgment.  And I for one am not afraid to call it that, when
I see it, no matter how highly esteemed the personage involved.

> The example is of a queue and its iterator.  Obviously the iterator has to
> know the representation of the queue, so it can iterate over it.  But the
> queue also keeps track of the iterators that have registered with it, so
> that it can adjust the pointer if an element is removed from the queue.

This is exactly the sort of case I had in mind where co-encapsulation
_can_ be justified: The types are very tightly coupled, and need to know
each other's _implementations_.  But this case should be carefully
distinguished from loosely coupled types that don't need to know each
other's implementation details, yet still collaborate with each other in
terms of each other's abstractions.

> Now, this is certainly not the smartest way to do iteration (they didn't
> need all that power, nor the attendent complexity), but the queue
> abstraction was made unnecessarily complex because it didn't have
> visibility to the representation of the iterator, which was in a nested
> package.  The simple solution would have been to just put the 2 types
> together in the same package, so they could see each other's
> representation.

Hmm. I think there might be a way for you to satisfy your employer while
at the same time simplifying your life a bit.  Your boss wants the
iterator type to be visible in its own package, fine. But who says it
actually has to be _implemented_ there?  Here's the idea:

(1) Move your iterator type to a child of your container package.

(2) Write an iterator implementation type inside your container package,
but hide it in the private part.  The container type and the iterator
implementation type can know each other's implementation details.

(3) Privately implement your iterator type in the child package using
the ready-made iterator implementation type from the parent container
package.  

  package Containers is
    type Container_Type is ... private;
    ... -- primitive Container operations
  private
    type Iterator_Implementation_Type is ...
    ... -- primitive Iterator_Implementation operations
    type Container_Type is ...
  end Containers;

  package Containers.Iterators is
    type Iterator_Type is ... private;
    ... -- primitive Iterator operations
  private
    type Iterator_Type is
      record
        Implementation : Iterator_Implementation_Type;
      end record;
  end Containers.Iterators;

In other words, Containers.Iterators is just a "skin" package providing
access to something already built-in (but hidden) in the Containers
package.  You'll have to implement the Iterator_Type operations using
delegation: Each Iterator_Type operation needs to explicitly call the
corresponding Iterator_Implementation_Type operation. (Inheritance won't
work, because you can't take privately-inherited features and make them
public.)  But this way, the real guts of the iterator implementation can
be in the same package with the container guts.

> This is the about the only degree of colocation I've ever seen necessary: 2
> types that are mutually dependent.  I'm not suggesting put "24 types"
> together in the same package, and agree completely that that would be a bit
> confusing!  (Though the reader of my examples posted on the SIGAda Patterns
> WG home page should be warned: my toy examples all feature multiple types
> per package!)
> 
> My real issue is with this coding convention that's been floating around
> for years, that says something like "Thou shalt put only one ADT per
> package."  If you blindly apply a rule like that, without any thought at
> all (like on my current project), then you're going to make your code very
> complex.  The guideline should be stated "Don't put unrelated types
> together in the same package," because that would increase coupling.  (It
> gives a client interested in only one of the types an unnecessary
> compilation dependency on the other.)
> 
> Glib application of the former rule is also a warning sign that the shop
> isn't really thinking in Ada, and is confusing module and type.  Natural
> and elegant solutions are only effected by immersing oneself in the
> language, and not fighting its idiosyncrasies.

Violent agreement. :-) Just beware that, in fighting one dogma, you
don't inadvertently promote another...

------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name       => "John G. Volan",
   Employer   => "Texas Instruments Advanced C3I Systems, San Jose, CA",
   Work_Email => "johnv@ti.com",
   Home_Email => "johnvolan@sprintmail.com",
   Slogan     => "Ada95: World's *FIRST* International-Standard OOPL",
   Disclaimer => "My employer never defined these opinions, so using " & 
                 "them would be totally erroneous...or is that just "  &
                 "nondeterministic behavior now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: circular unit dependency
  1997-06-03  0:00         ` John G. Volan
@ 1997-06-05  0:00           ` Matthew Heaney
  1997-06-05  0:00             ` John G. Volan
  1997-06-06  0:00             ` Stephen Schmid
  0 siblings, 2 replies; 28+ messages in thread
From: Matthew Heaney @ 1997-06-05  0:00 UTC (permalink / raw)



In article <3393D0E1.AC9@sprintmail.com>, johnvolan@sprintmail.com wrote:

>I guess you meant "deficiencies". (Hey, if you're going to nit-pick over
>word usage...)

I guess it's time for me to install my spell-checker, which I got as a
Christmas gift!

I've been studying for the GRE, and I've had to memorize thousands of
words!  Funny that that should be a criterion for getting into grad school. 
You'd think that they would prefer I spend my time studying the theory of
machines and computation.  They didn't even ask for any sample code!

But I digress.

>Perhaps you just haven't worked on the kinds of problems where this
>issue arises.  There are a lot of ways to skirt the issue (see section 3
>of my FAQ for a few).  But there are just some domains where this
>pattern is the most straightforward one, the one that preserves the most
>abstractions.

Perhaps that's true.  Bob Eachus and those guys gave examples the last time
we...um..."discussed" this ...um.. "issue" in the language, where recursive
packages neatly solved the problem.

Right now I'm doing a job for a client who insisted that each ADT get its
own package (even if it were a nested one), even when colocating the types
would have been the most natural solution.  The result is a bloody mess.

The example is of a queue and its iterator.  Obviously the iterator has to
know the representation of the queue, so it can iterate over it.  But the
queue also keeps track of the iterators that have registered with it, so
that it can adjust the pointer if an element is removed from the queue.

Now, this is certainly not the smartest way to do iteration (they didn't
need all that power, nor the attendent complexity), but the queue
abstraction was made unnecessarily complex because it didn't have
visibility to the representation of the iterator, which was in a nested
package.  The simple solution would have been to just put the 2 types
together in the same package, so they could see each other's
representation.

This is the about the only degree of colocation I've ever seen necessary: 2
types that are mutually dependent.  I'm not suggesting put "24 types"
together in the same package, and agree completely that that would be a bit
confusing!  (Though the reader of my examples posted on the SIGAda Patterns
WG home page should be warned: my toy examples all feature multiple types
per package!)

My real issue is with this coding convention that's been floating around
for years, that says something like "Thou shalt put only one ADT per
package."  If you blindly apply a rule like that, without any thought at
all (like on my current project), then you're going to make your code very
complex.  The guideline should be stated "Don't put unrelated types
together in the same package," because that would increase coupling.  (It
gives a client interested in only one of the types an unnecessary
compilation dependency on the other.)

Glib application of the former rule is also a warning sign that the shop
isn't really thinking in Ada, and is confusing module and type.  Natural
and elegant solutions are only effected by immersing oneself in the
language, and not fighting its idiosyncrasies.

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: circular unit dependency
  1997-06-05  0:00           ` Matthew Heaney
  1997-06-05  0:00             ` John G. Volan
@ 1997-06-06  0:00             ` Stephen Schmid
  1 sibling, 0 replies; 28+ messages in thread
From: Stephen Schmid @ 1997-06-06  0:00 UTC (permalink / raw)



mheaney@ni.net (Matthew Heaney) writes:

> The example is of a queue and its iterator.  Obviously the iterator has to
> know the representation of the queue, so it can iterate over it.  But the
> queue also keeps track of the iterators that have registered with it, so
> that it can adjust the pointer if an element is removed from the queue.

I haven't thought about how to implement it in Ada95, but the 'Iterator'
pattern in the 'Design Patterns' book by the GOF shows how to construct
collections and iterators that do not need access to the internal
representations of each other.

Steve Schmid




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada95=>Ada0Y Process? [was: circular unit dependency]
  1997-06-02  0:00     ` Ada95=>Ada0Y Process? [was: circular unit dependency] John G. Volan
  1997-06-04  0:00       ` Ada95 packages, C++ namespaces, & circular dependencies John G. Volan
@ 1997-06-07  0:00       ` Robert Dewar
  1997-06-07  0:00         ` John G. Volan
  1997-06-07  0:00         ` John G. Volan
  1 sibling, 2 replies; 28+ messages in thread
From: Robert Dewar @ 1997-06-07  0:00 UTC (permalink / raw)



John Volan says

<<It has been a week and there has been utter silence on this. Tucker, are
you there?  I guess if there's no answer, then it must mean that
nobody's doing anything about this.
>>

Is it conceivable that an alternative explanation is that Tuck is away, he
was at the Ada Europe conference, where he gave a very interesting address
on an entirely different subject???

:-)





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada95=>Ada0Y Process? [was: circular unit dependency]
  1997-06-07  0:00       ` Ada95=>Ada0Y Process? [was: circular unit dependency] Robert Dewar
  1997-06-07  0:00         ` John G. Volan
@ 1997-06-07  0:00         ` John G. Volan
  1 sibling, 0 replies; 28+ messages in thread
From: John G. Volan @ 1997-06-07  0:00 UTC (permalink / raw)



Robert Dewar wrote:
> 
> John Volan says
> 
> <<It has been a week and there has been utter silence on this. Tucker, are
> you there?  I guess if there's no answer, then it must mean that
> nobody's doing anything about this.
> >>
> 
> Is it conceivable that an alternative explanation is that Tuck is away, he
> was at the Ada Europe conference, where he gave a very interesting address
> on an entirely different subject???
> 
> :-)

Ah, I had a suspicion there was a major conference going on, forgot
about Ada Europe. "It was quiet around here. Too quiet." :-)

------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name       => "John G. Volan",
   Employer   => "Texas Instruments Advanced C3I Systems, San Jose, CA",
   Work_Email => "johnv@ti.com",
   Home_Email => "johnvolan@sprintmail.com",
   Slogan     => "Ada95: World's *FIRST* International-Standard OOPL",
   Disclaimer => "My employer never defined these opinions, so using" & 
                 "them would be totally erroneous ... or is that"     &
                 "just nondeterministic behavior now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada95=>Ada0Y Process? [was: circular unit dependency]
  1997-06-07  0:00       ` Ada95=>Ada0Y Process? [was: circular unit dependency] Robert Dewar
@ 1997-06-07  0:00         ` John G. Volan
  1997-06-08  0:00           ` Robert Dewar
  1997-06-07  0:00         ` John G. Volan
  1 sibling, 1 reply; 28+ messages in thread
From: John G. Volan @ 1997-06-07  0:00 UTC (permalink / raw)



Robert, according to the SIGAda website (http://info.acm.org/sigada/),
you're listed as the contact for (and I'm guessing the chairman of) the
Standards Working Group ("SIGAda's liaison to Ada language maintenance
activities").  Can you answer my original question?

I wrote:
> My question for comp.lang.ada as a whole is this:  What mechanism, if
> any, is currently established for evolving the Ada language standard?
> Since I haven't heard the trumpet fanfare yet, obviously the Ada0Y
> process has not yet begun (and is not due to begin for a few years yet).
> However, is there an interim Rapporteur Group or something that is
> administering Ada95 Interpretations and/or extension requests and
> what-not?  Maybe they'd like to have a look at the hypothetical language
> rules for with-type clauses described in
> http://bluemarble.net/~jvolan/WithingProblem/FAQ.html#forward_incompletes

------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name       => "John G. Volan",
   Employer   => "Texas Instruments Advanced C3I Systems, San Jose, CA",
   Work_Email => "johnv@ti.com",
   Home_Email => "johnvolan@sprintmail.com",
   Slogan     => "Ada95: World's *FIRST* International-Standard OOPL",
   Disclaimer => "My employer never defined these opinions, so using" & 
                 "them would be totally erroneous ... or is that"     &
                 "just nondeterministic behavior now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada95=>Ada0Y Process? [was: circular unit dependency]
  1997-06-07  0:00         ` John G. Volan
@ 1997-06-08  0:00           ` Robert Dewar
  1997-06-08  0:00             ` John G. Volan
  0 siblings, 1 reply; 28+ messages in thread
From: Robert Dewar @ 1997-06-08  0:00 UTC (permalink / raw)



John Volan asks

<<> My question for comp.lang.ada as a whole is this:  What mechanism, if
> any, is currently established for evolving the Ada language standard?
> Since I haven't heard the trumpet fanfare yet, obviously the Ada0Y
> process has not yet begun (and is not due to begin for a few years yet).
> However, is there an interim Rapporteur Group or something that is
> administering Ada95 Interpretations and/or extension requests and
> what-not?  Maybe they'd like to have a look at the hypothetical language
> rules for with-type clauses described in
> http://bluemarble.net/~jvolan/WithingProblem/FAQ.html#forward_incompletes>>


The current Ada standard is maintained by ISO WG9, with the technical work
being done by its Ada Rapporteur Group. The ARG is concerned with clarifying
the current standard and fixing any minor problems found, it is not concerned
with evolving the standard. No formal group that I know of is concerned with
the latter, and indeed I think any formalized discussions of changes to
Ada 95 would be premature and non-constructive.

Probably one of the most useful things at this stage would be for people to
prototype possible new language suggestions using GNAT.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada95=>Ada0Y Process? [was: circular unit dependency]
  1997-06-08  0:00           ` Robert Dewar
@ 1997-06-08  0:00             ` John G. Volan
  0 siblings, 0 replies; 28+ messages in thread
From: John G. Volan @ 1997-06-08  0:00 UTC (permalink / raw)



Robert Dewar wrote:
> 
> John Volan asks
> 
> <<> My question for comp.lang.ada as a whole is this:  What mechanism, if
> > any, is currently established for evolving the Ada language standard?
> [snip]
>
> The current Ada standard is maintained by ISO WG9, with the technical work
> being done by its Ada Rapporteur Group. The ARG is concerned with clarifying
> the current standard and fixing any minor problems found, it is not concerned
> with evolving the standard. No formal group that I know of is concerned with
> the latter, and indeed I think any formalized discussions of changes to
> Ada 95 would be premature and non-constructive.

Yes, that is what I thought. Thank you.

(Just out of curiosity, is there a URL for ISO (and WG9 (and the ARG))?)

> Probably one of the most useful things at this stage would be for people to
> prototype possible new language suggestions using GNAT.

I have started looking at the GNAT 3.09 sources with that very
possibility in mind. With regard to the Ada0Y proposals I enumerated in
my FAQ:

- Scanner: The scanner most likely would not need to be modified, since
these proposals don't require any new reserved words or any different
treatment of lexical elements. (The most I could see there would be
possible new error handling situations with feedback from the parser.)

- Parser: The parser would need to be modified to recognize the new
syntax and generate new kinds of nodes and/or entities, e.g., the
forward incomplete types.  This does not look to be a huge amount of
work.

- Semantic Analyzer: The biggest part of the job would be in the
semantic analyzer, to deal with new situations involving forward
incomplete types spanning compilation units.  For instance, an ordinary
"with" clause would need new handling to deal with the possibility that
it provides the completion of a forward incomplete type. There would
have to be checks to determine that a forward incomplete type was
actually completed at the necessary places. And so forth.

A "divide-and-conquer" strategy is applicable here: "With type" clauses
(and the forward incomplete types they introduce) could be implemented
first and experimented with, and later one could experiment with
liberalizing incomplete types for use as "in," "out," and "in out"
parameters. (This is one reason why I broke up Tucker's original
proposal into two sections in my FAQ.)

- Expander/Gigi/Backend: I'm not sure I know enough there to estimate
what would need to be done, but I'm hoping changes to those parts can be
avoided.

Any advice you could give to someone contemplating such an adventure
would be greatly appreciated.

In particular, what would be the best way to structure such enhancements
so they would be maintainable given the on-going maintenance of GNAT?
 
------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name       => "John G. Volan",
   Employer   => "Texas Instruments Advanced C3I Systems, San Jose, CA",
   Work_Email => "johnv@ti.com",
   Home_Email => "johnvolan@sprintmail.com",
   Slogan     => "Ada95: World's *FIRST* International-Standard OOPL",
   Disclaimer => "My employer never defined these opinions, so using" & 
                 "them would be totally erroneous ... or is that"     &
                 "just nondeterministic behavior now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~1997-06-08  0:00 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-05-24  0:00 circular unit dependency jdlopez
1997-05-24  0:00 ` Michael F Brenner
1997-05-25  0:00 ` Jon S Anthony
1997-05-26  0:00   ` John G. Volan
1997-05-26  0:00     ` Fergus Henderson
1997-05-27  0:00     ` Jon S Anthony
1997-06-02  0:00     ` Ada95=>Ada0Y Process? [was: circular unit dependency] John G. Volan
1997-06-04  0:00       ` Ada95 packages, C++ namespaces, & circular dependencies John G. Volan
1997-06-07  0:00       ` Ada95=>Ada0Y Process? [was: circular unit dependency] Robert Dewar
1997-06-07  0:00         ` John G. Volan
1997-06-08  0:00           ` Robert Dewar
1997-06-08  0:00             ` John G. Volan
1997-06-07  0:00         ` John G. Volan
1997-05-28  0:00 ` circular unit dependency John G. Volan
1997-06-01  0:00   ` John G. Volan
1997-05-31  0:00 ` Kevin Cline
1997-05-31  0:00   ` Matthew Heaney
     [not found]     ` <33932F31.4399@sprintmail.com>
1997-06-02  0:00       ` Matthew Heaney
1997-06-03  0:00         ` John G. Volan
1997-06-05  0:00           ` Matthew Heaney
1997-06-05  0:00             ` John G. Volan
1997-06-06  0:00             ` Stephen Schmid
1997-06-03  0:00         ` W. Wesley Groleau (Wes)
1997-06-03  0:00           ` John G. Volan
1997-05-31  0:00   ` John G. Volan
1997-06-01  0:00     ` Kevin Cline
1997-06-01  0:00       ` John G. Volan
1997-06-02  0:00     ` John G. Volan

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