Hi,
When working with announcements I find it strange I can only specify subscriptions to announcements on the subject level. What I like to do is be able to add a subscription to a certain aspect of a model: employee := Employee new. (employee scopeForAspect: #name) when: ValueChanged do: [nameChanged := true]. employee when: ValueChanged do: [employeeChanged := true]. employee name: 'Piet'. self assert: nameChanged = true self assert: employeeChanged = true With: Employee>>name: anObject (self scopeForAspect: #name) announce: ValueChanged So the [triggered := true] block would only be triggered when the name aspect changes. But the [employeeChanged := true] block gets also triggered by virtue of being subscribed to a larger scope. A nice addition would be to subscribe to a collection of objects When using a sort of ObservableModel this kind of usage doesn't really occur since an ObservableModel usually has only one aspect (the #value) to consider. Do you guys have the idea I'm designing my application in a weird way, can it be done in the current announcements framework? What I don't like to have is to receive annoucements for all sorts of aspects and then filter them out. I don't want the announcements I'm not interested in not to arrive at my subscriber. Any ideas would be appreciated, Wouter |
Wouter Gazendam wrote:
> Hi, > > When working with announcements I find it strange I can only specify > subscriptions to announcements on the subject level. What I like to do > is be able to add a subscription to a certain aspect of a model: > > employee := Employee new. > (employee scopeForAspect: #name) when: ValueChanged do: [nameChanged > := true]. > employee when: ValueChanged do: [employeeChanged := true]. > employee name: 'Piet'. > self assert: nameChanged = true > self assert: employeeChanged = true > > With: > > Employee>>name: anObject > (self scopeForAspect: #name) announce: ValueChanged > So the [triggered := true] block would only be triggered when the name > aspect changes. But the [employeeChanged := true] block gets also > triggered by virtue of being subscribed to a larger scope. Hi, I would do the following: [1] Define the #name: method Employee>>name: aString name := aString. self announce: EmployeeNameChanged. self announce: EmployeeChanged. Alternateively, you could define EmployeeNameChanged as a subclass of EmployeeChanged. In that case the method would look like this: Employee>>name: aString name := aString. self announce: EmployeeNameChanged. But keep in mind that the order in which you receive the announcements is not given in this case. [2] Subscribing I would replace employee scopeForAspect: #name with employee when: EmployeeNameChanged do: [nameChanged := true]. [3] Example Then, the example above would look like this: nameChanged := false. employeeChanged := false. employee := Employee new. employee when: EmployeeNameChanged do: [nameChanged := true]. employee when: EmployeeChanged do: [employeeChanged := true]. employee name: 'Piet'. self assert: nameChanged = true self assert: employeeChanged = true This is the scheme I use in daily life with announcements and it quite well suites my needs. Hope this helps, Ladislav Lenart |
Wouter Gazendam wrote:
> This would mean I'd have to make a Announcement class for each > DomainClass - aspect combination. This would run into thousands in my > system. Well, if you could live without anouncement inheritance, you could have NameChanged announcement instead of EmployeeNameChanged and you could use this announcement for all objects with name aspect. In this case, you would have to do more manual work (see the first Employee>>name:). But on the other hand, you would have specific announcement class for each aspect you're interested in, no matter what the total number of domain classes is. I think, having thousands of Announcement classes in this case is not a problem anymore, because announcements are object replacement for triggerEvent model; basically each triggered symbol means specific announcement class... Ladislav Lenart >> Employee>>name: aString >> name := aString. >> self announce: EmployeeNameChanged. >> self announce: EmployeeChanged. >> >> Alternateively, you could define EmployeeNameChanged as a subclass of >> EmployeeChanged. In that case the method would look like this: >> >> Employee>>name: aString >> name := aString. >> self announce: EmployeeNameChanged. >> >> But keep in mind that the order in which you receive the announcements >> is not given in this case. |
In reply to this post by Wouter Gazendam
Wouter Gazendam wrote:
> > employee := Employee new. > (employee scopeForAspect: #name) when: ValueChanged do: [nameChanged > := true]. > employee when: ValueChanged do: [employeeChanged := true]. > employee name: 'Piet'. > self assert: nameChanged = true > self assert: employeeChanged = true > > With: > > Employee>>name: anObject > (self scopeForAspect: #name) announce: ValueChanged > > > Any ideas would be appreciated, You've already outlined a very simple solution, missing implementation details. :) Instead of using Employee itself as the announcer, create a dedicated HierarchicalAnnouncer with a 'parent' link. Implement HierarchicalAnnouncer>>announce: as super announce: anAnnouncement. parent announce: anAnnouncement. In #initialize of Employee, create one such announcer for each individual aspect, with the parent link pointing to the receiver Employee. Remember those announcers in something like a Dictionary and implement #announcerFor: method to retrieve them. (You could call the method #scopeForAspect: too, I just find #announcerFor: less of cognitive load). Then everything should work exactly as your test code assumes. -- Vassili Bykov <[hidden email]> [:s | s, s printString] value: '[s: | s, s printString] value: ' |
Free forum by Nabble | Edit this page |