[squeak-dev] Re: [ANN] Unload Traits script

Andreas Raab andreas.raab at gmx.de
Mon May 12 12:41:03 UTC 2008


Hi Matthew -

This is very interesting work. Your script presents a unique opportunity 
to actually compare the traitified version of the class kernel with one 
that doesn't have these modifications applied and compare notes 
directly. I am still in the process of doing that, but one thing that I 
almost instantly noticed was the subjective feeling that "sanity had 
suddenly returned" to a previously insanely complex part of the system. 
And I'm slowly starting to understand why that is.

Let's do a little exercise: One thing I regularly do when there are 
changes to the class kernel is to go through the main hook for method 
addition (addSelector:withMethod:) to see if there are any changes along 
the way. When you do this in the image without traits you end up with an 
exploration chain like here:

* addSelector:withMethod: has one implementor which calls 
addSelector:withMethod:notifying:
* addSelector:withMethod:notifying: has two implementors (in Behavior as 
well as ClassDescription) where the latter is basically just adding the 
SystemChangeNotifier around its superclass implementation. Both versions 
call addSelectorSilently:withMethod:
* addSelectorSilently:withMethod: has the same pattern (the base 
implementation in Behavior and an added notification in 
ClassDescription) which calls methodDictAddSelectorSilently:withMethod:
* methodDictAddSelectorSilently:withMethod: calls then 
#basicAddSelector:withMethod: which ultimately does the work.

Coincidentally, the last two methods are completely superfluous and 
could just be folded into Behavior>>addSelectorSilently:withMethod: 
(which is the implementation in 3.8).

The total number of entities to deal with in this case is seven methods 
(five if you discount the last two) in two classes.

Now let's do the same for the traits version:
* addSelector:withMethod: starts out with showing four implementors; two 
traits (TCompilingBehavior and TPureBehavior) as well as two classes, 
TraitBehavior and Behavior. The implementations look identical but it is 
not clear if they are and how one would actually find out.
* addSelector:withMethod:notifying: shows *seven* implementors; but with 
only two obviously different versions which are the ones ultimately used 
by Behavior and ClassDescription
* addSelectorSilently:withMethod: shows again seven implementor; this 
time with four apparently different implementations
* methodDictAddSelectorSilently:withMethod: shows three implementors 
with only one apparent implementation of the method
* and finally, basicAddSelector:withMethod: shows another four 
implementors with only one apparent version of the method.

Total number of entities dealt with in the process: 25 methods, 4 
classes, 3 traits. Even if you ignore those parts that aren't present in 
the first image, you still end up with 18 methods, 2 classes, 3 traits. 
In other words, the relative complexity one needs to deal with to 
perform the same task is about 3-5 times higher.

I think that's the main problem that I have with the implementation at 
hand. Any measure that I can think of to compare complexity comes up 
with at least a doubling of the complexity introduced in the class 
kernel, many of them show *much* larger increases. This is very similar 
to the issues observed here:

http://lists.squeakfoundation.org/pipermail/squeak-dev/2007-August/119295.html

where the amount of complexity explodes similarly. I'm not completely 
sure at this point whether the issues should be attributed to lack of 
tool support, or whether they are just the natural result of using MI 
inappropriately. I currently tend towards the latter because even with 
better tools significant amounts of extra complexity would remain and 
there is no real justification for the use of MI in that part of the system.

In any case, this is truly a *great* opportunity for people who haven't 
made up their mind to compare both versions directly and see which one 
they prefer.

Cheers,
   - Andreas

Matthew Fulmer wrote:
> I wrote a script that removes traits from a 3.9 or 3.8 image:
> http://installer.pbwiki.org/UnloadTraits
> 
> In an image with Installer (preferably LPF), do:
> Installer install: 'UnloadTraits'
> 
> I tested this in 3.10, 3.9, and 3.9.1
> 
> What it does:
> - Stop all trait activity
> - Recompile all classes into the old format
> - Remove all traits from the system
> - Get rid of pointers to traits or traits-related classes
> - Remove/modify lots of methods that understand traits
>   functionality
> - Unload the traits package
> - Install 3 stub methods so that Monticello versions descended
>   from 3.9 still work
> 
> This is not a modular solution, but it does make a 3.10 or 3.9
> system with no traits around anywhere, and the resulting image
> is quite stable. I don't intend to make Traits loadable right
> now, but if you want to, I can answer questions.
> 
> Have fun
> 




More information about the Squeak-dev mailing list