I don't know about your specific requirement but I just want to share an approach that I found quite useful in difficult debugging situations.
The method markReadOnly: sets an object to call the method "attemptedROMStore:intoSlot:" when an instance variable of an object gets changed.
Thus, if you have an own object model of e.g. business objects you can use this approach to determine when someone changes an instance variable in an object in an unexpected way. Just implement this method in a subclass and you know when someone changes the object. If you do not want to disturb the flow in your program, then resetting markReadOnly in this method lets you write the new contents to an instance variable.
If "attemptedROMStore:intoSlot:" cannot be subclassed, you can always use an exception handler in order to get to the difficult location.
So for example:
| aObj assoc |
aObj :=Dictionary new.
aObj at: #A2 put: 'Hallo'.
assoc := aObj associationAt: #A2 ifAbsent:[].
assoc markReadOnly: true.
[
aObj at: #A2 put: 'This will not be set into the object'.
] when: ExError do: [:sig |
sig arguments first = 'Store into read-only object' ifTrue: [
Transcript show: 'Read only object has been changed. Do perhaps a stack dump to see where the change comes from ??'; cr.
].
sig exitWith: nil.
].
And of course - this type of coding is for debugging purposes only.