This story occurred at a client of mine, I tend to think it separates masters from gurus I was introduced to an application that a novice Smalltalker had written, there was odd things happening. Not badly written, but I soon tripped over a bizarre problem. After I had placed some self halts in the code I was confused. It seemed that the instance variables I saw didn't match my knowledge of the classes. It's early in the morning and (A) you didn't know the application, and (B) the inspectors were lying, or were they? Grumble Grumble, so I went and made a class definition change. Then boom! Up poped a notifier saying: Set doesn't understand at: HUH? So I asked: "Do you get this often?" "Oh yes once and awhile this happens... I just reply ok and continue what's the big deal? " Well where was this coming from? A little digging on the stack frame showed that ClassBuilder>>mutateInstances:from: was attempting to mutate all instances of the old class to the new class definition. Since I had lately studied Meta-classes I explored further. Sure enough if I asked for the class of the instance then for some of the instances I'd get a class definition that was OBSOLETE! This causes really bizarre behavior problems since for example instances using the old class didn't see new methods in the new class. IE an instance of FOO doesn't understand fum, but method fum is certainly defined in the browser, Oh what fun. This happened because the code that migrated all instances of an old class to the new class of course failed, but why? "Oh, I added an allInstances method on the class side, and I keep track of instance creations so I can later ask for all instances of a class" Proud novice Smalltalker speaking... {drink more coffee, take stroll, think about what to say} Of course the real Behavior>>allInstances returns an array, not a set. But the programmer didn't know about that and hunting down all instances was of course flawed logic, perhaps a dependency set made more sense and might be faster. Lint in the Refactory Brower would of course tell you that you're not sending super for your newly declared class method which might clue you into the fact you're overriding a system method. I zapped her allInstances call after ensuring her use of the returned object, now an array was acceptable. But wait what about all those instances that point to obsolete classes. Well this proved difficult to fix, since the system dictionary points to the currently defined class, and you can't get to the obsolete classes directly. Mumble Mumble. Of course asking for allInstances of a class now only returned the instances for the current class, not the obsolete ones... Grumble Grumble... To fix it we built a new image, then all the odd things that happened in the past disappeared, small wonder. |