Refactoring To Higher-Order Functions

In my last post, I demonstrated how we might refactor a simple object oriented piece of code into a functional style with a JavaScript example. The focus of that example was about how to get from instance methods that access mutable fields to stateless functions that use immutable data structures.

I wanted to follow that up with a slightly more sophisticated example to illustrate how we might refactor from an OO design that uses dependency injection to an FP design that uses higher-order functions.

Let’s do it in Ruby this time.

Here we have a class that writes customer data in a variety of formats – XML, HTML and andstrings – to a variety of output destinations – console, log file and NoSql database.

The serializers all present the same interface, with a write() method that accepts a customer parameter. A good first step might be to pass in lambda that invokes the serialize() method instead of invoking it on the serializer instance inside write().

So far, so ugly. Next we can make all our serialize() methods unique.

Then we can clean things up by turning these instance methods into standalone functions. e.g.

…allows us to re-write the client code more cleanly.

We can rinse and repeat for the output writers. Start by passing in lambdas that invoke their write() methods.

Then make each write() method unique.

Now, the next part is a little fiddlier. We want to turn these methods into standalone functions. For the console writer, it’s simple because write_console() is stateless, so we don’t have any fields to worry about.

But write_logfile() and write_nosql() access fields that are set in constructors. In the previous post, I illustrated how we can refactor from there. All the information those methods need can be passed in as arguments.

Now we can make them standalone functions.

And a final bit of tidying up: if we turn our write_logfile() and write_nosql() into closures, with the outer functions acepting all the messy extra parameters, we can simplify our client code.

Last, but not least, we get rid of the ResponseWriter class, making its write() method a standalone function.