With that in mind, I recently watched a presentation titled Simple Made Easy by Rich Hickey, the creator of Clojure. The presentation contained a pretty compelling definition of the term “simple” and explained the benefits of functional programming in a way that things finally clicked in my head. Let’s get down to the details.
In the presentation, Rich Hickey assumes that the roots of the word simple are “sim” and “plex,” which means literally “one twist,” while the roots of the word complex are “com” and “plex”, which means “multiple twists.” This implies that the word complex should be understood as a synonym to “complected” — braided together.
As Hickey later points out, object-oriented programming, as understood by most of its current practitioners, is a paradigm that inherently complects a lot of things together. Just to mention a few of his examples:
- Objects braid together state, identity, and value.
- Methods braid together function and state.
- State braids together EVERYTHING.
If I remember correctly, it was not elaborated a lot in the presentation, but if you try to add object-relational mapping to the mix, things are… extremely complex. You don’t even have to use tools like Hibernate or JPA (although these certainly don’t help). The mere fact that you have to take the database into account with every single field of your object can be considered extraneous complexity.
Let’s leave Hickey’s way of thinking for a bit (you can watch the presentation for more of that). I know that it’s not really a valid argument, but as a lot of you most likely noticed, functional programming has recently become extremely popular among OO programmers, while more and more functional capabilities are being added to languages like Java or C++. The same applies to favoring immutability, which has been considered a best practice for at least 10 years or so (probably more, but I was too young to know that). It means something.
Not looking too far away from my area of interests, one of the mosts important OOD concepts ever are high cohesion and low coupling. It’s like we all see how complect-ed object-oriented systems can become from day 1, so instead of eliminating the problem completely, we make it a lifelong battle of every programmer.
Another closely related example is the Single Responsibility Principle. If I were to get a dollar for every person I’ve seen asking what does one thing in SRP mean, I could buy myself an IntelliJ license for a year. As objects in languages like Java are artifacts made to complect multiple things together, the one thing is always an approximation.
The last point related to complexity that I’ll mention is about making things fit in our head. After all, if we had an unlimited amount of brain power, we wouldn’t need to bother ourselves with limiting complexity. But we don’t and, as a form of adaptation (I guess), our brains almost always make us see only a single part of the whole “object” picture. This allows us to work without going crazy but, at the same time, is very, very error prone. If we were to effectively reason about objects, then at any point in time, to understand a single line of a single method in an object, we would need to consider all possible states of a given object and sometimes even a few more related ones.
As all of you expect by now, the conclusion of the presentation and all of the arguments above is that functional programming, especially in languages like Clojure, is so much simpler and all that. There are immutable data, pure functions, almost no state mutations, and all of that is easy to reason about. At least that’s how FP fans market it.
As for me, I’m not really converted. I’d rather say that I’m confused and having doubts about all the programming stuff that I’ve been doing over the last 11 years. All these arguments here make a lot of sense, but I guess it’s not enough to convert a true believer like the one I used to be.
I’m also pretty sure that it’s not the only sensible way of thinking about simplicity, although it’s by far the most convincing I’ve heard so far. And even if this one is right, it only proves a significant drawback of the as-is OO approach. Maybe we can mitigate it somehow? Or maybe there are advantages that make it up for us? Or do other paradigms’ drawbacks make them a worse choice than OO anyway?
What do you think about it all? Let me know in the comments!