[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