If you're using the new Announcment's framework, you may be in for a little surprise with the latest edition (v27) in the Open Repository. Said version removes the global registry that objects can use as a "look aside" variable when they don't define their own instance variable to hold an object's subscriptions. Ultimately, I imagine this is a good thing. And it may be that no one else is really using Announcements that much. At Key, we use them a lot. We don't use any triggerEvents or change/update stuff. It's all announcements. We even figured out how to make the existing View/Wrapper/Composite framework use them. So, this has the potential to be a bit of a headache for us.
I've done my whining and am ready to move on. Ultimately I think this is a good thing. How to ease my pain of having to hunt down all the places we might do this and fix it? It started with an exploration of the MethodCollector. Basically, I'm looking for classes which have methods that send "announce:", but the only implementation of subscriptionRegistry: that will be seen is the (now defunct) one provided by Object. After some monkeying around, I came up with:
mc := MethodCollector new.
methods := mc select: (mc referencesTo: #announce:)
& (mc methodsSelect:
[:method |
(method mclass findSelector: #subscriptionRegistry:) first = Object]).
So, you can use this to look at the methods which announce: without first class support for a local subscriptionRegistry. The next part involved flattening that to the classes of interest:
classes := Set new.
methods do: [:each | classes add: each implementingClass].
classes := classes
reject: [:each | classes anySatisfy: [:other | other allSubclasses includes: each]].
If I just did the first two lines, I had 23 classes that needed to be modified! The third line trims it down by removing redundant subclasses. It got me down to 19. I must say, I was surprised about some of those 19. Some I knew were "lightweight" observables, and did not mind the "look aside" implementation. But others were heavy hitting frequently running announcers, where I would not want to pay the overhead of using the look aside.
I could go do the work of adding variables to each of those, and two methods. Yuck. Or I could do a little workspace scripting, something like:
change := CompositeRefactoryChange new.
classes do:
[:each |
change
addChange: (AddInstanceVariableChange add: 'subscriptions' to: each);
addChange: (AddMethodChange
compile: 'subscriptionRegistry: aSubscriptionRegistry
subscriptions := aSubscriptionRegistry'
in: each);
addChange: (AddMethodChange
compile: 'subscriptionRegistryOrNil
^subscriptions'
in: each)].
change inspect
This builds change object that will add the instance variable to each object, and the two support methods. By sending inspect at the end, I get a change set inspector, so that I can review them, and in a couple of cases, I chose to remove them, having a different idea about how I wanted to solve the problem.
Ain't Smalltalk cool? I don't even want to imagine the sed/awk hackery I would have to use to pull off this kind of program introspection and modification in a "non image" programming environment.
In case you're wondering why the change, in the end it boils down to a discussion that might go something like this:
Why remove the global registry?
Collection growing takes too long.
Why is it too slow?
Because we use become: to grow collections.
What's wrong with that?
Well, become preserves the subscription registries found in the global registry by swapping them.
And that's bad because?
All access to the registry is mutexed. Makes things slow, and can lead to dead lock.
Why's it all gotta be mutexed?
Because it's a weak registry.
Why?
So that people don't have to clean out their entries in the global registry. And the weak registry is thread safe too.
The whole problem is a mess. The "look aside" registry was always kind of a hack. And the notion of using identity in it. And making it weak to cover over other problems. And then there's the whole become: for collections thing. This is one step to making the system better.
I'll save Terry Raymond the comment... Traits would probably improve the situation as well. Maybe some poor tools slob at Cincom will get a chance to figure out all the issues with integrating Traits into the tools nicely.