Hello everyone,
I recently started to study Morphic and its implementation in Squeak, Pharo, and mostly Cuis. Reading through the code, I noticed that there currently are three implementations of "events". All of them are mechanisms to signal state changes; two are very generic, the third specializes in Morphic input. Slightly confused by the many meanings of "event", I began to sort the different parts and assign them unique names. The result of this process is a short tutorial on Events in Squeak, Pharo, and Cuis. It might reduce confusion for people starting their tour through the code, or simply help when using events in own projects. You can download it from http://www.elwedgo.de/fileadmin/events_in_smalltalk.pdf I would greatly appreciate any comments, ideas, or corrections. Thanks and have a good day, Peter |
Peter Dinges wrote:
> Hello everyone, > > I recently started to study Morphic and its implementation in Squeak, Pharo, > and mostly Cuis. Reading through the code, I noticed that there currently are > three implementations of "events". All of them are mechanisms to signal state > changes; two are very generic, the third specializes in Morphic input. > > Slightly confused by the many meanings of "event", I began to sort the > different parts and assign them unique names. The result of this process is a > short tutorial on Events in Squeak, Pharo, and Cuis. It might reduce confusion > for people starting their tour through the code, or simply help when using > events in own projects. > > You can download it from > > http://www.elwedgo.de/fileadmin/events_in_smalltalk.pdf > > I would greatly appreciate any comments, ideas, or corrections. > > Thanks and have a good day, > Peter > Hi Peter, Nice writing, thank you! Just a few comments. - #when:send:to: and #changed/#update serve a similar purpose, and only one of them is really needed. Their main use is to reflect model changes in user interfaces. For instance, PluggableMorphs use #changed/#update and LightWidgets use #when:send:to: for this. - At the implementation notes of #changed/#update you forgot about class Model. - At the implementation notes of #when:send:to: you didn't mention that ActiveModel is an optimization, using own actionMap instance variable and not the dictionary in the class side. This optimization is not unlike the one in Model. - MorphicEvents are really something really different... They are not message sends, but objects. This is not an implementation of the observer pattern, there is no mechanism for message delivery. Instead, MorphicEvents are stateful objects that are sent around until handled. - You forgot the AbstractEvent hierarchy. While this is not as general as #when:send:to: and #changed/#update, it is closer to them than MorphicEvents are. AbstractEvent is used to notify various Smalltalk tools of system changes. I hope you find these comments useful on your journey. Please keep your document updated with further explorations! Cheers, Juan Vuletich |
In reply to this post by Peter Dinges
On Tuesday 16 Nov 2010 8:55:52 pm Peter Dinges wrote:
> You can download it from > > http://www.elwedgo.de/fileadmin/events_in_smalltalk.pdf > > I would greatly appreciate any comments, ideas, or corrections. Good stuff. You should add it to squeak wiki so that you can directly link terms to their wiki entries. when:send:to: and changed/update are used for different situations. WS is used when event listeners are known apriori and the listener is interested in the happening. Changed/update is used when they are unknown and the listener is interested in the state change caused by the event. For instance, when up key is pressed in a list, the listener is well known and interested only in the happening of key press. WS is ideal for this case. On the other hand, when a value in viewer is changed, an unknown number of watchers need to read the new value. This would be a case for changed/update. Of course, we could use a WS when the watcher is created but it wouldn't be simple. In your CU example, Alice would be an instance of Dresser and Bob will be an instance of Eater, where Dresser and Eater are subclasses of Person. Alice would wear office dress if the alarm went off in the morning or an evening dress if it went off in the evening. Subbu |
Hello Subbu,
> Good stuff. You should add it to squeak wiki so that you can directly link > terms to their wiki entries. thank you very much. Putting the text into the squeak wiki is on my todo list. Also, thank you for your clarifications on the different usage scenarios. Unfortunately, I think I do not fully grasp why CU events are easier for unknown listeners. All that a change from CU to WS events seems to require is maybe a relocation of the registration code(?) [Note that my text is meant as a description of what is, not of what should be. What was/is important to me, is to document that several mechanisms exist so that people don't end up looking for errors in the wrong places.] Suppose we have a viewer as you proposed. When a value in the viewer is changed, - with CU events, viewer would issue "self changed: #valueUpdate"; - with WS events, viewer would issue "self triggerEvent: #valueUpdate". > For instance, when up key is pressed in a list, the listener is well known > and interested only in the happening of key press. WS is ideal for this > case. On the other hand, when a value in viewer is changed, an unknown > number of watchers need to read the new value. This would be a case for > changed/update. Of course, we could use a WS when the watcher is created > but it wouldn't be simple. Why is it more complicated? At some point you have to tell the watcher which viewer to watch. So couldn't you just have a method Watcher>>watch: viewer viewer when: #valueUpdate send: #doSomethingWatcherSpecific to: self that is called during initialization (or maybe later)? It certainly has more characters than "viewer addDependent: self", but avoids the (possibly) huge distinction of cases in Watcher>>update: Also, if the watcher watches several viewers, it has to query all of them if it only receives the CU event "update: #valueUpdate". (The viewer triggering the update might not be provided.) With WS events, above method could be modified to: MultiWatcher>>watch: viewer viewer when: #valueUpdate send: #doSomethingWatcherSpecific to: self with: viewer No code change in the viewer class is required to accomodate MultiWatcher :-) > In your CU example, Alice would be an instance of Dresser and Bob will be > an instance of Eater, where Dresser and Eater are subclasses of Person. > Alice would wear office dress if the alarm went off in the morning or an > evening dress if it went off in the evening. I guess I overemphasized instance specific behavior. The situation I made up to show that CU events are less general probably rarely occurs in real code. I will incorporate your suggestion in the next version. Cheers, Peter |
On Sunday 21 Nov 2010 9:57:06 am Peter Dinges wrote:
> Unfortunately, I think I do not fully grasp why CU events are easier for > unknown listeners. All that a change from CU to WS events seems to require > is maybe a relocation of the registration code(?) CU and WS are meant for different scenarios. Studying senders of model: will make the context clear. CU is for situations where the views are intentionally decoupled from the object being observed (model). > Suppose we have a viewer as you proposed. When a value in the viewer is > changed, > - with CU events, viewer would issue "self changed: #valueUpdate"; > - with WS events, viewer would issue "self triggerEvent: #valueUpdate". The viewer does not know the number and kind of listeners interested in the changes so it cannot register handlers for them. Of course, you could add a method in the Viewer that Watchers can call when created to register a handler for them but it would only be duplicating CU logic in a roundabout way. > Why is it more complicated? At some point you have to tell the watcher > which viewer to watch. So couldn't you just have a method A watcher is for a single variable in a morph. When you click on 'simple watcher' or 'detailed watcher' from a variable's menu in a Viewer, the watcher is created to get/set that variable from that morph. Subbu |
In reply to this post by Juan Vuletich-4
Hi Juan,
thanks for telling me about the optimizations in Model and ActiveModel; I guess I should have looked more thoroughly at which classes reimplement parts of the mechanisms. I will add a paragraph to the implementation notes. > - MorphicEvents are really something really different... They are not > message sends, but [...] stateful objects that are sent around until > handled. OK, I see your point. They do, however, fulfill the criterion of "signaling an asynchronous state change" (the user pressed a key, etc.). Don't you think that they should at least get mentioned? > - You forgot the AbstractEvent hierarchy. While this is not as general > as #when:send:to: and #changed/#update, it is closer to them than > MorphicEvents are. AbstractEvent is used to notify various Smalltalk > tools of system changes. Concerning the AbstractEvent hierarchy: I do not know why I had not found this one, but you are of course right, it deserves some paragraphs in the text. Furthemore, Torsten Bergmann noted that Pharo additionally includes the Announcements framework. So two more event mechanisms to choose from. :-) Thank you very much for your comments. The next draft will certainly benefit from them. Also thank you for your work on Cuis. Cheers, Peter |
Hi Peter,
Peter Dinges wrote: > Hi Juan, > > thanks for telling me about the optimizations in Model and ActiveModel; I > guess I should have looked more thoroughly at which classes reimplement parts > of the mechanisms. I will add a paragraph to the implementation notes. > > >> - MorphicEvents are really something really different... They are not >> message sends, but [...] stateful objects that are sent around until >> handled. >> > OK, I see your point. They do, however, fulfill the criterion of "signaling an > asynchronous state change" (the user pressed a key, etc.). Don't you think > that they should at least get mentioned? > Yes, sure. I just say that it is not a direct replacement for #when:send:to: and #changed/#update. Those are indeed redundant, but MorphicEvent is not IMO. >> - You forgot the AbstractEvent hierarchy. While this is not as general >> as #when:send:to: and #changed/#update, it is closer to them than >> MorphicEvents are. AbstractEvent is used to notify various Smalltalk >> tools of system changes. >> > Concerning the AbstractEvent hierarchy: I do not know why I had not found this > one, but you are of course right, it deserves some paragraphs in the text. > Furthemore, Torsten Bergmann noted that Pharo additionally includes the > Announcements framework. So two more event mechanisms to choose from. :-) > Right. > Thank you very much for your comments. The next draft will certainly benefit > from them. Also thank you for your work on Cuis. > > Cheers, > Peter > Good! You're welcome! Cheers, Juan Vuletich |
Free forum by Nabble | Edit this page |