Service Decorators

TL;DR: decorators for services are pretty easy to write in Jolie,
thanks to a native feature called aggregation.
Be careful in the deployment phase for managing performance hits!

Service Decorators

Just read this article about using decorators over inheritance in
object-oriented programs. I assume that you know decorators in the following. If
you don’t, get informed (e.g., by reading that article) before proceeding.

The Decorator design pattern offers a way to cleanly modify the behaviour of an
object by using composition instead of inheritance. I won’t enter in the merits
of composition against inheritance in object-orientation (both have their own,
depending on the other features of the language), because I’m interested in
microservices here. In microservices, composition is typically the only option
you have. That’s because your microservices may be written in different
languages, or even paradigms. And even if their codebases were somehow
compatible, inheritance would still be out of place: your microservices can only
depend on the communication APIs of other services, not on their implementation
details (e.g., by looking at their source code).

Since decorator acts through composition, this pattern is potentially
interesting for service programming. But as the author of the article linked above mentions,
using it can be frustrating since it requires a lot of boilerplate code. This makes it also
error-prone.
As a running example, let’s look at the e-mail service interface proposed in that article, rewritten in Jolie:

Decorating an operation

Now, suppose that this service is available to us as EmailService. Assume also
that we want to write a new service that decorates EmailService with the
following logic: whenever send is called, we check if we have sent an
“important” e-mail (e.g., the subject contains a specific keyword telling us
that the e-mail is important, or the addressee is in a special list); if an
important e-mail has been sent successfully, we backup its content by calling
another service, for indexing and safe-keeping.

A naive implementation is to write the decorator by re-implementing interface EmailService, like this:

The code for listEmails and downloadEmail is boilerplate, since we’re just
forwarding requests and responses. The author of the article
suggests that it would be nice if languages supported a native feature that makes
writing this code unnecessary. Luckily, we have it in this case!

Forwarding is a native feature in Jolie, since building proxies is the bread and
butter of service composition (think of load balancers, caches, etc.).
We can rewrite our decorator like this:

Interface Decoration

What if you want to change the behaviours of many operations, not just one?
What if this behaviour change is always the same? For example, suppose that we want
to write a decorator that keeps track of all events: whenever an operation is called,
we write this in an external log.

Ouch, boilerplate again! What we need is the capability of writing that logging
code just once, and applying it to the entire API of EmailService. That’s what
courier processes
in Jolie are for. Here’s the improved code, using courier:

Circuit breakers

What’s a cool example of a decorator? Circuit breaker! Yup. A sketch in Jolie using aggregation can be found
in this paper.

Conclusions

As cool as decorators are, don’t forget that you are adding a layer of
indirection. Many times, you don’t have a choice and your code benefits so much
that you should pay the price. But in microservices, be very careful about how
efficient your extra layer will be. If you stack too many decorators and they
are all communicating remotely via sockets, you’ll soon have a performance
problem. This is a deployment challenge: in Jolie, using a different
communication medium doesn’t alter your behavioural code. So choose your
communication media wisely when you deploy! If you have control over your stack
of decorators, consider whether it would be better to put them all in one place and
have them communicate using shared-memory (local location in Jolie).