[ENH][Modules] Delta Modules [was: Another version]

Henrik Gedenryd Henrik.Gedenryd at lucs.lu.se
Mon Oct 8 13:16:52 UTC 2001


I have been out of town for a few days without email, this is why I haven't
been able to answer before.

Andrew P. Black wrote:

> DeltaModules are a kind of Module[2].  They are distinguished from
> base modules by being defined by difference.  ...
> So, my question is: why do you consider DelatModules as being
> conceptually different from Modules at all?  Why do they have
> different properties, just because they happen to have a different
> representation? ...
> Why do DeltaModules and Module not have identical
> protocols?  Why are DeltaModules and regular Modules not just tow
> implementation classes with the same interface?

You are right: My specification of DMs was unclear as well as unfinished,
but I wanted to put it out early along with the code.

It did mix the implementation aspect with how DMs would be used, in the
manner of "here are some problems, and this is how DMs can address them".
The implementation difference is not strictly linked to the uses I
mentioned, but in practice there will be such a link: the convenience of the
delta representation means that class extensions probably will be put in DMs
99% of the time, and so on. But I know it may have looked like there was a
harder link there. (I hope this answered your policy vs. mechanism point as
well, otherwise let me know.)

You are also right in that the differences between regular and delta modules
should be as small as possible, and that we should be specific about what
they are. However, the two cannot be identical: a DM needs to be defined
relative to a base module, and the concept of a base module is meaningless
for a regular module. This ought to be the only real difference. Then we may
want to have some tool-like support for viewing DMs in terms of differences
wrt the base module, but those are minor issues.

I think that this situation between Modules and DeltaModules is rather
common in class/subclass relations, and I think your question can be
understood by analogy to other known cases: why aren't the protocols for
Array and OrderedCollection identical, and so on. It is because they are
very similar but still slightly different.

The result of activating/installing a DM is equivalent to creating a
new/different version of the base module by filing in all the contents as a
regular Module. (I now think that de/activating a DM is a better term than
un/installing it.) You aren't forced to use DMs for class extensions, but
filing in five new methods is clearly more convenient than loading a new
version of the whole module that contains String.

Activating a DeltaModule does not modify its base module--it creates a new
version of the base module, with the modifications installed. Being able to
modify a module is a bad thing since different code packages should be able
to specify a module by version and be able to rely on its contents. But this
distinction is a technical detail.

ducasse stephane wrote:

> I have mod1 with extensions (DM1) = String>>asUrl
> 
> can I see String>>asUrl from mod2 if there are not relations between the
> two?
> 
> I have the intuition that I should only see asUrl from a module only if this
> module depends from mod1.
> 
> What is your point of view on that?

There is a short answer to this: Yes, that was just how I intended it to be.

More precisely, when the DeltaModule containing your extensions would be
made active, this would create a new, modified version of the base module
with the changes installed into it.  If mod2 wouldn't specify a particular
version of the modified module, then it might use the new version as well,
but if it specifically wanted the old version then it wouldn't see the
changes.

If two different loaded systems want to modify the same module (the same
class/es), then you need to switch between the two module versions created
by the modifications--you enter into the area of conflict resolution.

Andrew P. Black wrote:

> I understand that "DeltaModules can be un/installed, but the
> un/install operation has no meaning for regular Modules" [1].  My
> question is: Why.  If un/install is such a good idea, why not have it
> for all Modules, not just for DeltaModules?

The reason is that Modules are independent and self-contained, and therefore
cannot be in conflict with each other. However, several packages may want to
apply DMs to the same module, and then there is a use for being able to
de/activate all but one of these DMs.

But while you could have two versions of Morphic loaded at the same time,
with no conflicts since they would be two different modules, you can't have
both running at the same time. E.g. who takes care of input events? But this
is not a conflict on a module level (which just defines code), but on a
component level (i.e. between parts of the system that are running).

> I just put my "loose
> methods" (like String >> asUrl) into a DeltaModule inside my Module,
> and the unsuspecting user who imports my module is still surprised
> that it "damages" other classes like String, or Form, or whatever.

I don't agree at all. DMs not only collect all external modifications in a
special place, instead of mixing it with the "proper" contents of your
module. They also associate such modifications with the modules where they
are made, so that you by looking at the list of delta modules can see
exactly what parts of the system a certain package modifies. Any
"unsuspecting user" would most probably look at what parts of the system a
module modifies before they use it. In this way this is made easy. Can you
suggest any way to make it clearer?

This also serves to make it very clear to a conflict resolver in what parts
of the system conflicts arise with other loaded packages: conflicts need
only be handled in those modules where multiple sources want to have
modified versions of the same module.

> Now, I had assumed up until this morning that a Module could contain
> not only whole classes, but also "class extensions", that is, groups
> of methods that could be added to existing classes, even though those
> classes might be defined in different modules.  (The String>>asUrl
> example again, which I had assumed could be part of the HTML module).

But the very purpose of modularity is to separate a system into smaller,
independent, self-contained pieces, whose definitions are not entangled in
each other. Modules really should not be allowed to modify the contents of
other modules. Allowing this would go against the very idea of
modularity--it is really a contradition in terms, more or less. It is the
same violation as if an object would be allowed to directly alter the
innards of another object, it breaks encapsulation.

>> A module
>> * will of course also have contents proper: classes, globals, etc.
> 
> I notice that "proper contents" does not include methods.  Is this
> intentional?  Is this a mechanism restriction that is intended to
> make it hard for me to put the "wrong stuff" in my module, that is,
> to put in "loose methods" that change some other classes?
...
> If so, I admire 
> your good intentions, but I think that you are misguided.

This is just because in ordinary Smalltalk you don't put methods anywhere
except as part of classes, this just follows that principle. You may
consider Smalltalk to be misguided when it enforces this principle, and
would then regard C++ as superior in this respect, but many would consider
this part of the essence and elegance of Smalltalk.  #Smalltalk contains
classes and other globals, but not loose methods, it's the same thing with
modules. In fact, neither DMs contain loose methods, they are put in class
objects too, at least as it is now. In fact it would be more work to support
the kind of exception you suggest, than to simply put methods in classes
like now.

Dan stated earlier that while method extensions may be supported, they
shouldn't be encouraged (something to that effect), and I agree, since it
breaks the above principles. I see it as a kind of emergency solution or
exception, a concession to realities, it is never strictly necessary I
believe--although I don't want to repeat the {} discussion here.

> Now I see that I might be wrong about this, and that Andreas' point
> of view would say that Modules shall contain _only_ whole classes,
> and DeltaModules shall contain _only_ class extensions and perhaps
> class retractions (deleting methods).

Since DMs are defined as differences in relation to a base module, per this
definition (and for superseding change sets) they strictly ought to be able
to define any possible differences in a module, however some changes are
harder to support than others. Still, adding new classes should definitely
be possible, and it is easy to support (DMs being Modules, I think they
already do). But this would probably be used when DMs are used in the role
of change sets--a package will rarely need new classes to be added to other
modules.

> The email of yours in reply to Michael Rueger also said a lot of
> interesting things about modules being namespaces (not stated on the
> Wiki) and that these namespaces do not follow the hierarchic
> structure of the module nesting (not on the Wiki either).

In both cases, the information on how names are looked up was in the first
posting I made, and was copied into the first heading listed on the Swiki,
"design principles". However, Smalltalk is the only language I can think of
where different modules share a single namespace, so I may not have made it
as clear, taking it for granted. Again, it seems to go against the very
principle of modularity, where modules' contents should be independent per
definition. So I've been taking this feature for granted whereas all
Smalltalkers obviously don't.

> The distinction between BasicModules (as I shall call them) and
> DelatModules as I now understand it is:
> 

As I said above, it now seems clearer that the only difference ought to be
that a Module is self-contained, whereas DeltaModules are represented as
differences wrt a base module. However, this apparently small difference
will lead to great differences in usage patterns.

> *  BasicModules can be used only to define whole classes, whereas
> DeltaModules can be used only make additions, removals or changes to
> classes that are defined elsewhere.

Regular Modules should be complete and self-contained, as per the definition
of modularity, with e.g. complete classes, as usual in Smalltalk.

DMs should in principle be able to handle all possible differences wrt a
base module: new items, deletions, and changes.

> *  BasicModules can contain (sub) BasicModules, global specifications
> and Class specifications, but not DeltaModules.

Regular Modules can be linked to any other Module, regardless of their kind
(of course). PackageModules etc. are unnecessary.

> *  DelataModules can contain (sub) DeltaModules and change
> specifications (but not BasicModules)

A DM really ought to only specify changes to the contents, and not itself
have any submodules. If your system X modifies module A and A's submodule B,
then X should have one delta module DM(A) and one DM(B), this is for
clarity, in this way you clearly see what parts X needs to modify.

Henrik






More information about the Squeak-dev mailing list