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

goran.hultgren at bluefish.se goran.hultgren at bluefish.se
Wed Oct 24 11:34:55 UTC 2001


Hi!

Ok, now I am in trouble... :-)
Allen, I know that you have vastly more knowledge on these things than I
have so bear (is that actually the correct spelling...) with me. Ok,
here we go...

Allen Wirfs-Brock <Allen_Wirfs-Brock at Instantiations.com> wrote:
> At 09:45 AM 10/23/2001 +0100, goran.hultgren at bluefish.se wrote:
> >...
> >Object subclass: #Module
> >   instanceVariableNames: 'version parentModule neighborModules
> >definedNames exportedNames repository'
> >  ...
> 
> This apparently defines the class that is used to model a "module" that is 
> loaded into an image. More interesting would be a specification of a 
> "module" that was external to an image.  (After all, by the time you've 
> loaded a module all the interesting work has already happened). For 
> example, I'm guessing most or all of the above instance variables reference 
> other instantiated meta objects of the module system. How do those 
> translate externally?.  What is the external form of a module reference. 
> Externally, is definedNames a list of class and global names or is it the 
> actual source/object code for the defined entities. How about exported 
> names. Is it a list of strings?

Ehrm. I have no good picture of this unfortunately! I hope Henrik chimes
in.
Have you got his code by the way? I can always give you an url with the
image we used at OOPSLA.

> >...
> >- Submodule = Another module that is one of my children. Consider it a
> >"part of me". Especially note that a submodule of "me" has me as it's
> >parent. This is in contrast to the external modules whose parent is
> >someone else completely.
> 
> Note that the bi-directional linkage of submodules and parents mean that a 
> particular module may be a submodule of exactly one parent.. This would 
> seem to significantly limit the reusability of modules. This is 
> particularly a problem if you think about your modules in a context 
> external to an image. In concept a "module" could contain code that is 
> applicable in many different situations by many different parents but the 
> tight (and early) binding of the submodule to the parent means that to 
> reuse the code it will have to be duplicated within additional modules.

Well, I think I say yes and no, or something... :-)

Yes, each module has only one parent. The full name of the module is
derived from its place in the module hierarchy. And yes, that is a tree
which means a submodule only really lives in one single place.
(Sidenote: I like this. This is simple. More or less like in Java btw. A
module has a home and a name. Period.)

BUT... you can also "link" modules as an external module - didn't I
write that? Yes I did. But perhaps it wasn't clear. Or perhaps I am dead
wrong. Henrik, correct me here but wasn't the idea that if a module
needs to reuse an already existant module placed somewhere else
completely in the module tree it just references it as an external
module? I think so.


> >- Module parameter = Well, perhaps it sounds better if we call these
> >"parameter module" instead. It is an advanced feature that means that
> >the module shas a "valueholder" instead of a reference to a concrete
> >module. We then have to specify a concrete module as a value when we
> >load (or perhaps activate?) the module in question. An example would be
> >to make stuff "pluggable" so that for example you could bind another
> >"Transcript" than the standard one etc.
> 
> How would you externally represent a such a set of module bindings so it 
> can be reproducibly loaded.  You don't want to depend upon "doIts" for 
> this. Don't you need some sort of configuration module to specify these 
> bindings?

Well, I think so. This just flew by me so I do not really know. Henrik!?
:-)
 
> >- Delta module = Yes, we have discussed these in length. When going home
> >on the train last night I saw them even more clearly than before. Let me
> >explain:
> >
> >If we build a module with everything in it (classes and loose methods
> >end tutti) in a big pile we have a problem. The classes are self
> >contained, they are what they are and do not need any more information
> >to be "complete". But the loose methods (read class extensions) need a
> >"home". Ok, so we have to say what class they should go into. But then
> >we are still not clearly defined because - what version of that class
> >are we referring to? We need to say "this loose method should go into
> >class Object version 1.34" to clearly define things. So our "loose
> >changes" to classes outside of our own module needs to be complemented
> >with information about the version of those classes that they refer to,
> >right? Aha! This is exactly what the Delta modules do! They group our
> >"loose changes" that should be applied to classes in other modules and
> >complement them with information about which specific module they should
> >be applied to.
> 
> No, this is wrong!  You are binding too early and hence limiting 

That sounds bad... ;-)

> reusability. Consider the classic class extension, adding a isFoo method to 
> Object. In most cases, the extension module that defines this does not care 
> which version of Object it is extending. The same extension module should 
> be usable  by many parent modules.  When assembling a system you will want 
> to bind an extension to a particular parent, but not any earlier.
> 
> An overly constrained module system is essentially the same as no module 
> system. If every module must explicitly identify the specific versions of 
> other modules it interacts with then you have essentially gone back to 
> having a monolithic image where any change causes a cascade of dependent 
> changes throughout the system.

Ok, I see your argument. But... Hmm. The Debian package system is very
early/tight bound and it sure doesn't mean it is useless... Anyway, I
think I will pass on this one and let Henrik dive in! :-)

I need that watch that Tim Olsen (name?) has in Superman...

> ...
> >- One thing that might confuse people is that when Henrik (and I) says
> >"module" he means an exact version of a bunch of code. This means that
> >"Morphic 1.23" is ONE module and "Morphic 1.24" is ANOTHER module. In
> >ordinary speech we sometimes talk about "the module Morphic" talking
> >about all/any version of that stuff. This is a naming problem and
> >perhaps there is a better word for "Module" that we should use... A
> >deltamodule is always in reference to a specific module, for example
> >"Morphic 1.23". So when a module has been "published" it should never
> >ever change content of course.
> 
> Most systems would make a terminology distinction between a logical module 
> and a particular "version" of the module. Common terminology would be 
> "module version", "module revision", "module edition", etc. It's would 
> certainly help communications, to choose a term and then to be fastidious 
> in making the distinction.

Ok, I like "module revision" or "module version". In the Smalltalk world
the word "edition" and "version" might be tainted by earlier products in
such a way that we should perhaps stay clear of them. And the word
"revision" is used in CVS but the meaning there is probably intuitive
enough to not be a problem.

I vote for "module revision" meaning "one specific version".
And when we say only "module" we should always mean the logical module.

Agreed? :-) (pretty, pretty please...)

Perhaps we should then rename those classes to ModuleRevision etc...

> >- A Deltamodule inherits from Module and this could perhaps be
> >refactored with a common baseclass as is common in the Composite pattern
> >but I haven't looked into that issue. One fact though: Looking at the
> >code a Deltamodule CAN NOT have neighborModules. Those methods are
> >overridden. So, a Delta module can only be a leaf in the Module tree.
> >Henrik, what about applying the Composite pattern here? Or are there
> >other considerations?
> 
> Why the restriction on neighborModules?  This would seem to imply that a 
> class extension may not reference any classes (or globals) that are not 
> already known to the parent. This would seem to extreme limit the use of 
> deltamodules.

Ah, I checked the code! :-) Well, a Deltamodule can not HAVE neighbors,
instead it defines CHANGES to it's basemodules neighbors. So I think
your guessed implication is not valid. Phew. :-)

> >...
> > > Eh, well since a Deltamodule defines a difference between two modules it
> > > should be able to contain a whole new class. But you would probably
> > > rather seldomly have one Module add classes to another module so it will
> > > probably be a rare case.
> > >
> 
> Again, this seems like the common case, not the rare case.  The module that 
> defines the Foo class also wants to add the isFoo method to Object and 
> possibly other classes.

Really? When you write "and possibly other classes." did you mean "and
add possibly other classes." or "add the isFoo method to possibly other
classes."?

It doesn't seem common to me that the module Morphic typically would add
classes to the module Collections (or any other module), methods
certainly probably all over the place but new classes in OTHER modules?
Don't really buy that. Convince me! :-)

> >...
> >Ok, so revising it a bit further (leaving out module parameters):
> >
> >- A Module contains global definitions including classes and can contain
> >other modules and Delta modules creating a tree.
> 
> As explained above, it's not a tree -- it a cyclic graph!

Yes, my threeliner tried to be "pedagogic" in the sense that the first
line establish the module tree and then I add the fact that there are
also crossreferences making it somewhat "graphish", but still - those
references are notably different.

Perhaps we should try to revise the threeliner even further then
(leaving out "module parameters" and changing "module" to "module
revision"):

- A Module revision contains global definitions including classes and
can contain
other module revisions and Delta module revisions creating a tree.

- A Delta module revision can only be a leaf in the module revision tree
and defines the
difference between two Module revisions. (changed methods, added
methods, added
classes, removed methods or classes etc.)

- A Module revision also references so called external module revisions
(used module revisions) outside
of it's subtree. This enables reuse of module revisions across module
revision tree boundaries. This actually turns our simple tree into a
cyclic graph but do note that a module revision still only has one home
(=one parent module revision) in the tree.


I skipped the part about "name lookup" etc since it hopefully is
implicit in the word "used". Henrik likes the word "external" meaning
"outside of my own tree". "Used" doesn't really imply that but I find it
more telling.

 
> >- A Delta module can only be a leaf in the module tree and defines the
> >difference between two Modules. (changed methods, added methods, added
> >classes, removed methods or
> >  classes etc.)
> 
> So to create a delta module you first must have two "editions" of a module 
> and the creation process creates a third edition of the module (necessary 
> to contain the child extension reference) plus an extension module?

I think you lost me there. As it is meant to work now (I think) is that
when you change a class in a different module than your "own" (that you
are working in - think "current module" like in "current changeset") a
delta module revision is created and added to your own module revision.
Any other changes after that in that same other module will also end up
collected in this delta module revision.

This delta module revision is also (mostly I guess) activated from the
start meaning that the method just added is actually there able to run.

This was probably not an answer to your question...

> 
> >...
> >Obviously the Delta modules are the tricky part - but personally I just
> >view them as a "diff" between two modules. I do have a question to
> >Henrik though - the deltamodule refers to the baseModule that is applies
> >to but it doesn't refer to the resulting module when it has been
> >applied. Ok, I admin that the last sentence sounded strange, but let me
> >put it like this: When Delta module Z has been applied to "Morphic 1.23"
> >I can't really say if the result is "Morphic 1.24" or whatever? The
> >source is defined but the target is not. So... I am not even sure if
> >that is a problem, but perhaps it can be? When it comes to conflict
> >detection I mean. Whatever...
> 
> Since I've been throwing stone I should also offer a solution.  I think 
> what you need to decouple extensions and parents.  You can do this by 
> introducing a new module type, call it an extended module. So, instead of 
> defining Module "Morphic 1.23" that must explicitly include module "Z 4.56" 
> (and which must explicitly say it extends "Morphic 1.23") it would define 
> the extended module "MorphicWithZ 1.0" which includes as children "Morphic 
> 1.23" and "Z 4.56"

I am sorry, my brain is turning into jello here. I can't give any
sensible response.

But I can try to clarify my little question:

Currently a delta module revision exactly specifies a new revision of
another module revision.
It does this effectively by definining a bunch of differences that
should be applied to the specifically named module revision. So... delta
module revision "Z 1.0", which is actually my improved homehacked
version of "Morphic 1.23" includes a reference to "Morphic 1.23" and
then a bunch of changed methods, added methods etc.

Loading and activating "Z 1.0" will also load and activate "Morphic
1.23" and then apply all those changes to it.

Now, back to my question: What is now the activated revision of Morphic
called? It is not 1.23. And the delta module doesn't say. It's like an
"open edition" in ENVY (or whatever they are called) that hasn't got a
revision number yet. And more importantly - is this a problem? Perhaps
it's just fine, I can't see the implications.


> >...
> >regards, Göran
> 
> Final thoughts.  I would expect a module system to support two major goals:
>          1) Reusability of modules
>          2) Reproducability of system configurations.
> 
> These goals might appear to be conflicting but need not be. However, you 
> have to be very careful in designing a module system to not achieve one of 
> the goals at the expense of the other. My sense is that the design 
> decisions in this system that support goal 2 will severely interfere with 
> goal 1.

Well, let us bounce this around a bit first and let Henrik explain it a
bit further - my impression is that he has given all this a lot of
thought and also read up on the problems too. He has also studied Ginzu
in some extent. So I have faith that it isn't as "bad" as it looks when
I try to explain it! :-)

> Allen

Thanks again for your input in this, we greatly appreciate it. And just
mail me if you want the image that circulated at OOPSLA.

regards, Göran




More information about the Squeak-dev mailing list