On 21 July 2013 20:21, Denis Kudriashov <dionisiydk@gmail.com> wrote:
2013/7/21 Stéphane Ducasse <stephane.ducasse@inria.fr>
Interesting how many people in this list think that "Announcer subclass: #TxEditor" provides special implementation of announcer named TxEditor?
Many this is composition using inheritance and inheritance should not be used like that.
Announcer subclass: #GreedyAnnouncer
Announcer subclass: #RemoteAnnouncer
And if we prefer composition we should not implement such kind of hierarchy. We should implement GreadySubscriptionsRegistry, RemoteSubscriptionsRegistry or AsynchSubscriptionsRegistry and reuse existed Announcer. All subscribing and delivering logic implemented by subscription registry. Announcer is just simple delegator with convenient api to create Subscription instances:
Announcer>>subscribe: anAnnouncementClass do: aValuable "Declare that when anAnnouncementClass is raised, aValuable is executed." ^ registry add: ( AnnouncementSubscription new announcer: self; announcementClass: anAnnouncementClass; valuable: aValuable)
Announcer>>announce: anAnnouncement
| announcement | announcement := anAnnouncement asAnnouncement. registry ifNotNil: [ registry deliver: announcement ]. ^ announcement
All magic happens inside #add: and #deliver: methods of SubscriptionsRegistry.
Also announcements framework provides very nice feature: you can have announcer as last argument of event handler selector (that's why AnnouncementSubscription contains reference to announcer instance):
announcer on: MyEvent send: #handleAnnouncement:raisedBy: to: aSubscriber
Without subclassing YourEventsSource from Announcer you will not have such feature. Or you will need implement complex subscription method inside YourEventSource which will delegates special event handler to its announcer
1. you don't need separate class to represent event source. it can be any object which does: announcer announce: Foo. in any place.. I do not see any practical gains from forming a separate class for this role. It is barely formalizeable because the way how users creating and triggering events is arbitrary. 2. SubscriptionRegistry is an implementation detail. It is private. It is a way how Announcer doing things inside. It should be no concern of anything outside to consider what it does. You won't find this class in VisualWorks implementation, for instance. 3. again, event source - is any object which says 'announcer announce: ...' It is NOT announcer, because announcer is an event dispatcher. dispatcher ~= source Is it so hard to see a difference? When you subclass from Announcer, is that you want to say: 'self announce:' , so the very same object acts both as event source and event dispatcher. But then , as Stef said, by subclassing you inheriting API. So, what prevents me from writing following code, in my own class, which uses your domain object in a following way: coolDomainObject := YourDomainObjectWhichInheritsFromAnnouncer new. coolDomainObject on: Foo do: #bar. coolDomainObject announce: Foo. That i guess is not something you expected, huh? But why not? As long as your object understand this protocol, and as long as you don't overriding original behavior of Announcer, i can abuse your object in a way you did not expected. And this is a consequence of violating principle of least authority. Because once you declare that we're free to use subclassing for any purpose, then, i can declare: i am free to use any subclass of Announcer as announcer for myself. Lets write random code, do not follow any rules and everyone will be happy. --- Best regards, Igor Stasenko.