Out of the university and into the trenches
Functional programming is often associated with academia, because it’s roots can be found in lambda calculus. Functional languages such as Lisp, OCaml, Haskell might seem obscure and only relevant to the computer scientists who study them, not software engineers tasked with getting things done.
There are, however, many real-world benefits to functional programming languages that make them the best choice for certain applications. Erlang, for example, is a functional language developed at Ericsson and used to develop distributed and fault-tolerant software to run telephone exchanges. A more modern example of Erlang is WhatsApp, which is famously only had 35 engineers at the point where it was serving 450 million users and sold to Facebook for $19 billion.
That example not enough? Here are four more reasons to try functional programming.
- No side effects make it easy to run in parallel
2. FP techniques are a good way to structure asynchronous code
3. Pure functions are easier to test
4. FP techniques are a readable way to use collections
The FP techniques used by jQuery are primarily based around operating declaratively on collections of objects without having to manually iterate through each one. It provides composable functions which can be chained and lazily evaluated in the way you would expect from a functional language. This sort of chaining of operations is one of the most readable ways to perform multiple operations on a collection.
Writing good FP style code
Functional programming is not the same as the procedural code we have discussed above. It’s at its best when it’s more declarative. Declarative code can be a great way to express certain problems. Take a look at components in React, for example. They declare the current state of the DOM rather than describing every little change required to get there, and as a result, are much more readable.
The danger with this sort of code is that it can be a mystery to someone who doesn’t know how it works. React code may look simple, but it would make no sense if you didn’t know that it a framework was comparing it to the DOM and applying changes. Each type of declaration tends to have something in the background that does the work and only make sense once you know of its existence.
This example, from the React Hooks documentation, shows examples of declarative coding, both in the useState hook, and in the JSX template.
Here are a few things to focus on with your functional code.
When we have reusable bits of code, we often want to assemble them in different ways. In object oriented code, a common approach is to use inheritance, but a downside of this is that it’s must be a tree structure. If we consider an inheritance tree for classes relating to different types of vehicles, we might divide them up one way, such as whether they travel through land or water, and then find we want to split another way, such as whether they use propellers or rockets.
If we put all the code relating to propeller-driven planes in the subclass of air-vehicle, it’s hard to re-use it for propeller driver boats. Maybe we should have sub-classed on that first, but then we’d have the opposite problem.
In functional programs, if we make our functions composable in a variety of different ways, we can often create the ability to augment a data structure without ruling out the ability have other functions augment it further. For example, if we consider some jquery code, each of the functions can be chained together in any order and transforms the result passed into it.
Function programs look different to object oriented ones. At a simple level, they are often centred around the verbs (operations), rather than the nouns (objects). Conventional OO thinking might be that this isn’t as good. Objects provide us with an ability to structure our code by bundling it all up into classes that make sense in our problem domain.
Some problems though, don’t seem to map as well to an object model. Perhaps you’re building something is much more of a process than a thing, such as a service that processes and resizes images. An OO approach to the problem might end up with a lot of classes with rather abstract names, like ImageResizingService. If the goal of the program is to ensure that inputs flow through transformations to outputs, and object oriented code-base can actually make it harder for a new person to read and understand this flow.
Consider how we can make this most understandable to our reader in a functional program. Perhaps our image tool is like a conveyor belt in a factory. Files move through and have different transformations applied in several steps. Readable code should show the action of the conveyor belt, possibly using functions chained together. To see how the steps work or test them individually, dive down deeper into the functions.
For this sort of code, ensure that it’s read in the same direction as it executes, never be tempted to write code like.
const result = stepThree(stepTwo(stepOne(input)))
Anyone of the following ways would look better:
Craig enjoying another ice-cream sandwich in Korea