I came recently upon a thread where Object-Oriented Programming was being questioned because of excessive complexity, ceremony, layers,… and because of the insistence of OOP of treating everything as an object, which some feel runs counter to most people’s intuition. Similar threads keep appearing, where OOP is being questioned and other approaches, like functional programming, are seen as a cure for the OOP “problem”.
My answer touches upon many points, and I wanted to share it with you.
Encapsulation is a key thing in OOP, and it’s just part of the larger context. Abstract Data Types also do encapsulation. OOP is more than that; the key idea is that OOP enables the building of a model of the problem you want to solve; and that model is reasoned about with the spatial, verbal and operational reasoning modes that we all use to solve everyday problems. In this sense OOP culture is strongly different from the ADT and formal math culture.
Math is very powerful. It enables to solve problems that by intuition alone you wouldn’t be able to solve easily. A good mathematical model can make simple what seems to be very complex. Think how Fourier transforms make it easy to reason about signals. Think how a little mathematical reasoning makes it easy to solve the Mutilated Chessboard problem. In fact, a good mathematical model can reduce the essential complexity of a problem. (You read right — reducing the essential complexity. I think that we are never sure what the essential complexity of a problem really is. There might always be another angle or an insight to be had that would make it simpler than what we thought it was. Think a parallel with Kolmogorov complexity: you never know what the K complexity of a string really is.)
However, mathematical reasoning is difficult and rare. If you can use it, then more power to you! My feeling is that many recent converts to FP fail to see the extent of the power of mathematical models and limit themselves to using FP as a fancy procedural language. But I digress.
My point is that if you want to reach the point of agile maturity where programming is no longer the bottleneck, and we deliver when the market is ready, not when we finally manage to finish coding (two stars on the Shore/Larsen model), building the right model of the problem is an essential ingredient. You should build a model that is captured as directly as possible in code. If you have a mathematical model, it’s probably a good fit for a functional programming language. However, we don’t always have a good mathematical model of our problems.
For many problems, we can more readily find spatial/verbal/operational intuitive models. When we describe an OO model with phrases like “This guy talks to that guy”, that is the sort of description that made Dijkstra fume with disdain! Yet this way of reasoning is simple, immediate and useful. Some kind of problems readily adapt themselves to be modeled this way. You may think of it as programming a simulation of the problem. It leverages a part of our brain that (unlike mathematical reasoning) we all use all the time. These operational models, while arguably less powerful than mathematical models, are easier reason about and to communicate.
Coming to the perception of the excessive “ceremony” and “layers” of OOP, I have two points:
- Most “OOP” that we see is not OOP at all. Most programs are conceived starting with the data schema. That’s the opposite of OOP! If you want to do OOP, you start with the behaviour that is visible from the outside of your system, not with the data that lie within it. It’s too bad that most programming culture is so deeply data-oriented that we don’t even realise this. It’s too bad that a lot of framework and tooling imply and push towards data centric: think JPA and Rails-style ActiveRecord, where you design your “object” model as a tightly-coupled copy of a data model.
- Are we practicing XP? When we practice XP, we introduce stuff gradually as we need. An abstraction is introduced when there is a concrete need. A layer is introduced when it is shown to simplify the existing program. When we introduce layers and framework upfront (anybody here do a “framework selection meeting” before starting coding? :-) ) we usually end up with extra complexity. But that’s nothing new: XP has been teaching us to avoid upfront design for a long time.