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; 33+ 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] 33+ messages in thread

* Re: circular unit dependency
  1997-05-24  0:00 jdlopez
@ 1997-05-24  0:00 ` Michael F Brenner
  1997-05-25  0:00 ` Jon S Anthony
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 33+ 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] 33+ messages in thread

* Re: circular unit dependency
  1997-05-24  0:00 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 ` John G. Volan
  1997-05-31  0:00 ` Kevin Cline
  3 siblings, 1 reply; 33+ 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] 33+ 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
  1997-05-27  0:00     ` Jon S Anthony
  0 siblings, 2 replies; 33+ 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] 33+ 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
  1 sibling, 0 replies; 33+ 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] 33+ 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
  1 sibling, 0 replies; 33+ 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] 33+ messages in thread

* Re: circular unit dependency
  1997-05-24  0:00 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; 33+ 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] 33+ messages in thread

* Re: circular unit dependency
  1997-05-24  0:00 jdlopez
                   ` (2 preceding siblings ...)
  1997-05-28  0:00 ` 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; 33+ 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] 33+ 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; 33+ 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] 33+ 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; 33+ 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] 33+ 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; 33+ 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] 33+ 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; 33+ 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] 33+ messages in thread

* Re: circular unit dependency
  1997-05-28  0:00 ` John G. Volan
@ 1997-06-01  0:00   ` John G. Volan
  0 siblings, 0 replies; 33+ 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] 33+ 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; 33+ 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] 33+ 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; 33+ 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] 33+ 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; 33+ 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] 33+ 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; 33+ 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] 33+ 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; 33+ 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] 33+ 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; 33+ 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] 33+ 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; 33+ 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] 33+ 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; 33+ 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] 33+ messages in thread

* circular unit dependency
@ 1998-05-26  0:00 Brendan Reville
  0 siblings, 0 replies; 33+ messages in thread
From: Brendan Reville @ 1998-05-26  0:00 UTC (permalink / raw)



I have two packages, each of which "with"s the other.

I get the following error:

   "Circular unit dependency."


How can I then allow each package to "with" the other?

Thanks very much for any help!

- Brendan




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

* circular unit dependency
@ 2003-05-23  9:20 Mirko Aigner
  2003-05-23 11:37 ` Jeffrey Creem
  2003-05-23 18:08 ` Stephen Leake
  0 siblings, 2 replies; 33+ messages in thread
From: Mirko Aigner @ 2003-05-23  9:20 UTC (permalink / raw)


Hi Again !!

Any way to prevent this compiler error (circular unit dependency) 
without deleting one of the "with" statements ?!

Is there any way to make sure that on spec is only once "included" ?!

thanks for helping !!

greatings Mirko Aigner




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

* Re: circular unit dependency
  2003-05-23  9:20 circular unit dependency Mirko Aigner
@ 2003-05-23 11:37 ` Jeffrey Creem
  2003-05-23 12:12   ` David C. Hoos
  2003-05-23 18:08 ` Stephen Leake
  1 sibling, 1 reply; 33+ messages in thread
From: Jeffrey Creem @ 2003-05-23 11:37 UTC (permalink / raw)



"Mirko Aigner" <Mirko.Aigner@alcatel.de> wrote in message
news:3ECDE7D1.9010507@alcatel.de...
> Hi Again !!
>
> Any way to prevent this compiler error (circular unit dependency)
> without deleting one of the "with" statements ?!
>

The answer is almost certainly no. It is hard to be sure without seeing the
exact source code
but if you have two "specs" withing each other, you have a problem.

> Is there any way to make sure that on spec is only once "included" ?!

No. Withing is not the same as #include.


You probably needs to break this dependancy by creating a 3rd package spec.
Problems like this are usually (not always) an indication of a poor design.
You really are better off trying to get rid of it by re-thinking the
approach rather than coming up with a workaround.








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

* Re: circular unit dependency
  2003-05-23 11:37 ` Jeffrey Creem
@ 2003-05-23 12:12   ` David C. Hoos
  0 siblings, 0 replies; 33+ messages in thread
From: David C. Hoos @ 2003-05-23 12:12 UTC (permalink / raw)



"Jeffrey Creem" <jeff@thecreems.com> wrote in message
news:3Knza.694005$OV.649162@rwcrnsc54...
>
> "Mirko Aigner" <Mirko.Aigner@alcatel.de> wrote in message
> news:3ECDE7D1.9010507@alcatel.de...
> > Hi Again !!
> >
> > Any way to prevent this compiler error (circular unit dependency)
> > without deleting one of the "with" statements ?!
> >
>
> The answer is almost certainly no. It is hard to be sure without seeing
the
> exact source code
> but if you have two "specs" withing each other, you have a problem.
>
> > Is there any way to make sure that on spec is only once "included" ?!
>
> No. Withing is not the same as #include.
But even the #included files have to have ifdefs to insure that the file is
#included only once.
>
>
> You probably needs to break this dependancy by creating a 3rd package
spec.
> Problems like this are usually (not always) an indication of a poor
design.
> You really are better off trying to get rid of it by re-thinking the
> approach rather than coming up with a workaround.
>
>
>
>
>
> _______________________________________________
> comp.lang.ada mailing list
> comp.lang.ada@ada.eu.org
> http://ada.eu.org/mailman/listinfo/comp.lang.ada
>
>





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

* Re: circular unit dependency
  2003-05-23  9:20 circular unit dependency Mirko Aigner
  2003-05-23 11:37 ` Jeffrey Creem
@ 2003-05-23 18:08 ` Stephen Leake
  2003-05-24 22:12   ` Robert I. Eachus
  2003-05-26  8:05   ` Mirko Aigner
  1 sibling, 2 replies; 33+ messages in thread
From: Stephen Leake @ 2003-05-23 18:08 UTC (permalink / raw)


Mirko Aigner <Mirko.Aigner@alcatel.de> writes:

> Hi Again !!
> 
> Any way to prevent this compiler error (circular unit dependency)
> without deleting one of the "with" statements ?!

You will have to change something. You'll have to post the code, so we
can help you figure out what to change. Try to simplify it first.

If you have something like:

with A;
package B is
  
   type B_Type is record
      A_Obj : A.A_Type;
   end record;
end B;

with B;
package A is
  
   type A_Type is record
      B_Obj : B.B_Type;
   end record;
end A;

then the only way to "fix" this is to put both types in one package.
They belong together, since they are dependent on each other.

Other types of circular with can be cured by introducing a "parent" type.

> Is there any way to make sure that on spec is only once "included"
> ?!

"with" in Ada is really, really _not_ the same as "include" in C. By
definition, each package is in the library only once.

-- 
-- Stephe



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

* Re: circular unit dependency
  2003-05-23 18:08 ` Stephen Leake
@ 2003-05-24 22:12   ` Robert I. Eachus
  2003-05-26  8:05   ` Mirko Aigner
  1 sibling, 0 replies; 33+ messages in thread
From: Robert I. Eachus @ 2003-05-24 22:12 UTC (permalink / raw)


Stephen Leake wrote:

> If you have something like:
> 
> with A;
> package B is
>   
>    type B_Type is record
>       A_Obj : A.A_Type;
>    end record;
> end B;
> 
> with B;
> package A is
>   
>    type A_Type is record
>       B_Obj : B.B_Type;
>    end record;
> end A;
> 
> then the only way to "fix" this is to put both types in one package.
> They belong together, since they are dependent on each other.

Actually if he has a circular definition like that, he needs to do more 
than just change the package structure.  There is no way that a object 
of A_Type or B_Type can exist.  He would need to add an access type to 
break the cycle.




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

* Re: circular unit dependency
  2003-05-23 18:08 ` Stephen Leake
  2003-05-24 22:12   ` Robert I. Eachus
@ 2003-05-26  8:05   ` Mirko Aigner
  1 sibling, 0 replies; 33+ messages in thread
From: Mirko Aigner @ 2003-05-26  8:05 UTC (permalink / raw)


Stephen Leake wrote:
> 
> You will have to change something. You'll have to post the code, so we
> can help you figure out what to change. Try to simplify it first.
> 

I'm Sorry, Ok here comes some code.

Some words to the structure at first. There is a boundary subsystem 
where logical Messages are generated. These Messages can be from 
different type (class). All Messages are sent first to a dispatcher in 
the Control Subsystem. The  dispatcher send them to subscribed 
Control-Classes. The Control-Classes react to the messages.
The Control-Classes can be dynamically subscribed or unsubscribed to the 
dispatcher. Now there is used a design pattern called Visitor, so that 
the dispatcher can decide what kind of message he got.

I can't change the design, i have to implement it in Ada. It is already 
imlemented in C++.

here is some code ...

-- Event.ads

with Class_EventVisitor; use Class_EventVisitor;

package Class_Event is

   type Event is tagged null record;
   type Event_Pointer is access all Event'Class;

   procedure acceptVisitor( this : in Event_Pointer; visitor : in 
EventVisitor_Pointer ) is abstract;

end Class_Event;



-- Event.Message

with Class_EventVisitor; use Class_EventVisitor;

package Class_Event.Class_Message is

   type Message is new Event with null record;
   type Message_Pointer is access all Message'Class;

   procedure acceptVisitor( this : in Message_Pointer;
                            visitor : in EventVisitor_Pointer );

end Class_Event.Class_Message;


-- Event.Message.PointMessage

with Class_EventVisitor; use Class_EventVisitor;

package Class_Event.Class_Message.Class_PointMessage is

   type PointMessage is new Message with private;
   type PointMessage_Pointer is access all PointMessage'Class;

   procedure acceptVisitor( this : in PointMessage_Pointer;
                            visitor : in EventVisitor_Pointer );

   function Create ... return PointMessage;

private
   type PointMessage is new Message with record
      ...
   end record;

end Class_Event.Class_Message.Class_PointMessage;


-- EventVisitor

with Class_Event.Class_Message.Class_PointMessage;
use Class_Event.Class_Message.Class_PointMessage;

package Class_EventVisitor is

   type EventVisitor is tagged private;

   type EventVisitor_Pointer is access all EventVisitor'Class;

   procedure handlePointMessage ( this : in EventVisitor_Pointer;
                                  pMessage : in PointMessage_Pointer )
                                  is abstract;

   -- other message types
   ...


private
   type EventVisitor is tagged null record;

end Class_EventVisitor;

The Control-Class handling the PointMessage will inherit from the 
EventVisitor.




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

* circular unit dependency
@ 2005-01-04 18:31 R
  2005-01-04 23:45 ` Randy Brukardt
  2005-01-05  0:26 ` Stephen Leake
  0 siblings, 2 replies; 33+ messages in thread
From: R @ 2005-01-04 18:31 UTC (permalink / raw)


Hello everybody.

I've got a problem with circular unit dependency.

In main package I have:

with base;
with base.derv1;
with base.derv2;

derv1 has tagged record rec1 and derv2 has its rec2

the derv1 and derv2 packages have overritten operator "+"
which spec look like this:

in derv1 package spec and body I have:

with base.derv2; -- info about rec2 needed in "+" spec
...
function "+"(left: rec1; right: base.derv2.rec2) return rec1;

and the same thing with the second package spec and body:

with base.derv1; -- info about rec1 needed in "+"'s spec
...
function "+"(left: rec2; right: base.derv1.rec1) return rec2;

when I compile it with gcc i have:
main.adb:8:06: circular unit dependency
main.adb:8:06: "Main (body)" depends on "base.derv1 (spec)"
main.adb:8:06: "base.derv1 (spec)" depends on "base.derv2 (spec)"
main.adb:8:06: "base.derv2 (spec)" depends on "base.derv1 (spec)"
main.adb:8:06: "base.derv1 (spec)" depends on "base.derv1 (body)"
main.adb:8:06: "base.derv1 (body)" depends on "base.derv1 (spec)"
main.adb:8:06: "base.derv1 (spec)" depends on "base.derv1 (spec)"

well - I need info about other record because it's the parameter of
both function"+"

any idea? I tried to remove 'with' statement but then I received  msgs
like:
"xxx" not declared in "yyy"

thanks in advance

best regards
R




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

* Re: circular unit dependency
  2005-01-04 18:31 R
@ 2005-01-04 23:45 ` Randy Brukardt
  2005-01-05  8:35   ` Martin Krischik
  2005-01-05  0:26 ` Stephen Leake
  1 sibling, 1 reply; 33+ messages in thread
From: Randy Brukardt @ 2005-01-04 23:45 UTC (permalink / raw)


"R" <ruthless@poczta.onet.pl> wrote in message
news:1104863498.813484.201360@z14g2000cwz.googlegroups.com...
> Hello everybody.
>
> I've got a problem with circular unit dependency.

Get an Ada 2005 compiler and use limited with. (I believe GNAT Pro supports
that using some switch). Otherwise, you are SOL. The only solution is to put
everything together in one package (which is definitely disgusting).

                          Randy.






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

* Re: circular unit dependency
  2005-01-04 18:31 R
  2005-01-04 23:45 ` Randy Brukardt
@ 2005-01-05  0:26 ` Stephen Leake
  1 sibling, 0 replies; 33+ messages in thread
From: Stephen Leake @ 2005-01-05  0:26 UTC (permalink / raw)
  To: comp.lang.ada

"R" <ruthless@poczta.onet.pl> writes:

> In main package I have:
> 
> with base;
> with base.derv1;
> with base.derv2;
> 
> derv1 has tagged record rec1 and derv2 has its rec2
> 
> the derv1 and derv2 packages have overritten operator "+"
> which spec look like this:
> 
> function "+"(left: rec1; right: base.derv2.rec2) return rec1;
> 
> well - I need info about other record because it's the parameter of
> both function"+"

Yes.

> any idea? 

You need to move the "+" to a place where both base.derv1.rec1 and
base.derv2.rec2 are visible.

That could be another package base.derv3.

Or a child of one of the packages.

Or you may be able to move the declarations of rec1 and rec2 to
base.ads.

This will be fixed in Ada 2005, via a "limited with" clause. See
http://www.ada-auth.org/cgi-bin/cvsweb.cgi/AIs/AI-50217.TXT?rev=1.19 

-- 
-- Stephe




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

* Re: circular unit dependency
  2005-01-04 23:45 ` Randy Brukardt
@ 2005-01-05  8:35   ` Martin Krischik
  2005-01-05  8:55     ` Duncan Sands
  0 siblings, 1 reply; 33+ messages in thread
From: Martin Krischik @ 2005-01-05  8:35 UTC (permalink / raw)


Randy Brukardt wrote:

> "R" <ruthless@poczta.onet.pl> wrote in message
> news:1104863498.813484.201360@z14g2000cwz.googlegroups.com...
>> Hello everybody.
>>
>> I've got a problem with circular unit dependency.
> 
> Get an Ada 2005 compiler and use limited with. (I believe GNAT Pro
> supports that using some switch). Otherwise, you are SOL. The only
> solution is to put everything together in one package (which is definitely
> disgusting).

GNAT's limited with isn't finished yet. Last time (2 weeks ago) I checked it
got me an errror box right away.

Martin

-- 
mailto://krischik@users.sourceforge.net
http://www.ada.krischik.com



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

* Re: circular unit dependency
  2005-01-05  8:35   ` Martin Krischik
@ 2005-01-05  8:55     ` Duncan Sands
  0 siblings, 0 replies; 33+ messages in thread
From: Duncan Sands @ 2005-01-05  8:55 UTC (permalink / raw)
  To: comp.lang.ada, martin

> GNAT's limited with isn't finished yet. Last time (2 weeks ago) I checked it
> got me an errror box right away.

Me too.  The "with type" extension is more stable, if not perfect.

Duncan.



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

end of thread, other threads:[~2005-01-05  8:55 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-05-23  9:20 circular unit dependency Mirko Aigner
2003-05-23 11:37 ` Jeffrey Creem
2003-05-23 12:12   ` David C. Hoos
2003-05-23 18:08 ` Stephen Leake
2003-05-24 22:12   ` Robert I. Eachus
2003-05-26  8:05   ` Mirko Aigner
  -- strict thread matches above, loose matches on Subject: below --
2005-01-04 18:31 R
2005-01-04 23:45 ` Randy Brukardt
2005-01-05  8:35   ` Martin Krischik
2005-01-05  8:55     ` Duncan Sands
2005-01-05  0:26 ` Stephen Leake
1998-05-26  0:00 Brendan Reville
1997-05-24  0:00 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-05-28  0:00 ` 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