Handling conflicting definitions
Last updated at 2:36 pm UTC on 16 January 2006
> I'm wondering if we mean two different things by this. I think it is easy to
> support the notion of a module "owning" individual methods in "upstream"
> classes, and I am in favor of this capability (though opposed to its casual
> use ;-). However the use of separate Symbol spaces is a very subtle
> technique, and one I would love to avoid in normal Squeak. The VM supports
> it, of course, and i've even considered doing it to mix ST-76 methods with
> ST-80 methods in squeak, but it's a real jump in subtlety. It IS the only way
> to deal with conflicting changes to upstream classes, but I'd almost rather
> declare it an error and fix it there than to have this kind of magic going on.
> I would like an ambitious newbie to be able to explore everything in squeak,
> without ever having to deal with this. (di)
I've thought about this since Les' posting, and I think I came up with a simple solution that avoids symbol spaces. If module M modifies upstream class C, you simply provide a different, modified class object C' to module M, where C' contains the modifications (eg. more/different things in the methodDictionary). Another module N might have C'', and this would handle conflicts.
In fact, you would do this slightly differently: if C belongs in module X, you instead make M depend on X', a "shadow" version of the whole module which contains C'. In this way you can handle conflict resolution by rather easily computing the set of modules that must be cloned.
This scheme is also good for avoiding magic, which I agree with you is a bad thing. Here, a project would explicitly say, "I use a modified version of module X, containing these changes in these classes", and this is also just what the system would give you. This is a very upfront version of conflict resolution I think. (Note that only your project's modules would be bound to this version of X).
I have also thought of a case which symbol spaces can't handle, I think. If your project modifies a base class (say, Object), all the external classes you use (say, all collection classes) should also use the modified class O', even when eg. methods refer to the original O in a method literal. This will require changing the bindings of variables (incl. globals), and this is what my scheme can handle but I don't see how selector spaces could. A big reason to use shadowing modules instead of just shadowing classes is that it becomes much easier to ensure that all references are changed as they should: it can be tricky to compute what classes need to be modified, but the same computation on modules is simple.
I still think we could wait with this feature however, but we could use simple faux classes to keep track of methods defined upstream. (hg)