I’ve worked on a Scala project for the last 6 months and previously given a couple of talks about adopting a functional style of programming in C# so this is a subject area that I find quite interesting.
The talk focused on 5 refactorings that the presenters have identified to help move imperative code to a more functional style:
- Isolate mutation – keeping mutation in one place rather than leaking it everywhere
- Isolate predicate – making it possible to filter collections
- Separate loops – iterating over collections more than once if we’re doing more than one thing with the collection
- Decide on branches once – putting conditional logic into a map as functions
- Separate sequence of operations from execution of operations – composing functions and executing them at the end
Since they were coding in Java they made use of the Google Guava collections library to make it easier to work with collections in a functional way.
As you might imagine some of the code ends up being quite verbose due to the inability to pass functions around in Java.
I was reminded of a coding dojo we did a couple of years ago where we compared how code written using lambdaj would compare to Scala code.
Despite the verbosity it was interesting to see that it’s actually possible to achieve a similar style of programming to what you would expect in languages like Scala, F# and Clojure.
One interesting thing the speakers suggested is that they are better able to see data dependencies in their code when chaining functions together which they wanted to apply to that data.
I hadn’t really thought about the data dependencies before but I generally find code written using function composition to be easier to read than any other approach I’ve seen so far.
The main reason I picked up for why the authors thought we would want to adopt a functional approach to start with is the fact that it limits the number of things that we have to reason about.
Interestingly Jon Tirsen recently tweeted the following:
In my experience large purely functional codebases are very painful. Shared immutable, local mutable is the way to go.
We’ve mostly kept our Scala code base immutable but it’s not large by any measure (5,000 lines of production code so far) and probably not as complex as the domains Jon has worked with.
It’s an interesting observation though…immutability is no silver bullet!