2009/10/27 Nicolas Cellier <[email protected]>: > 2009/10/27 Igor Stasenko <[email protected]>: >> 2009/10/26 Stéphane Ducasse <[email protected]>: >>> so what is the fix? >>> I would really like to get announcement instead of event >>> systemNotification but I'm sure that this >>> can be a bit tricky. >>> >> >> Yes, tricky :) >> Here what i have in mind: >> >> Any change to system should be captured _before_ it applied. >> This allows us to introduce a policy which can validate the change and decide >> whether it allowed to be made or not. >> >> I made the SystemChangeEvent class, which having following state: >> - changeKind - a symbol, which identifies the change > > Hi Igor, > IMHO, nowadays, the trend would be to create subclasses rather than > internal symbols... > Shouldn't there be a symmetry with the hierarchy of changes in > DeltaStream (for example) ? >
Well, my own 'trend' is to use GLOBALS as little as possible. So instead of spawning a whole tree of different event types, and then spit them around in different places, i prefer to use messages instead. I am using a single #newSystemEvent: message to create an instance of system event. So, there will be only a few places, where #SystemChangeEvent global be referenced, and therefore you can refactor the whole thing by changing few places. I don't plan to put into the SystemChangeEvent any kind of clever code. It just a state holder, notthing more. And handlers usually do a simple dispatch to handle the event. Moreover, i won't be using numerous #isXXXXX stinky tests, which is just a code bloat and don't really helpful unless you writing plainly wrong code ( remember? "don't ask - tell" ) :) For instance, i tried to track all listeners of particular SystemNotification event, and had hard times to find them out, because its dispatching scheme generates the selector consisting from 3 parts: itemKind, changeKind, 'Event:' (see implementation of #eventSelector) but when i staring at code which creates a notification, i don't see these selectors, and to figure out, that is the actual method is used to handle given notification i need to go exploring the internals of dozens of AbstractEvent subclasses. In contrast, if i would want to find out all handlers of particular SystemChangeEvent , i would need only to see implementors of changeKind selector (such as #changeSelectorCategory) , which is right before my eyes, in the code which emits the system change event. But i want to hear your counterarguments, why bunch of subclasses is more appropriate. Symmetry with DeltaStreams: no symmetry. The difference is that deltas capturing 'before' and 'after' state. While for SystemChangeEvent, there is no 'after' happened yet. It should carry the only state which is enough to analyze & perform the change. And its not necessary that this state will consist of simple objects (strings, symbols etc), simply for speed & efficiency purposes - i could pass the CompiledMethod instance instead of the source of method, behavior object, instead of a class name and 'isMeta' boolean, and so on. Moreover, it is not necessary that change will be applied at all. The users of SystemChangeEvent operating directly with system data model, therefore you don't need to translate everything to simplest forms, as deltastreams doing, because these events living & dying inside the system and have little use for outside. Of course, the arbiter object, which i mentioned before could easily capture all 'before' and 'after' state, and then broadcast this to all subscribers. And of course its free to translate the event into more edigible form. > Nicolas > >> - parameters - a dictionary , which holding different parameters, >> important for change >> - subject - the object which is going to be changed (or taking a main >> role in change) >> - action - a block closure which , if evaluated, will apply the >> change to system >> >> For example, here the method which creates & populates the system change >> event: >> >> classify: element under: heading suppressIfDefault: aBoolean >> >> (self subject newSystemEvent: #changeSelectorCategory) >> subject: element; >> param: #behavior->self subject; >> param: #category->heading asSymbol; >> param: #suppressIfDefault->aBoolean; >> action: [ super classify: element under: heading >> suppressIfDefault: >> aBoolean ]; >> signal. >> --------- >> >> The event handling procedure is following: >> >> - first of all, an event passed to a system arbiter object >> - a system arbiter checking with the policy >> - if everything ok, change is applied by evaluating action. >> - and finally, change is announced to any interesting parties >> >> I want to make each package to hold own policy (a set of flags >> identified by name, to ease fileout). >> Then, any event could be validated by policy by issuing: >> package policy validate: change >> >> For example, lets see , what validations we could introduce for method >> recategorization event. >> >> - lets take most interesting case, when we want to recategorize the >> method in ClassA, which belongs to PackageA, >> and putting it into extension category, like *PackageB >> >> - check, if we allow any changes to ClassA (policy of PackageA) >> - check if PackageA allows method extensions (policy of PackageA) >> - check if PackageB allows extending the classes of another packages >> (policy of PackageB) >> - check if extension overrides existing method >> - and of course, we should check that given extension does not >> creates a circular dependency between the packages. >> >> There, of course, some problems which arising. >> - changes nesting. >> Some changes is complex ones, and even a simple method >> recategorization could lead to another event - creating a new >> category in class. Optimally, it would be cool to have only most >> basic events, which can't be nested. And any action which may lead to >> multiple changes, should be split on a number of basic ones. >> A SystemChangeNotifier solving this by allowing doing things silently: >> SystemChangeNotifier uniqueInstance doSilently: [ ... ]. >> so, any changes within the block , if any, won't be announced. >> >> - atomicity support. To support the bulk model updating, i can imagine >> the framework, which capturing any changes without applying them, by >> building/collecting all changes in parallel, and then applying them by >> a single mass-become. This is what SystemEditor does. >> >> - metaprogramming. There should be a means to leave a room for >> metaprogramming. We wouldn't want to signal a system change for >> anonymous classes, and many other things, which can be tricky here. >> >> P.S. as you can see , the plans is quite bold, and will require >> numerous refactorings :) So, the more people is interested in that, >> the better. >> >>> Stef >>> >> >> -- >> Best regards, >> Igor Stasenko AKA sig. >> >> _______________________________________________ >> Pharo-project mailing list >> [email protected] >> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project > > _______________________________________________ > Pharo-project mailing list > [email protected] > http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project > -- Best regards, Igor Stasenko AKA sig. _______________________________________________ Pharo-project mailing list [email protected] http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
