Template Method rocks but Higher Order Function can do the trick

Marco Nicolodi
Jan 28, 2019 · 5 min read
Image for post
Image for post
Photo by rawpixel on Unsplash

I love object orientation, and C# implements it in a very elegant manner, but since I do lots of JavaScript, sometimes I do mess with some functional stuff. It bothers me when people say functional programming is hard… It’s just different! Also, it’s not like Object Oriented Programming (OOP) is THAT easy. You have Design Patterns, SOLID (and solid is composed by SRP, OCP, LSP, ISP, DIP), inheritance, encapsulation… so why sometimes functional programming seems to fail to show its value? I think maybe the lack of real world examples makes OOP developers doubt the usefulness of it. After all, even though currying is awesome, no one needs it to sum two numbers!

In this short article, I’m going to show an elegant functional solution to a real-world problem and its OOP equivalently elegant solution, from an OOP developer perspective.

The Problem

At Qualyteam we have lots of scripts related to DevOps. As the number of scripts grew, our team had to reach for npm/docker/kubernetes/build/migration scripts in files, wikis, and documentations spread around. To solve this problem, we’ve built an internal CLI using Node JS (I will write an article about it soon!) to avoid this search hassle and free our talented developers to keep delivering our amazing products.
One of the CLI’s feature is to allow a developer to choose a test spec file to run:

Image for post
Image for post

This is the function that shows this option dialog:

We pass a directory as a parameter. At line 2, the helper returns a string array containing all filenames within that directory. We use this file array as options to a prompt dialog, at line 9. The chosen file is then returned.

After a few days of usage, we’ve come with the idea to let developers choose a Docker image to build. We wanted to use the same function, but the directory containing the Dockerfiles also contained other files not related to Docker, hence the filesystem helper needed to support filtering, returning only .Dockerfile extensions. We’re expecting to just pass a matching parameter to the helper, but we’ve found out that another helper, the , was the only function that supported filtering. We could then use a conditional statement to choose between either or depending on if we want to choose all files or all files matching a blob pattern:

We’ve added an additional matching parameter to and a conditional statement to switch between filesystem helper functions. Conditional statements are evil. They seem to solve everything but they often let the hell lose. We’ve added complexity to our function, and disrespected the Open Closed Principle (OCP):

Software entities should be open for extension, but closed for modification.

There’s no way we could extend the use of this function by adding support for another filesystem helper, and we’ve actually modified it to fulfill the new requirements.

Object Oriented approach

I know how I would solve this problem elegantly with Object Oriented Programming. I would make use of the Template Method design pattern.

Template Method description on Refactoring Guru:

Template Method is a behavioral design pattern that defines the skeleton of an algorithm in the superclass but lets subclasses override specific steps of the algorithm without changing its structure.

This is a C# representation of the above function, using the template method pattern:

The abstract is our superclass class that defines the algorithm’s template. Note that the is a public method. This is the method that’s going to be called by the client classes. It defines the algorithm template and a step that each subclass should implement, the abstract method. Each superclass will override it to implement this method, using the right Filesystem helper:

We’ve managed to solve the problem without a conditional statement! Both finders just override the file fetching algorithm step. Notice how none finders define a public method. The client classes would actually call the abstract class public method, which would call the subclasses algorithm step. This is called The Holywood Principle:

Don’t call us. We’ll call you

Back to the functional land

Ok, but that’s in the cozy OOP land. We’re using JavaScript ❤ now, so let’s go functional! How would we achieve the same level of OCP compliance without adding another conditional statement?

Higher Order Function to the rescue

A Higher Order Function is a form of function composition in which a function either receives another function as a parameter or returns a function. Javascript’s , , and are examples of Higher Order Functions.

Take , for example. It can filter an array given any predicate, and we don’t use inheritance for that. We just pass our predicate, which is a function that returns a boolean, as a parameter, and the function will iterate over the array to return only the values that fulfills our predicate.

But how could we use a Higher Order Function to solve our problem? We can pass the helpers result as a function to the function. Remember these conditionals?

Let’s split them into two functions:

Now let’s turn our old into a Higher Order Function:

Now our chooseFile function receives a finder function as a parameter and returns another function. It doesn’t know the finder fetches the files within a folder and is open for extension since it allows any finder to be passed in.

To those unfamiliar with ES6 arrow function syntax, this is the same as:

https://gist.github.com/MarcoNicolodi/4e4941deccfa28a5ac8863a9e3ed8769

To avoid having to pass the finder every time you need to choose a file, we can leverage function composition:

Here’s the whole solution:

Summary

Our functional solution using a Higher Order Function achieves the same as our OOP solution using the Template Method design pattern. It’s open for extension and closed for modification, since it accepts any finder, and has a single responsibility, since it will not change if a finder requirement changes.

Higher Order Function is a basic concept in functional programming, and you use it a lot if you code in JavaScript. For more details you can dive deeper with the amazing Eloquent Javascript Ebook.

Qualyteam Engineering

Time de engenharia da Qualyteam.com

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store