Don’t worry! I’m not going to talk about dressing up casually for work as the title may suggest. This is going to be a little story on how, after eight years since introduction, I stumbled into using functional style programming. Apart from using the occasional Java Stream here and there, I never wrote any code in a functional style kind of way. Until now that is…
An important aspect of my current project is logging. One of the requirements we defined for testing is that we want to be able to assert that things are logged correct. The objective was simple. Write a piece of code that can do that in an easy way (and if the code is flexible then that is a plus).
As a huge clean-code fanatic, instead of starting to type relentlessly and crank out the code as I go, I started at the end. How do I want it to look when I use my custom made class? How can I design it in an elegant way?
Asking myself these kinds of questions made me sort of design the code upfront. Which sounds to me like doing the right thing. And while I am at it I might as well throw in some TDD and write a test for my custom LoggerSpy first.
Awesome! Short, concise and it does the job. Although it is clear what LoggerSpy does, it isn’t very flexible. It accepts a string and checks if the list of log events contains a message that exactly matches the given string.
But what if I want to check if the log contains a message that ‘starts’ with a given string? Or ‘ends’ with it? Or complies to a certain regex? Should I make extra public methods in my LoggerSpy for each of those checks? That doesn’t sound overwhelmingly flexible.
My next design attempt was something along the lines of the Hamcrest library. It’s time to introduce the ‘equalTo’ matcher.
Now I could potentially make a matcher for every way I want to match my log message against a given string. The code reads well, it is flexible, the call to containsMessage is very self-explanatory and it looks nice also. This seems like a good time to start implementing the whole thing.
My first reflex for implementing LoggerSpy was doing it hardcore Java style. None of that functional style voodoo code! (Note: by voodoo code I mean code that seems to work great but you don’t quite understand what it does or how it exactly works)
Job accomplished. My design is implemented. The usage of the LoggerSpy is clean and simple. But we already knew that since we designed it upfront. The only thing that bugged me was the amount of boilerplate code needed.
1. for each type of matcher (equaITo, startsWith etc.) I had to create a separate class, create a static method that accepts a String value and create a field to store the String value. While actually the only thing that truly matters is this piece of code:
2. and since I have to create a different class for each type of matcher, I had to create an Interface (LoggerSpyMatcher) as well in order to pass along all my different types of matchers to the containsMessage method.
But altogether a very good attempt. The main goal was easy and flexible in use. Commit-Push. Next story…
A week or so later I accidentally stumbled upon a talk by a software engineer called Mama Samba Braima (aka Nelson). In that talk he explained functional style programming in an easy to follow manner. What first seemed like reading a book written in Chinese started to make some sort of sense to me all of a sudden.
What if I saw functional style programming as a way to create methods that you can pass along to another method and execute it inside that other method when needed? Although this explanation feels like selling the concept of functional style programming a bit short and not telling the whole story, it was a good metaphor that helped me visualize it a bit better. All of a sudden the idea of refactoring my LoggerSpy functional style was born.
If you take a look at the java.util.function package you’ll see all these kinds of interfaces. Consumer, ObjLongConsumer, Supplier, DoubleSupplier, Function, BiFunction, Predicates. There are 43(!) of those guys in there. Not very inviting to read.
But as it turns out these functional interfaces are basically descriptions of the kind of method that you want to pass. It defines the input parameter(s) and the return type, for instance:
There are many more functional interfaces but it is basically all the same.
So, I look at my LoggerSpy again…
I read about Functions… and then it clicked…
As you can see in the code example above, my “matches” methods in the non-functional style LoggerSpy accept a list of ILoggingEvents and return a boolean.
So, for my functional style LoggerSpy to work I need to create matchers of type Predicate<List<ILoggingEvents>>.
That piece of code above looks confusing at first glance. EqualTo returns a LoggerSpyMatcher while events.stream().anyMatch() would return a boolean, huh??? But it is not the value (or the outcome) of the anyMatch method that the equalTo method returns. Nope, it is the “logic” itself that the equalTo method returns.
Looking good, but all I have created up until now are my “methods” that I want to pass to the containsMessage method of the LoggerSpy. I can pass along all the matchers that I want but at this point it doesn’t do anything.
The only thing that I need now is a way to invoke the matcher. That is where the “Single Abstract Method” (SAM for short) of a functional interface comes into play.
All I have to do now is call the SAM on my matcher object inside my containsMessage method. Calling that method on my matcher invokes the method that I just passed into my containsMessage method and returns a boolean result.
Suddenly my LoggerSpy looks like this…
My matchers look like that…
… and I use LoggerSpy in my tests like this
Super clean, simple and easy to use. Never thought that I would end up actually using functional style programming after all this time. But I have to admit… I kinda like it!
The full working example can be found on my GitHub: