[Modules] A proposal for Modules, Packages and Dependencies
Allen Wirfs-Brock
Allen_Wirfs-Brock at Instantiations.com
Wed Aug 22 20:02:35 UTC 2001
Henrik Gedenryd presented a well thought out spec for a module system with
strong support for specify module interdependencies. It's a proposal worthy
of serious consideration.
Les Tyrrell articulately expressed his concerns that Henrik's proposal
would unnecessarily constrain the way that modules can be used.
From my perspective, they both have very valid points. This disagreement
is a reflection of the tension between the goal of maximizing flexibility
(reusability) and the goal of ensuring correctness. This tension exists in
every such system. Let me give a simple example of what I mean:
Assume we have some code that includes a statement like:
Transcript show: "my message";cr;
In Henrik's proposal, that code would exist in a module (let's call it
module X) that presumably would have to have an import statement something
like:
self uses: #(SqueakTranscriptModule) "I don't really understand
the syntax, it doesn't matter"
in order to make the global, Transcript, available for use from the
module. The problem, is that as soon as you do this you have constrained
Module X to only be used in conjunction with SqueakTranscriptModule. If
there were others modules that implemented and exported Transcript (let's
say a LoggingTranscriptModule or a RemoteTranscriptModule) Module X could
not make use of them. So, with this scheme we have lost flexibility in the
use (or reuse) of Module X but we have gained a degree of confidence in the
correctness of our program because we are ensured that Transcript is being
defined by the module that we intended (as presumably tested against).
In Team/V we tried to solve this problem by using two orthogonal artifacts:
packages and clusters.
Packages are code modules, they contain class, method, global variable, and
initialization definition. They do not have export, imports, or any other
sort of explicit dependency specifications. Basically, they just contain
code fragments. If you expressed the above example as a package there would
be no explicit constraints on its use. The package could be used in
combination with any other package that defined Transcript. However, if you
(or the development environment) looked at Package X you would find nothing
that told you what other packages might need to be loaded along with it.
Clusters are simply lists of packages (or other clusters). A cluster is a
specification that all of the listed packages must be simultaneously
present in an image. Cluster can be externally stored and versioned, just
like packages. Since clusters may reference other clusters you can build up
arbitrarily complex structures. Using clusters and packages you can get the
effect of Henrik's module by defining a cluster like:
Cluster X = {PackageX SqueakTranscriptModule}
Then, if you loaded Cluster X, both PackageX and SqueakTranscriptModule
would get loaded.
You can see, that there is also a trade off between simplicity and
complexity going on here. Henrik's solution is simpler as it only has one
kind of artifact, modules, to deal with. Team/V is more complex as it has
two kinds of artifacts, packages and clusters. Is the increased flexibility
worth the added complexity? We thought so, but others might disagree.
I've though a bit about, how this issue might be resolved in the context of
Henrik's proposal. The first thing that comes to mind is to (optionally?)
separate the actual code part of his module into a separate entity (a
package?). Then the module would provide all the structure information but
the package could still be used independently to create modules with
alternative structuring.
A few somewhat tangential thoughts:
This dichotomy between explicit vs implicit module dependency relationships
feels to me very similar to the dichotomy between static and dynamic
typing. There are good arguments on both sides of the typing debate but
Smalltalk has chosen (rightly so, I believe) to exploit the flexibility
that comes from dynamic typing. Why shouldn't Smalltalk also favor
flexibility in the module context?
Someone might argue that in my Module X example, I was misusing "modules"
by trying to achieve a degree of "pluggability" that would be more
appropriately achieved using "components". Given an adequate component
model, they might convince me they were correct.
In response to an earlier message of mine about the separating
configuration information David M. Siegel commented:
At 04:51 PM 8/19/2001 -0700, David M. Siegel wrote:
>>Alternately, you can separate the configuration information from the
>>modules. So M1 and M2 would be defined as:
>> M1 (v1.5) = {requires M3 ...}
>> M2 (V9.8) = { requires M3 ...}
...
>Aren't you assuming that module signatures are constant?
>
>In actuality, new versions of Modules will include new selectors and new
>classes, and will remove
>old selectors and old classes.
David's answer is above. I really wouldn't have the "requires" clause at
all. It was just there to illustrate the problems with embedded version
information.
Allen
More information about the Squeak-dev
mailing list
|