Pitfalls with event-driven programming

If you’re a programmer, you’ve probably done some event-driven programming. This may be as simple as responding to button clicks by attaching listeners to an object, or listening for special string constants which are emitted with some arguments. This blog post discusses some event-driven approaches and then details some of the pitfalls which you should look out for.

Writing an event handler

This is the most basic part, the stuff you do when your event fires. In languages which have first-class functions (e.g. JavaScript) this is often trivial to do, but in other languages like Java, it often involves overriding a base class or interface which has a bit more boilerplate attached to it. Interesting distinctions here are mainly in whether the function can return anything of interest or alter the sequence of event handlers called. The return value may alter subsequent event handlers which are listening on the same event e.g. by passing the return value to the next handler. Alternatively, the event handler may be able to prevent subsequent event handlers from being called like Android’s abortBroadcast() method on BroadcastReceiver.

In general, anything which can alter the arguments passed to other handlers or the sequence of handlers called is a very bad thing. This is because it adds a huge amount of complexity. You can never be 100% sure that a given handler will ever be called unless you check each and every handler that is listening for a given event. You suddenly need to care about the sequence of handlers called. Don’t do that to yourself. Handlers which can “pass” variables to other handlers are also a huge headache to work with. The semantics are often extremely murky, particularly whether handler X will receive handler’s Y return value (or will it get Z’s instead?), and where that will be positioned in the function arguments. In the end, you have to look at multiple handlers to work out what exactly you can do in another handler, which increases the scope of possible errors you can encounter.

Keep event handlers completely isolated from each other.

Binding the event handler

This is where you attach your function to a specific event which will be fired in the future (e.g. a button click). This binding may be based on an object instance (e.g. button.setOnClickListener(...)), or based on a string constant (e.g. Android’s Intent actions, Node.js’ EventEmitter.on("constant", function(){...}). The most interesting difference here is the dependency required in order for the event handler to be bound to an event. In one case it’s a string constant (assuming a global dispatcher), in the other it is a UI widget. This has implications on how accessible it is to listen for events.

In general, it is good practice to separate your logic from your UI. This means your logic won’t have access to any UI widgets in order to listen for events from button clicks like “delete all my stuff”. In frameworks where handlers can only be attached to UI widgets, you end up emitting another event (e.g. the string constant version) which can be listened by your logic layer. That’s not to say that the UI layer may not wish to listen for the event as well (e.g. to say “Are you sure? Y/N”), but ultimately the transition from UI to logic layers will need to be done at some point. This transition can be done directly if the UI layer maintains an instance of your logic layer (e.g. as an interface) which works fine if your only want to invoke a single component when the event fires. If you want to invoke mutliple components though, it begins to get error prone. One downside to the global dispatcher string-based approach is that you cannot enforce who can listen for a certain event, which you can do via the object instance approach via dependency injection.

Think about which entities are required in order to bind an event; it can be a boon if done right.

Firing the event

This is where each event handler listening for a given event is invoked with some arguments (which may be void). The devil is in the detail with this. Are the handlers invoked concurrently on different threads? Is there any ordering between the invocations? Are the handlers invoked asynchronously (next tick of the event loop)? Which thread will the handler be called on (e.g. do I need to do runOnUiThread)? This information is critical, but often missed out of public APIs which expose events. In some environments the answer is a given (e.g. JavaScript) but in others you may end up finding out through trial and error.

Scoping plays an important part when firing events. The event may be fired only for handlers attached to the object, or it may go into a global cesspool of events. The global way is by far the easiest because you don’t need to think about your dependencies, but it has all the problems of traditional global state (albeit in a read-only form since you can’t modify the event being emitted). On the flip side, if it is too highly scoped then it might as well be useless (e.g. UI widget scope).

Be clear and consistent with how your events are fired, and consider the scope of each event.

Finally, I want to discuss perhaps the biggest problem with event-driven programming: flow control. Looking at the code in the editor, it is nigh impossible to work out the line-by-line execution. Now, ideally you wouldn’t care because the handlers are processing completely isolated things. But it rarely works out this way. Some frameworks allow events to emit events which can lead to a cascade of additional unexpected logic firing whenever you, say, hit the send message button. This increases complexity hugely, and because your code has separated concerns nicely into different events and event handlers, it’s very easy to do this. At its worst, this can lead to spaghetti code. This can be mitigated by being strict with your dispatchers (don’t use global ones which every part of your program could potentially interact with!). Inject your dispatcher like you would any other dependency, and scope your dispatcher based on a function of your app (e.g. MessageSendingDispatcher). This allows you to make much stronger guarantees about events which could possibly be fired because each dispatcher acts like a fire break.

Overall, event-driven programming is a great way to design certain problems like button clicking, but when used without clear rules (which are enforced) it can lead to horrendously messy loosely-coupled code. Be conservative with what you emit: procedural isn’t always that bad.

API Design (Part 1/2)

API design is Hard. I’ve made many good and bad decisions when designing APIs and I hope this blog post will guide people into designing better APIs. It’s a pretty meaty subject, so I’ve broken it down into two parts. This first part focuses on the actual design process for APIs. The second part focuses on the tools and techniques you can use when designing APIs.

What is an API?

I don’t mean a textbook definition, which Google defines as:

a set of functions and procedures that allow the creation of applications which access the features or data of an operating system, application, or other service.

I don’t find this particularly helpful, as it’s hard to map this statement to what I do every day. My hand-wavey definition would be that “An API is the way a developer interacts with your code.”

This is short and sweet but has a few key points:

  • It is “The One True Way“. The API is the de jure way of accessing your code and logic. This is the way you intend for developers to use your code. This doesn’t always match reality. If the API is lacking or unclear, all too often practices like accessing private fields or functions or relying on undocumented side-effects creep in. People start to rely on this, and it ends up becoming the de facto way developers interact with your API. At this point, it is no longer your API, but a modified version of it which is often more practical to the problem domain.
  • It is for developers. Ultimately, other people in the profession are your target audience. They may be web developers half way around the world in the case of REST APIs. They may be a work colleague in the case of internal company APIs. It may even be yourself several years later when you’ve forgotten what you’ve done. More generally, the person using your API has some knowledge of the underlying domain in question (e.g. it’s a REST API, so you’re using HTTP) but may not have knowledge of the specific domain that your API is in (e.g. knowledge of all the Facebook Graph entities/relationships).
  • It is to interact with some code. This code may not be defined yet (in the case of specification writing), or it may be concrete. The important point to note is that APIs implies a concrete implementation somewhere. This has implications on the first two points. If you are not the one writing the concrete implementation, you need to be extremely thorough when specifying the interfaces in order to convey your intent correctly. Common pitfalls here are not specifying edge cases absolutely unambiguously (e.g. can this be null? Is 0 a valid value?)

What does the API do?

This is the single most important question when designing an API. What is your goal/objective/aim here? This should ideally be represented as use cases which are agnostic to the API itself. You want use cases to be clear and concise to a non-technical audience. This is not just for communication purposes. Specifying use cases in pseudo-code like terms immediately restricts how you think about the problem on a sub-conscious level and affects your ability to come up with potentially better designs. For example, a bad use case is something like “Get the account, add some money to it, store the account”. This immediately evokes 3 API calls (getAccount, addMoney, setAccount), whereas 1 may be the better solution (depositMoney). A better description would be to “deposit money into an existing account”. Use domain-specific words whenever you can, as it will likely affect the names of your objects/entities.

A particularly gnarly problem comes when trying to extract use cases from other people. People will often announce solutions or steps to perform to solve the problem rather than say what the problem really is. This is problematic because:

  • It prevents you as a developer from seeing the whole problem. This can lead to bad designs because you simply weren’t aware of some additional constraint or couldn’t leverage a useful bit of information.
  • The solutions presented may not be appropriate or well-thought out. Rarely is the first design the best design.
  • You may miss important “behind the scenes” information such as assumptions made and trade-offs considered.

Always, always dig deeper. It is sometimes hard work to do this, but you can save yourself a lot of time by getting clear and concise use cases first, so you know what the aim of your API is. Now that you have your use cases, you need to start designing the API…

What you should think about when designing an API

A lot of the guidelines when designing APIs go something like: “Be Consistent”, “Do one thing and do it well” and “Don’t have surprising behaviour”. I couldn’t find a comprehensive list of tips which I should be thinking about when designing APIs. Then, I stumbled upon the 1996 paper “Usability Analysis of Visual Programming Environments: A ‘Cognitive Dimensions’ Framework” by TRG Green and M Petre. They focused on visual programming, but their cognitive dimensions apply uncannily well to API design (Source: wikipedia):

  1. Abstraction gradient : What are the minimum and maximum levels of abstraction exposed by the notation? Can details be encapsulated?
  2. Closeness of mapping : How closely does the notation correspond to the problem world?
  3. Consistency : After part of the notation has been learned, how much of the rest can be successfully guessed?
  4. Diffuseness / terseness : How many symbols or how much space does the notation require to produce a certain result or express a meaning?
  5. Error-proneness : To what extent does the notation influence the likelihood of the user making a mistake?
  6. Hard mental operations : How much hard mental processing lies at the notational level, rather than at the semantic level? Are there places where the user needs to resort to fingers or penciled annotation to keep track of what’s happening?
  7. Hidden dependencies : Are dependencies between entities in the notation visible or hidden? Is every dependency indicated in both directions? Does a change in one area of the notation lead to unexpected consequences?
  8. Juxtaposability : Can different parts of the notation be compared side-by-side at the same time?
  9. Premature commitment : Are there strong constraints on the order with which tasks must be accomplished? Are there decisions that must be made before all the necessary information is available? Can those decisions be reversed or corrected later?
  10. Progressive evaluation : How easy is it to evaluate and obtain feedback on an incomplete solution?
  11. Role-expressiveness : How obvious is the role of each component of the notation in the solution as a whole?
  12. Secondary notation and escape from formalism : Can the notation carry extra information by means not related to syntax, such as layout, color, or other cues?
  13. Viscosity : Are there in the notation any inherent barriers to change? How much effort is required to make a change to a program expressed in the notation? There are 3 types: “Knock-on”: a change in the code violates internal constraints in the program, whose resolution may violate further internal constraints. “Repetition”: a single action within the user’s conceptual model requires many, repetitive device actions. “Scope”: a change in the size of the input data set requires changes to the program structure itself.
  14. Visibility : How readily can required parts of the notation be identified, accessed and made visible?

To highlight some examples of what these dimensions mean:

  • If you’re writing a pet store API, you would expect to see a Pet object and a Customer object (#2 – Closeness of mapping).
  • An API with an addFoo function should have a removeFoo function (#3 – Consistency)
  • To send instant messages to another user, a bad API may accept 2x User, a Route, a TargetDevice, MessageContents and MessageMetadata. This requires far too many moving parts in order to produce a result (#4 – Diffuseness / terseness). It’s worth noting that having too few objects is also bad, if it isn’t representative of the problem domain.
  • APIs which rely on being called in a certain order (#5 – Error proneness, #9 – Premature commitment)
  • Errors should be informative and clearly identify the problem (#10 – Progressive evaluation). Note that this clarity applies to the API and not to the implementation, e.g. returning HTTP 500 when there is an implementation error is appropriate.
  • Tightly coupled components (#13 Viscosity (Knock-on)).

For a good talk on API design (with an emphasis on Java), I would recommend Joshua Bloch’s Google Tech Talk. It’s an hour long but has a lot of practical advice which I’m not going to (badly) rehash here in this blog post. Once you’ve distilled this information, you need to actually come up with a proposal. Don’t try to be perfect, and instead aim to keep it as simple as possible.

Rapid development

When you have a proposed design, you need to see if it is fit for purpose. You should quickly write up a prototype which demonstrates the proposed design. This is hard to do because there aren’t a lot of tools to do this currently (I’ll cover this in part two). The prototype need not be code. Worked examples on paper using the proposed design can work just as well.

The whole point of trying out the design is to be able to prove that the 14 dimensions outlined earlier are met satisfactorily. Often, there will not be a simple pass/fail to each dimension. A lot of these dimensions are subjective e.g. #5 – estimating the likelihood of the user making a mistake. You’ll probably find some flaws in the original design. There will be disagreements among people about which dimensions are important. That’s the point. Iterate on the design a few times, and when you (and your team) are happy with it, write up a prototype in code if you haven’t already.

At this point, it’s extremely tempting to say that the API is complete and act as if the API is set in stone. This is a mistake. The point of writing a prototype in code is not to “finalise” the API. It is to exercise parts of the API which people may not have thought about. You may find yourself calling the same functions in the same order over and over, which you never thought about before. You may find edge cases where you lack all the information you need to make a decision due to some race conditions. The prototype is serving as the ultimate test of your API. Modify it liberally. Don’t be tempted to set your API in stone yet. How long you remain in this process depends on the time constraints. When the API hasn’t changed for a while, it’s a good indication that the API has reached a natural equilibrium. This doesn’t necessarily mean it is the best solution, it just means it has reached a local minima. This is the ideal point to make the API public.

Future-proof your API

You should assume that the first public API will be replaced completely. This means designing in version numbers from day 1. You should consider how flexible the API is to modification. For example, it is a lot easier to add new JSON keys to a JSON object than it is to rename keys. That being said, try not to “organically grow” your API or else you can end up with some odd, confusing or surprising behaviour.

An example of an inflexible API is Android’s permissions model, in particular push notifications. The permission depends on a string constant which was originally set to com.google.android.c2dm.permission.RECEIVE. This was named after Cloud-to-Device Messaging (C2DM) which was the API they presented at the time to send push notifications. Fast forward several years and this is the only reference to C2DM remaining. The API was superceded by Google Cloud Messaging (GCM) but because they baked-in the name of the API into the Android permission constant, they couldn’t ever update it. Now in practice, this doesn’t really matter because most people just copy and paste the string and couldn’t care less about what it means. However, anyone looking at the API can see this relic which developers are stuck with forevermore. Google had a choice to either leave the wart alone or break backwards-compatibility with apps which used the old string constant. They decided to leave it as it was, which I think was the right choice.

Always be thinking about extensibility when modifying the API. You may have heard the saying “It’s easier to add than it is to take away” used in reference to API design. This is absolutely true. You can always add more methods, more REST endpoints, more helper functions, but the moment you want to remove a REST endpoint or an obsolete interface function, things break and you start getting hate mail. Add things sparingly. This should be thought of as a stronger version of YAGNI, because the scope for things to go wrong is that much bigger. If you’re thinking you “probably” will need this in the future, don’t add it. You need to be certain; if it isn’t blocking progress then you don’t need it. It’s easy to add it in later and you don’t break other people’s code when you push a new version out. Rather than getting hate mail, you’ll be getting praise because you’ve added support for super-awesome-thing-#4.

Tools and techniques

Part two will outline some useful tools and techniques you can use when designing APIs. This will focus more on the actual “doing” part of API design rather than the ideals you should be shooting for.

Javascript Build Systems

There’s a lot of them. From Grunt to Gulp, it seems Javascript has a huge Not Invented Here syndrome when it comes to automating tasks like minifying, linting and automatic rebuilding when source files change. I’ve seen some backlash in the community (e.g. here and here) and to be honest, I agree with them. Engineering is all about trade-offs. Will using this tool save you time and  reduce complexity or will it just add complexity and end up costing more time? In some cases, it absolutely saves time. Take NPM for example. Trying to manage dependencies in a project manually is just insane, and NPM takes a lot of the domain-specific complexity (e.g. managing nested dependencies) completely out of the equation so you don’t even have to think about it (most of the time…). What do these build systems really offer over using NPM scripts or Make?


On the Grunt.js homepage, you’re shown two big questions right at the start:

  • Why use a task runner?
  • Why use Grunt?

The first question doesn’t have anything to do with Grunt. You could drop both the question and answer to any sort of build system and have it apply equally. The second question has the answer:

The Grunt ecosystem is huge and it’s growing every day. With literally hundreds of plugins to choose from, you can use Grunt to automate just about anything with a minimum of effort. If someone hasn’t already built what you need, authoring and publishing your own Grunt plugin to npm is a breeze. See how to get started.

This also feels like a non-answer. Why should I use it? “For the ecosystem”. That doesn’t answer the question and even taking it at face-value means nothing (given the Node.js ecosystem far exceeds that of Grunt). You would expect that the Grunt homepage would be the most biased place to find the answer to “Why should I use it?” in order to entice developers to give it a go, so the fact that this is the best they have really doesn’t bode well. Why should I use Grunt over the competition (read: the terminal)?

To uglify some JS files, you’d write (source):

// Combine all files in src/
  uglify: {
    all_src : {
      options : {
        sourceMap : true,
        sourceMapName : 'sourceMap.map'
      src : 'src/**/*.js',
      dest : 'composite.all.min.js'


On the Gulp.js homepage, there’s the following:

  • Easy to use: By preferring code over configuration, gulp keeps things simple and makes complex tasks manageable.
  • Efficient: Using the power of node streams, gulp gives you fast builds that don’t write intermediary files to disk.
  • High quality: By enforcing strict plugin guidelines, we ensure that plugins stay simple and work as expected.
  • Easy to learn: Using node best practices and maintaining a minimal API surface, your build works exactly as you would imagine.

There’s a lot of talk about how it works, but not why I should use it and why it is better than the competition. It’s concerning to see that writing code is easier than writing a configuration file in their eyes. I was curious to read the “High quality” section. Intrigued on how the enforcement would be done, I dug deeper and found a guidelines document. It looks like they want to add a scoring system for their plugin registry but they don’t currently do this. They aren’t as strict as they claim to be, given plugins that don’t pass their acceptance tests just get a low score; they aren’t removed from the registry.

To uglify some JS files, you’d write (source):

// including plugins
var gulp = require('gulp')
, uglify = require("gulp-uglify");

// task
gulp.task('minify-js', function () {
  gulp.src('./JavaScript/*.js') // path to your files

Compare this to how you actually use uglify in the terminal:

$ uglifyjs ./js/*.js -o output.min.js

I don’t think anyone would disagree when I say that the terminal usage is a lot clearer. Of course, the real power comes when chaining these commands to automate a set of tasks, and being able to specify which tasks to run. All of the options are pretty similar for this:

// Terminal using && to chain commands, task names in package.json
jshint lib/ && browserify index.js -o dist/output.js

// Gulp
gulp.task('default', ['lint', 'sass', 'scripts', 'watch']);

// Grunt
grunt.registerTask('default', ['jshint', 'qunit', 'concat', 'uglify']);

So, there’s no real gain here for chaining commands either. But wait, what’s with the whole streaming business with Gulp? Well, all it means is that instead of creating temporary files whilst running tasks you can just pipe the output into the input of another task… something which has existed in UNIX since forever.


I don’t see why you’d ever want to use Grunt and/or Gulp over terminal commands invoked via NPM scripts. There’s no stand-out feature in any of these systems over the terminal, and it can actually end up being detrimental to use these tools (e.g. wrapper packages forcing you to use certain versions of plugins). If you aren’t comfortable in a terminal, time would be better spent getting used to using pipes and redirects as those skills are a lot more transferable than the latest and greatest JS build system. Of course, this is totally UNIX-centric, but nonetheless the basics exist in Windows too… so who is the target audience here?

Android and the dangers of delegation

For any Android developer, there comes a time where you debug a stack trace from the Play Console or from Google Analytics and you think “what?!”. The stack trace may not even call into your code or it may be an exception which you didn’t know was possible to be thrown. The latter is the topic of this post.

The problem

In older versions of Android (API 8 / 2.2), the built-in Android libraries could throw an exception which was completely undocumented. This would manifest itself as a crash, unless you caught all exceptions, which is generally seen as bad practice.

The solution

The only way to handle this would be to either:

  • Work out the precise failure mode (which parameters caused the undocumented exception) and handle that case, scoping it as closely as possible to the data from the crash report. “Handling” in this case may be explicitly catching the exception, or it may be not calling the API with known buggy parameters.
  • Catch all exceptions on that API call.

In a production environment, catching everything makes the most sense because you completely remove the risk of crashing the app with that API call and you can fail gracefully. If instead you catch the explicit exception, but don’t quite have the full set of data to scope your exception handling to, you risk crashing again.


After encountering this, my faith in Android APIs was shattered. Failure modes were identified for the API, but this particular one was not documented. As a result of lack of documentation, users had a buggy crashy app and I had to pick up the pieces. What’s worse, the app could still easily recover had I known about it: this wasn’t a fatal “I really can’t startup without this API call working” scenario. This made me seriously reconsider how I was interacting with Android APIs, and led to me employing Pokémon exception handling (“Gotta’ catch em’ all!”). This was not ideal but it was the lesser of two evils (the alternative being risking another crash for another undocumented exception).

I then started to think how this could have happened. It’s unfair to push the blame solely onto Google for this, because device manufacturers have an awful habit of tweaking and modding the Android OS for their particular whim. I wasn’t out to play the blame game, I was more interested in how this bug could’ve slipped through. It turns out that this was caused by another internal API call throwing an exception which was not handled. This then went up the chain until it became an uncaught exception.

Don’t delegate your API contract

This particular bug was exacerbated by having documentation which clearly defined which exceptions it threw under which circumstances. Any developer could handle the documented exceptions and feel a false sense of security. API designers should strive to always meet their contracts, so that API callers don’t need to employ defensive programming techniques everywhere. If a function says it throws 2 exceptions, it should make damn sure it throws those 2 and nothing else. This may mean that the function employs defensive programming techniques to guarantee this, especially if the function is calling other functions which aren’t exposed or have poorly-defined contracts. Delegating responsibility for your API contract to other functions is a bad idea. This is amplified by representing errors as exceptions, which automatically bubble up unless they are caught. Error codes/statuses may have prevented this, but only because it makes handling errors simpler in the general case (e.g. if (returnValue != null) or if (returnValue != -1)).

Ultimately, someone has to pick up the pieces when that nested internal function fails. Don’t let it be the end-user.

What this blog is about

This blog is all about programming, including architecture, design, UX, testing and documentation. Anything particularly interesting I find out may make it onto this blog. I hope this blog will eventually contain a useful repository of information for others to learn from.

So with that in mind, let’s begin…