DeltaModules vs Envy/Ginsu Class Extensions (was Re: Squeak Starter)

Doug Way dway at riskmetrics.com
Sat Oct 19 07:15:54 UTC 2002


Ned Konz wrote:

>On Friday 18 October 2002 07:36 am, Roel Wuyts wrote:
>  
>
>>Stef has this kind of setup in mind, and in that setup there is no
>>difference between modules and delta-modules. A module is something
>>which has definitions and which you can apply on a system.
>>
>But that (a simple declarative system) not sufficient to do what we 
>want to do with the system. There has to be a way to remove an 
>existing method (at least for your code).
>
>So unless you effectively define an entire module which consists of 
>the original module MINUS the method, you don't get the behavior you 
>want.
>
>I _think_ the DM's are a way to do this kind of specification: "this 
>is a module just like module X but with this removed, this added, and 
>this modified".
>
Okay, this is getting into a difference between these two approaches 
which needs to be fleshed out some more (and which I'm somewhat familiar 
with, at least :-) ).

With Envy/Ginsu-style modules (which I assume are similar to what Roel & 
Steph are talking about), modules can contain classes, and can also 
contain "Class Extensions" (a.k.a. loose methods).  I would define Class 
Extensions as methods which are additions to classes in other modules, 
but they are ONLY additions, NOT changes to existing methods (and not 
removals either).

DeltaModules, on the other hand, can contain method additions, but also 
changes to existing methods and method removals too.

So, to generalize a bit, DeltaModules are more powerful, but Class 
Extensions are quite a bit simpler.

Let's think about a couple of useful properties of modules:

1. Can they be cleanly unloaded?
2. Are they behavior-preserving?  In other words, if you load (and 
activate) a module, will the rest of the system still run without 
breaking or behaving differently?

Regarding #1, 3.3a-style Modules and DeltaModules can be unloaded, and 
Envy/Ginsu-style modules can too, so no problems there.  Changesets 
cannot be unloaded, which is their big limitation.

Regarding #2, this is one reason for the split between Modules and 
DeltaModules in 3.3a.  If you load a Module (with no DeltaModules), the 
rest of the system will be unaffected, so they are behavior-preserving. 
 DeltaModules are not behavior-preserving, but that's the point of 
them... they can be used if you do need to change something else in the 
system.

Because DeltaModules are not behavior-preserving, they naturally have to 
change version numbers of the Modules that they modify.  So for example 
if a WebBrowser Module has a DeltaModule which adds the method 
#asEncodedHtml or changes a method in class String, in the Module 
"Kernel 2.7", the Kernel module will need to be assigned a new version 
number such as 2.8.  (I believe this is how DeltaModules are supposed to 
work, correct me if I'm wrong.)  This may have big implications for the 
rest of the modules in the system, which might expect to run on Kernel 
2.7 but not know about 2.8.

But the interesting thing is, Envy/Ginsu-style modules w/Class 
Extensions *are* behavior-preserving, with a few caveats* (see bottom of 
message).  This is because, in general, if you add a new method to an 
existing class, none of the rest of the system would ever send that new 
method, so the behavior of the rest of the system is unchanged.  So, 
reusing the example above, if a WebBrowser module has a Class Extension 
which adds the method #asEncodedHtml (but does not change any method) in 
class String, in the module "Kernel 2.7", the Kernel module will still 
remain 2.7.  (This is exactly what Envy does.  I don't remember now if 
Ginsu supports version numbers.)

The other question is then, if we're using Class Extensions, is it good 
enough to only be able to *add* methods to classes in other modules, not 
modify/remove them (as DeltaModules can do)?

Well, I guess that's a big question. :-)  I would say that most of the 
time, yes, it's good enough.  A module does not often need to 
change/remove methods in other modules, unless we're directly fixing a 
bug in that other module.  Adding methods is much more useful, and can 
be specific to the "outer" module (such as the example WebBrowser module 
adding #asEncodedHtml to String).  People who've used Envy know that it 
can be very handy... although you don't want to abuse it to an extreme.

With Envy/Ginsu, if your module *really* needs to change/remove a method 
in Kernel 2.7, you make your own private version of Kernel 2.8 with the 
change, and/or you lobby the maintainer of Kernel to make the change. 
 But this should be relatively rare aside from bug fixes.

On the other hand, the ability of DeltaModules to handle method 
changes/removals could be quite nice.  And they seem a bit more 
rigorous, no "caveats" as with Class Extensions below.  And namespaces 
are already built-in.  But there is extra complexity cost...  For 
example, DeltaModules have to worry about activation/deactivation, with 
Class Extensions it is irrelevant.  The Class Extensions are always 
active when the module is active, since they don't affect anything else.

One last thing: As far as splitting up the current Squeak image into 
modules goes, my hunch is that it would be easier to do with 
Envy/Ginsu-style modules.  This is because you would not need the 
DeltaModule capability of specifying changed/removed methods when 
divvying things up, only the ability to specify added methods, which the 
lighter-weight Class Extensions can also handle without version number 
worries.  For example, String>>asMorph could be quickly dumped into some 
Morphic module.

(Avi, are the DVS "logical modules" similar to Envy/Ginsu with Class 
Extensions?)

Am I making sense here?  This message is getting too long, sorry.  Let 
me know if I've characterized one of the approaches incorrectly.  And I 
know this is only one aspect of the differences between these two module 
systems.  Anyway, I've often found that I learn more by see two things 
compared against each other, than by seeing them described separately.

- Doug Way
  dway at riskmetrics.com



*Caveat #1: There could be namespace conflicts with Class Extensions, 
which Envy/Ginsu don't handle.  I'm guessing that adding namespace 
support is one thing that Roel & Steph were working on?

*Caveat #2: Ideally, to preserve behavior, you would not allow a Class 
Extension to override a method in a superclass.  This would be a simple 
restriction to add.  Otherwise, you could bring an image to its knees by 
adding a new method #size to SortedCollection which returns nil. :-)

*Caveat #3: If a base module class is doing something funky with 
reflection such that adding a new method changes its behavior, then the 
Class Extension might not be behavior-preserving.  But this falls under 
the category of Very Rare, IMHO.  (I guess an example might be adding a 
testXXX method to an SUnit test suite class.)
 




More information about the Squeak-dev mailing list