Simple Code: The Hystrix Story

  • 23 June 2018
  • 5 minutes to read
  • Share on:

Writing maintainable code is definitely hard. It’s even hard to define what “maintainable” means.
After watching an enlightening talk by the author of Clojure lang, I’d say that maintainable code should primarily be simple.

Simple is often erroneously mistaken for easy. “Easy” means “to be at hand”, “to be approachable”. “Simple” is the opposite of “complex” which means “being intertwined”, “being tied together”. Simple != easy.
– Rich Hickey, Simple Made Easy, 20 October 2011.

Reality is that we prefer easy “at hand” solutions that look innocent but lead to a poor maintenance experience.
Let’s explore how simple code differs from easy in practice using Hystrix library as an example.

Hystrix

Hystrix is a latency and fault tolerance library that became popular in Java community when it was open sourced by Netflix and integrated with Spring Cloud.

One of the most popular use-cases for Hystrix is protecting your app against failures in communication with 3rd party services.

alt text

Hystrix implements Circuit Breaker pattern that helps you to isolate failure and deal with it proactively.

Community-Driven Approach

Hystrix wouldn’t succeed if it wasn’t easy to use.
In Java community “easy” means that you add an annotation and it works out of the box. And it really works:

callWebService() method will return a default response if a web service throws an exception and you’ll see the errors statistic on a picturesque dashboard. Additionally, you can configure Hystrix command in a way that it won’t even call the web service after a specified amount of errors.
Looks awesome and, without a doubt, it’s easy.

Let’s test it. How can we do this?
You read hystrix-javanica documentation and realize that this code works only under certain conditions. You need to understand aspect-oriented programming model, AspectJ and Spring AOP (if you’re using Spring) to make it work.

The solution is to define a Spring context with AspectJ auto proxy and create App object as a bean.

The test looks as follows.

Although we easily implemented basic fallback functionality, we added accidental complexity that leads to maintenance problems:

Simple Approach

First thought is that Hystrix is just a poorly designed library. But surprisingly it’s the opposite. After reading the wiki it appears that there is a HystrixCommand class that has a well-defined interface.

Let’s create a Hystrix command for our use case.

It’s a generic implementation that can be reused for any command with a fallback. You write this once and reuse across the whole project.

The app code looks as follows.

You can reduce command object creation to just one line.

Sometimes it even makes sense to use a builder pattern with a rich DSL. You can get inspiration from another simple fault tolerance library - Failsafe.

Testing is simple. You don’t need a Spring context and Spring testing components such as mock beans. All you need is just a plain old JUnit test.

Let’s summarize what we just achieved:

These all are the benefits the simple code gives us.

Although big established frameworks like Spring strongly influence our perception of code quality, at the end of the day, it’s our responsibility to decide which code to write. My decision is to write simple code.

Here is the link to the repo containing source code: https://github.com/IlyaZinkovich/simple-hystrix