Tuesday, June 11, 2013

Aspect Oriented Programming in JavaScript

You may have heard about AOP recently or about some of the new libraries that are coming out. The first I had heard about it was with Angus Croll's talk on How we learned to stop worrying and love JavaScript, although they just called it advice (and is now being used in Twitter Flight). So just what is Aspect-Oriented, and why do you care?

Aspect Oriented programming is actually a subset of Object Oriented programming. It helps in code re-use where there are cross-cutting concerns that don't fit well in to the single inheritance model. These can be things like logging which you may want to apply to objects throughout your program that don't share a common ancestor that would make sense to add the functionality to.

So what we really need is functionality (called "advice", which is what Angus named his library) and a mechanism to add it to an object (called a "pointcut") and these two things together are called an "aspect". In the speaker deck we are given "before", "after" and "around" as our pointcuts, and our Aspect is actually the function that contains these. It turns out that using functions for describing these aspects are quite useful.

I wrote a plugin for Backbone called Backbone.Advice which we use at work. We've created a file which contains a lot of these mixins that we can now apply across different contsructors. This has allowed us to separate out logic which was repeated in disparate parts of the system, and f you look at the github repo you will see some examples which will do things from automatically listing views to giving you keyboard navigatable lists. Aspects turn out to be very handy.

So now the downsides. Using AOP makes it extremely difficult to debug. You will use functionality across different parts in your system but not necessarily know where it's going to be put when writing. You will also have a fairly ugly callstack, especially if you apply a few different aspects.

So how do we get around this? The trick is to keep the aspects simple and testable. If you have a look at the mixins you can see that often we're making another call to this.mixin(Mixin....); which gives us a sort of inheritance structure. We're also careful about our naming, keeping things consistent across aspects. Also we only allow mixing in on a constructor and not an instance which means we can easily find out what mixins are being used.

Some other AOP javascript libraries you can look in to:

1 comment: