Composability and Events

Apparently one of the new buzzwords is composability, meaning everything from reorganizing (“pivoting”) your business quickly in response to changing market conditions to adding new technical capabilities to your applications as needed. As new features come online, the story goes, you should be able to seamlessly (that word!) add them to your applications as you need them, and ditch the ones you don’t need any more.

Now, let’s see, where O where have I heard this story before? DLLs, Java Applets, ActiveX, Enterprise JavaBeans, Service-Oriented Architecture, Service Provider Interfaces, the API Economy: it seems like every few years we have to rediscover how utterly cool modularity and (if we’re really chic) loose coupling are.

Technically, composability appears to mean something like a combination of SPIs and APIs. Microsoft touts the fact that it’s easy to add a FedEx module to Dynamics to enable shipping when it absolutely, positively has to be there overnight.

Cool.

Real composability, it seems to me, means a near-infinitely malleable product whose behavior can be adapted to any reasonable need.

How do you do that? (What does that even mean?)

Of course part of the answer involves a good, solid set of APIs to an application, documented, hopefully, with OpenAPI (nee Swagger) or something similar. Enough has been written about Why APIs Are Good that I’m not going to repeat their virtues.

But what about when you want to change, or augment, or even replace the core processing of an application feature? Well, of course many applications support events so you can know when they’re about to do something, or when they’ve done something.

But back in the day doing Lotus 1-2-3 my team and I decided we needed something more powerful. Our scripting language team (LotusScript) was demanding deep access to the product internals, and our addons like our Solver, even deeper ones. They needed to execute code in some cases before the relevant application code, in some cases after, for example, sideloading a file needed by the addon. And in certain cases – for example, loading a file type not supported by the original app – they needed to replace the existing code.

We had a pretty comprehensive set of APIs. But they didn’t solve the problem.

The Problem

Here’s the core idea: imagine a file load routine (this is pseudocode, so don’t get upset):

Pretty straightforward: parse the file extension and pass it off the right handler. No worries.

But what if you want to load a PDF? Or a text file? Or an MP3, for whatever reason? (Hey why not?)

Introducing the Event Manager

The idea of our Event Manager was simple: an addon could register for an event that happened before the core code ran, and/or an event that ran after the core code. In addition, the addon could return one of three values:

  • Ran successfully
  • Ran successfully, and bypass core code
  • Error

In other words, something like this:

Here you can see the first thing that happens is any addons that have registered for the “OpenFile” Before-Event get notified, and can either ignore, augment – or replace – the core handling, and thus can load a wholly new file type, if desired. (EventManager.BeforeEvent() fans out the event to all registered addons.)

The After-Event has less options, for obvious reasons. It can be used for logging, or can be used to (say) load a shadow file (as many of the 1-2-3 addons did). In this case the addon has to handle any errors that occur as the core code may not understand the addons’ semantics.

Value

We found this pattern very useful in 1-2-3, so much so that I ported the concept to Lotus Notes some time after. In some ways, I think, this provides a good benchmark of what composability should really be.

Comments are closed.