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
|