Skip to main content

Feature flags revisited

Feature flags have always made me feel ambivalent. On one hand, I can relate to the need for having a mechanism to easily enable or disable particular features, while on the other hand, being a software engineer I pretty much loathe this concept, since feature flags make your code ugly more often than not. Especially if such a flag is left in place even after its corresponding feature has become fully operational, eliminating any practical need to be turned off on demand.

Cliché ahead in 3,2,1: not everything in life is black and white, and sometimes, even in the face of feature flags, we can still, well, save face.


Basically the options fall into the following categories:

Hard coded if statement

boolean enabled = true;

if(enabled) {
  feature.activate();
}

Configurable if statement

// "enabled" is injected using DI
MyCtor(boolean enabled){
  this.enabled = enabled;
}

// later on in your code
if(enabled) {
  feature.activate();
}

Hard coded polymorphism

MyFeature feature = new MyFeatureImpl();

// replace above line with this one to disable the feature
//MyFeature feature = new MyFeatureDummyImpl();

// this line doesn't know if it's activating the real feature, or the dummy one.
feature.activate();

Configurable polymorphism

// enabled can be injected using DI
MyFeature feature = enabled ? new MyFeatureImpl() : new MyFeatureDummyImpl();

// this line doesn't know if it's activating the real feature, or the dummy one.
feature.activate();


The configurable polymorphism looks almost bearable.
Taking it one step further, one could give up the if statement determining what implementation to initialize, by simply injecting the appropriate one. The downside of it is that in order to switch between the two implementations (the real one and the dummy) one would have to create two different beans, and manually wire things properly (i.e., inject the correct bean). It's definitely a feasible solution, though a bit too delicate, in my humble option, since it requires manually tossing beans around.

It would be great to get the simplicity of a configurable boolean flag along with the elegance of polymorphism, enter Spring Expression Language (SpEL).

Suppose we create 2 beans, a dummy implementation which effectively disables a feature, and the real one, with ids "myFeatureDummyImpl", and "myFeatureImpl" respectively, SpEL allows us to do the following:

<bean id="myLogic" class"bla.bla.yada.yada.MyLogic">
  <constructor-arg ref="#{${enabled} ? 'myFeatureImpl' : 'myFeatureDummyImpl'}"
</bean>

Now all we have to do in order to enable or disable our feature is to set the ${enabled} property to either "true" or "false", no need to explicitly temper with beans or bean ids.

Comments

  1. Oh, wow, I had absolutely no idea you can use boolean expressions like that in spring.
    This is so cool.

    ReplyDelete

Post a Comment

Popular posts from this blog

Sending out Storm metrics

There are a few posts talking about Storm's metrics mechanism, among which you can find Michael Noll's postJason Trost's post and the storm-metrics-statsd github project, and last but not least (or is it?)  Storm's documentation.

While all of the above provide a decent amount of information, and one is definitely encouraged to read them all before proceeding, it feels like in order to get the full picture one needs to combine them all, and even then a few bits and pieces are left missing. It is these missing bits I'll be rambling about in this post.

Dependency Injection - The good, the bad and the ugly

The Good
Dependency injection (DI, a.k.a IoC - inversion of control) is a well known technique to increase software modularity by reducing coupling between modules. To provide the benefits of DI, numerous DI frameworks have arisen (Spring, Guice, Castle Windsor, etc.) all of which essentially give you "DI capabilities" right out of the box (these frameworks tend to provide a whole lot more than just "DI capabilities", but that's not really relevant to the point I'm about to make). Now, to remove the quotes around "DI capabilities", let's define it as a DI container - a sack of objects you can manipulate using a provided API in order to wire these objects together into an object graph that makes up your application.

I've worked on quite a few projects employing Spring, so it will be my framework of reference throughout the rest of the post, but the principles and morals apply just the same.