Daniel Wengelin wrote to Team-Ada:
> I am contemplating transitioning a system in Ada83 to Ada95. Our current
> implementation uses a programming environment that supports "export sets"
> from components, i.e. the ability to define for a given software component
> (CSC, say 10-50 kSLOC) the package specifikations that are allowed to be
> "with"ed from another component.
> In Ada95, this ability was added to the language itself, using visibility
> of child packages as the means to define the export set of a component.
I read this idea with great interest. All the presentations/discussions
on child packages that I have heard seem to approach the feature in a
top-down fashion: for example, you've already got an existing package
that you want to extend or enhance, but would also like to leave it
intact (because it's been shipped to customers, or you don't want the
recompilation impact, or whatever); so Ada95 lets you attach child
packages and thus achieve both goals. The Message: child packages are
for extensibility (although the Ada95 Rationale also discusses sharing
of private types as another primary use).
But the above idea fascinates me because it suggests an additional/new
bottom-up applicability: for example, you've already got an existing
collection of packages (logically a CSC) of which only a specific few
are intended as the CSC interface; but as they stand, there's nothing in
the language to prevent a client from bypassing the CSC interface and
WITHing disallowed internal specs -- either ignorantly or intentionally
(such as for performance reasons). To enforce the intended design, we
need to have a vigilant architect or external tool/environment support
("export sets"). Happily, the above suggests that the language can
address the issue after all: create a "super-package" or "root" that
subsumes the CSC interface packages as its children. As Tucker Taft so
nicely explained it:
> it can be done
> pretty straightforwardly. The fundamental rules are that
> a private child cannot be "with"ed outside the "subsystem"
> rooted at its parent, and cannot be "with"ed by the spec of
> any unit visible to "outsiders."
> A "subsystem" is a tree of library units headed by some particular
> library unit.
> Another way of looking at it is that a subsystem can be divided
> into two parts: the part visible outside the subsystem (the "interface"
> to the subsystem), and the part visible only inside the subsystem
> (the "implementation" of the subsystem). The interface consists of
> the specs of the root of the subsystem and its public children,
> grandchildren, etc. The implementation consists of the
> specs of the private children/grandchildren, etc, plus all the bodies.
> Something outside the subsystem, or something in the interface of the
> subsystem, may not "with" something in the implementation.
Regarding the "export set" alternative, Steven Deller wrote:
> Only if there is ONE top level package would Tucker's solution apply. In
> most cases I have seen, this is rarely the case.
> Now one could consider creating a super-package containing all the parent
> packages, but that would change all points of usage -- something I would not
> think desirable.
Any existing points of usage would indeed be impacted (as would the new
child packages themselves) -- future points would not, by definition.
The original posting asked whether it was "possible to transform the
Ada83", so immutability of existing code is not a constraint here. Where
it is a constraint, then the "export set" solution does the job well;
but if we are willing to transform (dare I say "refactor"?) the code,
the result is *extremely* desirable: language-based enforcement of the
CSC-level architecture! ... and the actual editing is relatively minor.
> It is my personal feeling that Rational's subsystems addresses a different
> control issue than Ada 95's parent/child package system. I would suggest
> that Ada 95 child/parent packaging be used for encapsulation and hiding of
> implementation details for a parent package that needs subpackages specific
> to its implementation.
This is the top-down extensibility usage discussed above; but the
insight here is that child packages can also be applied in a bottom-up
fashion to address the very real issue of maintaining architectural
integrity -- and so can Rational's subsystems and their "export sets".
> Conversely, Rational's export control mechanism is appropriate for
> controlling exports within a subsystem of communicating "peer" packages in
> which only some of the communications should come from outside the
Of course, that peer relationship would be preserved among the newly
subsumed children as well.
> Thus I would think there would be some cases in your application where Ada
> 95's parent/child packaging would be appropriate to maintaining the
> integrity of your system, and some cases where Rational's subsystem export
> controls would benefit your system integrity.
I don't think the original goal was to duplicate Rational's "export set"
capability: clearly, the two approaches will manifest differences. For
the problem at hand, both approaches will serve admirably well; ... but
for the sake of clarity, it might be worth articulating just what some
of these differences are (at the risk of changing the subject -- not my
intent! -- but do correct me if I'm mistaken).
* A given Rational subsystem can support *multiple* independent "export
sets", that is, the same collection of packages (of a CSC) can be viewed
(WITHed) differently by different clients. This nicely supports CSC
variants, such as for different target platforms/domains. In contrast,
the equivalent with bottom-up child packages (as discussed) would be to
have interchangeable "roots" (one per variant), each of which could
share many/all of the children -- prohibited by Ada's strict hierarchy.
(Of course, Ada can deal with variants by other/better means.)
* On the other hand, Rational's subsystems cannot be nested (at least in
current implementations). The bottom-up child package approach, however,
would easily and directly support nested CSCs.
> Forcing either mechanism to do the work of the other may work against any
> improvement of system integrity -- essentially make work for no or negative
Correct! And bottom-up child packages as a refactoring strategy for
language-based architectural enforcement is an idea that should be made
more widely known, IMHO :-)
C. Daniel Cooper ==========v=================v=======================v
Adv Computing Technologist | processes | All opinions are mine |
206-655-3519 | + architectures | and may not represent |
[log in to unmask] | = systems | those of my employer. |