I appreciate the further thoughts of others - I should go back and look at Dolphin code (I think there are ways to run it on Mac now?).
The upcasting Richard refers to is what I'm trying to do - which is how I got interested in understanding if you could tell if someone was subscribed to an event, as if not - then you could pass it up to the parent to - re-announce it via the announcer of that parent (in CP - the announcers are by presenter, so hence the handoff). In theory it's quite neat - but I did see some deprecations in Announcer trying to stop too much knowledge leaking out. However, knowing if an event has any listeners doesn't on the surface seem too controversial - but I can see that everyone approaches this idea with understandable caution. Possibly this is masking some other approach to this - or - I can happily have an extension method on Announcer - or - I can propose this method in a PR for symetry with some of the other #hasXXXX methods. Tim On Tue, 27 Apr 2021, at 5:31 PM, Richard Sargent wrote: > I have seen something called upcasting and downcasting (as contrasted with > broadcasting). Mostly, I have seen it in UI layers. > > e.g. a leaf node receives a change notification, decides it isn't interested > in handling the notification, and so passes it up to its parent, etc. > > Downcasting is similar but in the opposite direction. e.g. a window receives > an event and asks its children to handle it, and they do the same. In this > case especially, the one that handles the event needs to mark it as handled > so that no one else is asked to handle it. > > On April 27, 2021 5:49:56 AM HST, Tim Mackinnon <tim@testit.works> wrote: >> Hi guys - yes that fire and forget was always how I had viewed >> announcements, and potentially my scenario is misusing "announcements" which >> is why I was interested in views here. >> >> However - as announcements are typically a mechanism for farming out >> processing to others - how does one handle the scenario that you might only >> want one object to handle the announcement (and not others)? >> >> in my specific example, with MVP - a view, totally decoupled in a web >> browser, wants to pass on a button click to a presenter - however it not >> clear what the best mechanism to bubble up that handling should be? If the >> immediate presenter of the view can handle it - great - but if not, how >> would you continue to broadcast wider to see if someone higher up the parent >> component chain can handle it? >> >> If you go fire and forget (which is how I had viewed announcements prior to >> this specific case) - then you have the problem a different way - when >> someone processes an announcement it might already have been handled earlier >> and so the consumer either has to check first, or their work is simply >> ignored as the announcement payload could just filter a response out. >> >> In my head, I'm sort of thinking this is akin to CPU interrupt chaining - >> where an interrupt can cascade up a stack if not handled OR like object >> inheritance where an object can choose to override a message and stop it >> from cascading up the inheritance chain. >> >> Maybe announcements aren't intended for this at all - although it seems an >> elegant way to handle it - with just 1 method addition to Announcer (but it >> does slightly expose things - albeit in a structured way - and similar to >> the similar #hasSubscriber:). >> >> I'm sure it "depends" - but interested in other observations from the field, >> as I'm sure I'm not the first person to hit something like this. >> >> Tim >> >> On Tue, 27 Apr 2021, at 3:51 PM, Sven Van Caekenberghe wrote: >>> The whole idea is to decouple producers and consumers, like in >>> messaging systems. >>> >>> You should not care if there are other listening, just like the >>> listeners should not care if there is someone posting data. >>> >>> Asking for subscribers is introducing a coupling. >>> >>> The announcement mechanism will/should deal with this in an efficient way. >>> >>>> On 27 Apr 2021, at 16:03, Tim Mackinnon <tim@testit.works> wrote: >>>> >>>> From my rather long ramble below - I am still curious if its distasteful >>>> to have a method on Announcer >>>> >>>> hasSubscriptionsHandling: anAnnouncement >>>> "Answer true if I have any subscribers to anAnnouncement" >>>> >>>> ^(registry subscriptionsHandling: anAnnouncement ) notEmpty >>>> >>>> Tim >>>> >>>> On Thu, 22 Apr 2021, at 11:34 PM, Tim Mackinnon wrote: >>>>> Hi everyone - I’ve always thought the article on announcements many >>>>> years ago was very cool - and we don’t seem to use them as much as we >>>>> could (but equally they aren’t a panacea to be overused everywhere >>>>> either - and they do get used in Pharo to some extent). >>>>> >>>>> Anyway, I’ve been playing around with CodeParadise (CP is a very cool >>>>> project, and Erik is very supportive and thinking about how to write >>>>> web apps a different way… I’m fascinated), >>>>> >>>>> And - CP uses announcements as mechanism to send events from the View >>>>> Client (in a web browser) to a Presenter on the server (which makes >>>>> total sense). >>>>> >>>>> In taking things for a spin, I hit an interesting problem on how in a >>>>> web component world, you should display a spelling test of words - >>>>> >>>>> e.g. SpellingTest — has many —> SpellingWord(s). >>>>> >>>>> >>>>> Initially I bunged it all in a single presenter with its associated >>>>> view, and it was a bit messy, and Erik guided me down a route (that CP >>>>> nicely supports) - that my SpellingTest view should have the name/date >>>>> of the test as well as an add word input field, but the list of current >>>>> Words (which I had bunged into a table) - were actually more elegant as >>>>> sub-components - hence a WordView - which renders a single word in a >>>>> DIV, and for the edit screen I was creating, a Delete button next to >>>>> the word (so you could delete it). So a 1 to many relationship >>>>> essentials. >>>>> >>>>> This is where the announcements kick in (and lead to my ultimate >>>>> question). >>>>> >>>>> When you click the Delete button, if I use a sub component - my view >>>>> will generate a DeleteWordAnnouncement - which gets fed to my >>>>> SpellingWordPresenter - however words in this sense don’t naturally >>>>> know their parent (the SpellingTest) - and its the parent test that has >>>>> a #deleteWord: method. >>>>> >>>>> I’ve been taking with Erik, on different ways to elegantly handle this. >>>>> >>>>> a) you could change the model so words know their parent (in my case, >>>>> I’m using a 3rd party model for Flashcards, and they just don’t know >>>>> this - and adapting them would be a nuisance >>>>> b) my TestPresenter could listen to announcements on the WordPresenter >>>>> - and I could get some communications between presenters (although >>>>> normally the Presenters just get events from Views, and pure domain >>>>> models - so it feels a bit abnormal to consider another Presenter as a >>>>> sort of model - but I could live with this >>>>> c) given the composable nature of views/presenters (and CP is base on a >>>>> WebComponent model) - you could bubble up Announcements, so that if an >>>>> event isn’t handled by a view’s immediate presenter, you could re-route >>>>> it to the parent of the View (the component owner) and see if it’s >>>>> presenter could do something. >>>>> >>>>> >>>>> I think (c) has a certain expectation to it - in fact when I converted >>>>> my initial one-presenter attempt into components, I still had listener >>>>> code in my TestPresenter that was expecting to get a deleteWord >>>>> announcement and I was initially surprised that I wasn’t getting it (as >>>>> it was now just going to the Word component I had refactored out). >>>>> >>>>> So I wonder if others here would expect things to work this way too >>>>> (and are there other examples in the wild that lead you here - or scare >>>>> you away from this?). >>>>> >>>>> Back to my Announcement question - if C is a good idea - why doesn’t >>>>> the Announcer class let you check if if will handle a particular >>>>> announcement? The API has #hasSubscriber: and #hasSubscriberClass: , >>>>> but its missing: >>>>> >>>>> hasSubscriptionsHandling: anAnnouncement >>>>> "Answer true if I have any subcribers to anAnnouncement" >>>>> >>>>> ^(registry subscriptionsHandling: anAnnouncement ) notEmpty >>>>> >>>>> >>>>> And I am wondering if this is because it's a bad thing to expect to be >>>>> able to check? In my case above, I would want to do this to know if CP >>>>> should instead try announcing a message to a parent presenter because >>>>> the current presenter won’t handle it. In my example above, my >>>>> WordComponentView will broadcast that the delete button was clicked, >>>>> but its actually a parent view which would reasonably want to listen to >>>>> this kind of event and process the delete. And in a many words >>>>> scenario (the Test has many words), its unrealistic for the parent to >>>>> register to listen to each word component individually (in fact CP sort >>>>> of hides this from you), however if you could listen to an event in >>>>> your TestView, it seems to come out quite nicely - and looks a bit >>>>> like this: >>>>> >>>>> viewCreated >>>>> super viewCreated. >>>>> >>>>> self view >>>>> when: CpNavigationAnnouncement >>>>> do: [ :action | self model goto: action location ]; >>>>> >>>>> when: CpAddWordAnnouncement do: [ :action | self addWord: >>>>> action data >>>>> ]; >>>>> when: CpDeleteWordAnnouncement do: [ :action | self deleteWord: >>>>> action data ]. <— this is the one I’m talking about >>>>> >>>>> >>>>> So I’m curious on the overall thought process here, but in particular >>>>> whether I should even submit a PR on Announcer for >>>>> #hasSubscriptionsHandling: ? >>>>> >>>>> Tim >>>>>