From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,aea4cc77526f5e4a X-Google-Attributes: gid103376,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!news1.google.com!newshub.sdsu.edu!newscon04.news.prodigy.net!prodigy.net!newsdst01.news.prodigy.net!prodigy.com!postmaster.news.prodigy.com!newssvr13.news.prodigy.net.POSTED!4988f22a!not-for-mail From: Newsgroups: comp.lang.ada References: <7xJvj.7420$Ru4.4246@newssvr19.news.prodigy.net> Subject: Re: Separate Compilation in Programming Languages X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2900.3138 X-RFC2646: Format=Flowed; Original X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.3198 Message-ID: <1wkwj.10399$0o7.2971@newssvr13.news.prodigy.net> NNTP-Posting-Host: 70.134.112.39 X-Complaints-To: abuse@prodigy.net X-Trace: newssvr13.news.prodigy.net 1203885181 ST000 70.134.112.39 (Sun, 24 Feb 2008 15:33:01 EST) NNTP-Posting-Date: Sun, 24 Feb 2008 15:33:01 EST Organization: SBC http://yahoo.sbc.com X-UserInfo1: Q[RGW^WETZSMB_DX]BCBNWX@RJ_XPDLMN@GZ_GYO^BTJUZ]CDVW[AKK[J\]^HVKHG^EWZHBLO^[\NH_AZFWGN^\DHNVMX_DHHX[FSQKBOTS@@BP^]C@RHS_AGDDC[AJM_T[GZNRNZAY]GNCPBDYKOLK^_CZFWPGHZIXW@C[AFKBBQS@E@DAZ]VDFUNTQQ]FN Date: Sun, 24 Feb 2008 20:33:01 GMT Xref: g2news1.google.com comp.lang.ada:20043 Date: 2008-02-24T20:33:01+00:00 List-Id: "Robert A Duff" wrote in message news:wccve4eff0d.fsf@shell01.TheWorld.com... > writes: > >> "Robert A Duff" wrote in message >> news:wccbq679zah.fsf@shell01.TheWorld.com... >> >> In the example you provided (shown below) you did defer the with clause >> for the Package P1 to the package body of P2. This illustrates my point. >> If the specification for P1 changes, only the body for P2 needs to be >> compiled. >> Had the with clause been at the specification level for P2, and had the >> specification for P1 changed, the entire package would have had to be >> compiled. > > Earlier, you said that this conversation was not about compilation > costs, but now you seem quite interested in compilation costs. > That's OK. So let's talk about compilation costs. ;-) > Actually, it is not about compilation "cost." Rather, it is about architecture stability, where compilation does play a role. > I think you miss the point of my example (still shown below). > Package P1 is the interface, and P2 is the implementation > of that interface. P2 is NOT a client of P1, it's an > implementation of P1! > > There are perhaps 37 clients of P1, not shown. The question is, > if we modify the implementation (i.e. P2) do we need to recompile > those 37 clients. The answer is "no". > Yes. I agree. When we defer the implementation to the body, there is no need to recompile anything, unless the implementation is tightly bound to the specification. The architectural concern is when we recompile the specification. Any change to the specification will imply a change to everything dependent upon it. > As you point out, if you change the interface, you have to recompile the > implementation. That's true in my example. It's also true if > the interface/implementation is split in the more traditional > Ada way (spec/body). > This is not true in the traditional Ada way when the dependencies are deferred to the implementation level. When the specification is dependent on something that has changed, it is true. When the specification is not dependent on that change, the high-level architecture remains intact and does not need recompiling. > The issue of recompiling the spec of P2 is irrelevant, since it's empty! > In your example, you have deferred the dependency to the body of P2. So there is no need to recompile the spec for P2. However, if the with clause had been at the specification level of P2, and if the specification for P1 had changed, there is certainly a danger of an architectural problem if we did not recompile the specification and body for P2. > > Let me try a more concrete example -- the trusty stack example. > > First, the traditional Ada way, using what you like to call "opaque" > types: > Opaque type is not my name for this. It seems to be a commonly accepted term for the idiom. > package Stacks is > type Stack is private; > procedure Push(...); > ... > private > type Stack_Rec; > type Stack is access Stack_Rec; > end Stacks; > > package Stacks is > type Stack_Rec is record ...; > procedure Push(...) is > begin > ... > end Push; > ... > end Stacks; > > If we change the implementation of the stacks abstraction (i.e. the body > of package Stacks), we do not normally need to recompile the clients. > Correct. A change to the implementation does not require a recompilation. However, a change to the specification does. Also, in the example shown, you accidentally omitted the word "body" from the implementation unit. > We can accomplish the same thing with interfaces. I'll use a child > package this time, just for fun: > > package Stacks is > type Stack is interface; > procedure Push(...) is abstract; > ... > end Stacks; > > package Stacks.Implementation is > type Stack_Impl is new Stack with private; > private > type Stack_Impl is ...; > overriding procedure Push(...); > ... > end Stacks.Implementation; > > package Stacks.Implementation is > > procedure Push(...) is > begin > ... > end Push; > ... > end Stacks.Implementation; > > If we change the implementation of the stacks abstraction (i.e. the > package Stacks.Implementation -- spec or body, it doesn't matter), we do > not normally need to recompile the clients. > Note the inadventant omission of the word "body" in the example. I agree, we do not need to recompile the clients or dependent children if only the implementation has changed. This is exactly my point. When the scope clause (with clause) is deferred to the package body, the dependencies are also deferred to that level. When the dependencies are at the specification level, and some specification on which there is a dependency changes, the specification does have to be recompiled. This is the point of deferring with clauses to the body. It is not about recompilation costs. It is about preservatation of architectural integrity. When any parent unit changes, there should be as few other changes as possible, especially at the architectural level. If the entire architecture is characterized by with clauses at the specification level, then the entire architecture must be recompiled, and potentially evalutated to preserve that architecture's stability. > Both ways of writing the stacks abstraction have the same property -- > the 37 clients that say "with Stacks" do not need to be recompiled when > we modify the implementation. > Agree. It is not about modifying the implementation, in Ada. The package body is unlikely to have any dependency issues in Ada. > The second example matches what is normally done in Java, except that in > Java, we wouldn't split the implementation into two parts. Note that in > the second example, that split has no value, since there are no clients > of Stacks.Implementation. In fact, in some cases, we can choose to move > all of the code from the spec of Stacks.Implementation to its body (as I > did in my P1/P2 example), making the spec empty. > I don't think so. In you example, there are no dependencies. If there were, and if those dependencies were additional children, we could certainly have issues at the specification level. In your opaque type example, those dependencies are less severe if we provide appropriate query function to ensure the client (or child unit) can query the state of the elements of a type instance during its lifetime. Whenever one unit has an existing dependency on another, a change that affects that dependency needs to be addressed. While I admire the virtues of the Interface model in Java and Ada, the dependency concerns have not vanished with the introduction of Interfaces. An Interface requires an implementation. One of its virtues is that it can have multiple implementations. Each implementation will have its own identifier. If the specification for the Interface should change, everything dependent on that interface will also change. If that change could be deferred to the implementation of a dependent class instead of the class specification, that change would have less effect on the rest of the architecture. In Ada, this is usually pretty easy. In a separate reply, you mentioned generics. In most cases, there is no reason why a generic cannot be instantiated at the package body level. Further, I am not asserting that dependencies can always be deferred. One example of this is Ada.Finalization which must be with'ed at the package specification level. There are other examples. My contention is that the Ada model of dependency management is far superior to most other models for the preservation of architectural stability. Am I alone in this view? Richard Riehle