September 9, 2010 | In: AlertGrid, Integrations, Programming

Why we should raise events instead of only handle them in our code

As an application developer you often want to include notification functionality in your product. You want your users to know about certain events occurring in your application. For example, if your application is a project management system, you may want the project manager to be notified by email whenever a milestone is reached. The first approach that some people may think of can be illustrated by the following pseudo-code:


if (milestone.reached)
{
send_email(to = config.milestone_reached_message_recipient , subject = config.milestone_reached_subject, message=config.milestone_reached_message);
}

It looks very simple and intuitive, it does not hardcode the email parameters (recipient, subject & message), typically these parameters are accessible either from a configuration file or from a nice ‘preferences’ panel.

However, when you think about this a bit more, you’ll notice that it can be improved. The biggest problem with this solution is that it hard-codes the logic. In other words: it will always send exactly one email to exactly one person when a milestone is reached. What if you wanted to send an sms to two people instead of an email to one person? What if you wanted to do nothing, just ignore this event? To solve these problems, you have to start adding more ‘if’ conditions and loops (to iterate through a list of recipients), build more complex preference panels etc., in order to implement all the required event handling flexibility.

The point of this article is to show  another, supplementary, way: raise events in your code, and let somebody else handle them. Consider this pseudo-code:


if (milestone.reached)
{
raise_event(object='milestone', action='reached', total_tickets_in_milestone = milestone.tickets, milestone_start_time = milestone.start_time, ... and so on );
}

See what’s happening here. You don’t do anything, you don’t send emails, you don’t take any specific action. You only forward information about a milestone being reached, and you pass some extra parameters like the milestone start time, the number of tickets involved and any other related data that may be necessary. What you do is you transfer the responsibility of the event handling to the event recipient. It is entirely up to the recipient how he or she is going to HANDLE it, you don’t care about it. The advantages of this approach are clearly visible:

  • You don’t deal with dispatching emails, sms messages etc. as you don’t implement it. Let the event handler do it.
  • You don’t enforce any event handling logic. Event handlers can build custom rules on their side.
  • An event handling rule can be of any complexity, it’s up to the event recipients how they handle the events. If they want to have a rule such as “if milestone is reached and it involved less then 5 tickets and it took more than 20 days, then notify Mr Smith by SMS and Mrs Jones by email” – no problem. It’s up to them how they implement it, your application functionality does not prevent them from doing this!
  • Last but not least, if you raise events on a scheduled basis (e.g. every 5 minutes) – you let the event recipient detect events that are mising for whatever reason: your app. crashed, the hosting server hanged up, someone pulled the plug and so on… The responsibility of detecting missing events is transferred to the recipient, which means you don’t have to build a complex infrastructure for self-monitoring.

But, what does raise_event() actually do? It is quite simple: it must send data to a given ‘endpoint’ using a given protocol – and no more. The endpoint must be able to accept the events and handle them. The most popular technique is to send an HTTP request at a given URL. This integration pattern is often called ‘webhook’. And if you’re looking for a generic event handler application, that can start receiving events and manage them right away, check out  AlertGrid!

One last note, we don’t suggest that using webhooks should be the only way to notify users about occurring events. You can combine both of the ways described above, so that your app. provides some basic notification logic out of the box, plus it allows for additional, custom logic by using webhooks. It might look like this:


if (milestone.reached)
{
#Do some basic hard-coded logic
if (config.send_emails_on_milestone_reached)
{
send_email(to = config.milestone_reached_message_recipient , subject = config.milestone_reached_subject, message=config.milestone_reached_message);
}
#Additionally, raise the event which allows the recipients for implementing their own custom handling
raise_event(object='milestone', action='reached', total_tickets_in_milestone = milestone.tickets, milestone_start_time = milestone.start_time, ... and so on );
}

Comment Form