Squeak SmalltalkJoker Squeak Smalltalk : Philosophy : prevnext Modules 1

It seems to me that part of the problem with these discussions of modules
is that nobody has been terribly clear about what they hope to get out of
them.  Perhaps if we make our goals clearer, it will be easier to talk
about the possible solutions.  Here are a few things that I would think a
module system might provide:

1. A way to specify related pieces of code.  This has to
include both entirely new classes and patches/additions to existing
classes.  Let's call these "packages".
2. A way to easily save and load these packages to and from easily
distributable files.
3. A way to cleanly update an image with a new version of a package.
4. A way to cleanly unload a package from an image.
5. A way to analyze dependencies between packages.
6. A way to specify dependencies between packages.
7. A way to protect packages from name clashes.
8. A way to organize packages hierarchically.

IMO, 1-3 are the most important.  Not surprisingly, these are also what
DVS mostly provides, although it works better for straight additions to
existing classes than for patches to them.  The interesting thing is that
this can be provided without any changes to the base image, as a simple
addon package.

4, I think, could also be done fairly easily on top of 3.2, but it seems
much less important to me: once I've loaded something into an image I
rarely want to remove it.  If I'm testing a new package, I use a throwaway
image.  I guess that assumes a minimal base image to load things into.

Daniel has already done 5, again in 3.2.  I don't see why 6 would be very
difficult - it ties into what Daniel and I were talking about with
subclasses of Module to store metadata.  6 also seems like something that
SqueakMap might be extended to do.

7 is, of course, the big one: it is the real justification, as far as I'm
concerned, of the work that's beem put into 3.3a.  But how big a deal is
it?  Are people routinely struggling with naming conflicts?  I tend to
throw a 2 letter prefix in front of my class names and forget about it.
But maybe that's just me.

8 would be nice, but the major benefits (being able to load/unload groups
of packages at once) can be gotten through dependecies + dummy packages,
the same way most of the linux packaging systems work.

This is a highly personal take on things, of course - I'm not
pretending that these preferences will be the same for everyone.  I'd
be curious to hear what, for example, Stef's or Henrik's version of
this list would look like.  But me, I'd rather see a lightweight module
system in 3.2 without namespaces or hierarchy get widely used first, and
then start to think about the full Module system a la 3.3a.

a) a Module is a bunch of classes (globals) and you need to explicitly
"import" the other Modules that you use in your Module. Very similar to
import/include in all the {}-languages.
b) The Modules are arranged in a global namespace hierarchy. Very
similar to Java.
c) The only thing remotely hard to understand here is IMHO DeltaModules
and they are more or less like a ChangeSet that *only* affects one given
Module. Another way of saying this is that a DeltaModule D specifies the
difference (like a patch-file) that needs to be applied to a Module A
version 1.0 to turn it into version 1.1.

DeltaModule
It has two very nice consequences:
1. Modules (regular ones) could then simply be a bunch of classes.
Period.
2. Any "changes" needed in other code to make a Module happy where
collected in the DeltaModules. This meant that the DeltaModules carried
all the "dirty tricks" and made them visible and concrete. This is a
good thing.

And finally, since a DeltaModule essentially is the a "cleaned up"
version of ChangeSet we could use it for those purposes too. Remember
that a DeltaModule is reversible - this is a very important thing to
have. According to Henrik (I haven't looked at them much) ChangeSets are
pretty weird beasts

Hierarchical view of modules
The hierarchy (currently) has two purposes:
1. A hierachical naming space makes finding stuff easier. Nothing
technical about that - it's just nice to have it hierarchical.
2. Since we then suddenly have a hierarchy we can choose some meaning to
attach to the child-relation (or we could choose not to - but why not?).
IIRC some operations work on a Module recursively.
Loading/unloading/activation/deactivation to be precise. But apart from
that I don't think the child-relation has any other "role" in Modules.

Personally I think we could perhaps let the operations mentioned
(loading/unloading/activation/deactivation) instead work only through
the dependency graph and simply ignoring the child-parent hierarchy. I
think Stephen Pair has made that proposal earlier. This would leave the
hierarchy as being only for naming.

A DeltaModule is more or less like a ChangeSet. And as you know this
means that:

1. It can contain loose method additions/removals.
2. It can contain class definition changes like variable
additions/removals, superclass changes etc.
3. It can contain complete additional classes.
4. In fact it can contain any conceivable change to a Module.

(the above might not be implemented yet, but this is the plan/design)

The whole point of the DeltaModule is that it contains all changes you
would like to do to *another* Module that is not yours in order to make
*your* Module happy. So think of it as a ChangeSet with the restriction
that it can only change *one* Module. And then add the very important
aspect of reversability. A DeltaModule is activated and deactivated -
when it is activated its changes are applied and when it is deactivated
the changes are removed.

So again, what are the nice properties of this scheme?

1. A Module is thus tremendously simple. It is just a bunch of classes.
No history, no additions/removals or anything - it is very much like a
category .st-fileout. It can't get simpler than that, and simplicity is
our friend.

2. A Module can't possibly conflict with another Module since it is in
it's own namespace. This is a very important aspect. You can load all
and any Modules into the image without any worry whatsoever, after all
it's only classes and simply filing in classes never hurt anybody
(unless the class initialization does dumb things, but that is another
story).

3. As we all know somewhere the "dirty business" must be taken care of,
otherwise all these Modules turn into isolated islands of no connection
at all and just sits there like dumb ducks. :-) And this is the job of
the DeltaModule. Think of it as a ChangeSet which can be reverted
(activated/deactivated) and that can only affect ONE Module. Since
DeltaModules carry all your changes in Modules that are not your own
they by definition contain the areas of your code that CAN conflict with
others.

So - the separation is very clear to me. When I write code everything I
write can be separated into two groups:

1. My own classes.
2. Changes in other peoples classes.

Voila! Modules and DeltaModules. Since I control my own classes I can
represent that code as a snapshot of the classes. But I don't control
other peoples code so those changes are best represented as *recorded
changes* to those classes.