Imperative vs functional programming. It’s a debate that goes back to the birth of high level languages—Fortran vs Lisp.
In later years, it was retreaded as object-oriented vs function programming (OOP vs FP)—OOP having become the (massively) dominant software development paradigm.
And, I’m a fully paid up member. I embraced Object Pascal via Delphi 1 on 1995 and have been on the train ever since. I now do a lot of development in C# and teach best-practices.
Problems with OOP
But, just between you and me, I’ve never been truly happy with OOP. I understand the technology fully, but it’s never felt elegant to me. My adoption of Object Pascal had nothing to do with object-orientation. I was seduced by Borland’s state-of-the-art tooling—an IDE that was years ahead of its time. Object Pascal just came along for the ride.
On balance, I’ve found OOP to provide more pain than benefits. Take the three pillars of OOP
- Encapsulation
- Inheritance
- Polymorphism
Encapsulation is great. I’m fully on board with it. But, a module system that allows me to group/isolate my code under namespaces, and hide private code, achieves that. Most modern languages—OOP or FP—deliver on encapsulation.
The benefits of inheritance are massively oversold. I have the scars. I’ve battled the fragile base class problem too many times—grappling with someone’s ill-conceived OO hierarchy that looked compelling in UML.
As for polymorphism, well, again, I’ve no problem with this, but it doesn’t need OOP. Polymorphism can be achieved with lightweight interfaces.
I’ve also failed to see many design benefits of using OOP. Mapping objects to the real-world is an incredibly leaky abstraction. Once you get beyond the high-level design it’s positively unhelpful. It also doesn’t fit very well with TDD. Designing objects to map to the real-world isn’t the same as creating testable classes.
The close coupling of data and behavior also feels unnatural. Maybe it’s my background as a data scientist, but I see code and data as separate things. My code is a pipeline through which data flows and is transformed.
OOP has, however, been wildly successful. It just seems that this success is a consequence of the significant education effort, impressive tooling and modelling techniques that have long been part of the OOP ecosystem. There’s a massive industry that supports, and it supported by, OOP.
Growth of interest in FP
FP isn’t new—Lisp dates from 1958. However, there’s been renewed interest in it in recent years. Much of this is down to growth in "parallel" environments, such as
- big data frameworks
- cloud computing
- GPUs
Functional languages tend to be more naturally parallelizable. They encourage the use of immutable data structures which reduce the side-effects that make code hard to run on multiple processors.
Apache Spark, the current darling of the big data world, is written in the functional language Scala. There’s even a (Haskell-based) functional language for programming FPGAs (CλaSH).
Many of the major OOP languages are also adopting functional features. .NET has LINQ—and most of my C# code is now LINQ with object-oriented plumbing. Java 8 introduced Lambdas. Idiomatic JavaScript is increasingly functional…notwithstanding the introduction of classes in ES6. Swift is often talked about as a functional language. Two prominent modern languages, Rust and Go, avoid classes altogether.
FP is also a natural fit for data science work. R, a popular language amongst data scientists, is functional (as is Excel). Functional languages translate well to interactive, REPL (or playground) environments, making it easy to experiment with code/analysis.
We need more op-ed like a hole in the head
A blog article expressing one guy’s opinion. Well, there’s a novelty. And, the flurry of interest in FP might be no more than fashion. Has anyone done any research?
When looking into this, I found a presentation given at Utah Valley University that pointed to some interesting experiments.
In one study a team at Yale asked teams to code solutions to a problem using a range of programming languages, including
- Haskell
- Ada
- C++
- Awk
Criteria used to evaluate the solutions were
- Extensibility
- Understandability
- Appropriateness
- Accuracy
- Compactness
Haskell, a functional language, was the clear winner. Given the possible variation in the skills of the teams, the study authors then had a graduate student learn Haskell for a week before attempting to code the solution. While not as effective as the experienced Haskell developers’ solution, the student’s submission came in second.
Now, this study was conducted in 1994, and development has moved on a long way since then. So…
Fast forward to 2014 and researchers at the University of California, Davis studied the following question
What is the effect of programming languages on software quality?
To do this, they took a dataset from GitHub. This dataset covered
- 729 projects
- 80m lines of code
- 29000 contributors
- 1.5m commits
- 17 programming languages
The projects were real-world products—such as Linux, MySQL, bitcoin, etc.
They concluded that
- functional languages are better than procedural languages
- strong typing is better than weak typing
- static typing is better than dynamic
- managed memory usage is better than unmanaged
The emphasis on the first point is mine.
Conclusion
Obviously, at the end of the day, use whatever makes you most productive. All experienced developers come with a history (baggage?) that makes then more efficient with certain paradigms, languages, environments, frameworks and technologies—regardless of the objective merits of those technologies.
However, if you are an OOP developer who’s never given FP a serious look (i.e. used it to develop a real-world application), I recommend giving it a try. It’s no longer an academic curiosity. React, the most popular front-end library for web development, encourages FP.
We’ll benefit from continued research into the effectiveness of different programming languages. Having data is so much more useful that a barrage of strong opinions (of which I’m as guilty as the next dev).