To event or not event, that is the question

Posted by jmls on 13-Apr-2011 15:29

In the middle of (re)writing the a webspeed module when I came across this scenario

METHOD PUBLIC VOID WebNotify(p_data AS CHAR):

    CASE p_Data:

      WHEN "extensions.conf" THEN hash42.lib:extensions:Config().

      WHEN "jabber.conf"     THEN hash42.lib:jabber:Config().

/* etc etc */

now, this got me thinking : would it be better to do the following

DEF PUBLIC EVENT ReloadExtensions ..

DEF PUBLIC EVENT ReloadJabber ..

METHOD PUBLIC VOID WebNotify(p_data AS CHAR):

    CASE p_Data:

      WHEN "extensions.conf" THEN ReloadExtensions:PUBLISH ...

      WHEN "jabber.conf"     THEN ReloadJabber:PUBLISH ...

/* etc etc */

or even

DEF PUBLIC EVENT ReloadConfig ..

METHOD PUBLIC VOID WebNotify(p_data AS CHAR):

ReloadConfig:PUBLISH(p_Data) ...

Thoughts ?, or comments ?

All Replies

Posted by Peter Judge on 13-Apr-2011 15:36

There's a lot of 'it depends' here, but first question is: how many components care about configuration? If it's just a library or manager, then I'd not use events.

And I think I'd do something along the lines of having a single config manager - or at the very least, since point of entry into all config managers.

Eg.

method public void WebNotify(p_data as char):

hash42.lib.GetConfigManager():Config(new ConfigArgs(p_data)).

/* or maybe */

hash42.lib.GetConfigManager(p_data):Config().

end method.

Posted by Admin on 13-Apr-2011 15:39

For something globally like "configuration changed" I'd even consider a static event.

Posted by Matt Baker on 13-Apr-2011 16:21

Don't make events your interface to a system.  But allow others to subscribe to the events of a system.

Events are there to notify an interested party that something has happened.  If you have some code where things happen, and you think "hey, maybe this object, which might not always be there, would like to know about it", then add an event for that thing, so they can freely subscribe to it themselves. e.g. "I'm a button and I was just clicked".

If you have a bunch of services that need to talk together to coordinate some single task, then use a service pattern.  e.g. getService("xyzservice").DoSomething() if that is appropriate or use just call the appropriate method on the appropriate object if that object should always be there.

The first is only appropriate if "extensions" and "jabber" are part of the base system.

The second is never right since that implies you don't really have properly separated services, as you have hard-coded not only the references to the service, but also you have made your events your interface.  If you wanna stick with this, just use methods as events are pointless if only one thing receives the event.

So of the three, the last is most appropriate if all the extensions needs to respond to the 'webnotify' call and reload their configuration, and they will take care of getting subscribed to the right method.

If only one module should receive the event based on the passed in data, then lookup the module via some service registration and call into the service interface as appropriate.  Leave the fact that the service reloaded its configuration in response to webnotify as an event of the service itself.

e.g.

method public void webnotify(p_data as char):

  define variable service as iService no-undo.

  service = ...lookupService(p_data).

  if (service <> ?) then

    service:webnotify().

end method.

Then have the service publish its own event which can be part of the interface in response to having its configuration reloaded, so others can know that that one service has been reloaded.

fixed some typos

Posted by Thomas Mercer-Hursh on 13-Apr-2011 16:42

I would add that any code which is choosing where to go like this one should be hidden behind a service so that the rest of the code doesn't need to know what is in use.

This thread is closed