Currying Specifications

noahs-knight-237650-unsplash

I learned about currying today. It’s very cool, but I realized I had (sort of) been using it previously without realizing it!

For background, I work primarily in Java. Java 8 supports functions, but beyond some simple applications the syntax gets in the way of actually being able to do functional programming. I’ve also fairly recently been using the idea of specifications from domain driven design.

Specifications (specs) are just a way to separate business / domain logic into its own place, rather than leaving them as seemingly-random snippets or methods in other parts of your code. A spec might look like this:


/**
* Determines if the given objects have the specified color.
*/
public class MatchesColorSpec {
public static boolean isSatisfiedBy(Color color, Collection<Colored> objects) {
return objects.stream()
.allMatch(object -> object.hasColor(color));
}
}

There are a few things to comment about here. First, I don’t use specs quite how Fowler recommends. Namely, I don’t always use them as predicates (mainly because I haven’t needed to support composition).

Second, as written, this spec is kind of useless. That’s because it can’t be reused–every caller must specify exactly what colors they need to check for. This also means that you can’t pass the spec around to ensure that multiple applications are using the same spec. What we really want is this:


/**
* Determines if the given objects have the specified color.
*/
public class MatchesColorSpec {
private final Color color;
public MatchesColorSpec(Color color) {
this.color = color;
}
public boolean isSatisfiedBy(Collection<Colored> objects) {
return objects.stream()
.allMatch(object -> object.hasColor(color));
}
}

We now need to actually instantiate a spec in order to use it, but that instantiation ties a specific color to the spec. We can define, for example, an isRedSpec and pass that around.

This is currying! It’s just not solely using functions. The pro: it gives us the benefits of currying while still being idiomatic Java. The con: it’s not obvious that this is using currying, so others may not keep that in mind when maintaining this code in the future.