Object Orientation: How Much is Too Much?
Has object orientation gone too far? Has the effort to build infinite reusability taken a turn for the absurd?
Maybe. Maybe not. Let’s have a look.
In theory, object orientation seeks to build code the way we build physical devices: it makes more sense to build general, modular, reusable components rather than specific, intertwined, inseparable ones. Take your car engine for example. The starter motor, alternator and battery can all be swapped out individually without changing the engine. Any replacements will drop right in, provided they have right interfaces, in this case, the voltage (12V), the starter gear meshes with the ring gear on the flywheel and has the proper bolt pattern to mount to the engine block, the alternator spins at the right RPM on the serpentine belt, etc. This is possible because the starter, alternator and battery are dumb, they don’t know what engine they’re on, they just do their job (although the bolt patterns mentioned may limit their use to a specific engine block).
This analogy defines objects, composition, and interfaces. It’s not hard to extend it to include inheritance: if we want to build a 24V starter motor, we can probably reuse some of the parts from the 12V version. Nor are the concepts of public and private properties difficult: the battery terminals are publically accessible, the cells inside the battery are private. The alternator rpm is a public method (we can spin it as fast as we want).
In theory, all together these OO features allow the programmer to build code that is safe (avoids bugs created by plugging incompatible objects together), allows changes to be made in one spot only and propagate everywhere by default (no duplicated code), and reusable (no reinventing solutions).
These OO concepts come directly from the physical world. Others aren’t so easy to find a physical analogue: static methods, abstract interfaces. A static method is like taking an Uber, it gets you where you want to go without buying a car. An abstract interface is like a standard that everyone chooses to follow so that things work together, the electrical sockets on the wall have a common plug for example. Outlets in other countries that implement different voltages use a different plug type to avoid damage, i.e. type hinting.
Like any theory, practice is imperfect. People who subscribe to theory regardless of this fact are ideologues, which doesn’t make them evil, but it’s always worth questioning if strict adherence to theory is doing more harm than good. Case in point: the React framework for JS broke the almost religious devotion programmers had to an architecture known as MVC.
MVC required the definition and instantion of a model (with all its properties and methods) anytime a view needed to reflect some user supplied data (because models and views were bound through events) even if that data never needed the local storage or send to server methods, etc. One only had to build a single complex UI to see the ridiculous amount of code that required the programmer write to say, “hmm...is this really the best way to do this?” (This post is not a defense of React, you can do your own research there, now back to the original point.)
If time tested theories like MVC can, in fact, be rethought, what about OO? While it would certainly be difficult to defend spaghetti code, there are occasions when abstraction goes too far. The factory pattern teaches that it is best to send our request to a “factory” (or agent, or broker) that produces the appropriate variant that we need to get the job done, like a travel agent picks the best flight for us. For example, instead of having our models build themselves from database data, have a “mapper” object get the data and pick the right model to build. That way, in the future, should we decide to change the database, we only change the code in one place, not on every model.
It’s easy to see how this pattern of abstraction can turn our code into a fractal, putting agents in front of agents in front of agents...when are we going to write the code that actually does something!?
This point has been made by many before. The zealous devotion to putting everything into classes, using static methods to get around the awkwardness of this, leads to the creation of many, many unnecessary lines of code, and potentially hours of lost productivity worrying about how best to abstract your functionality to plan for future use rather than simply writing the functionality now.
The fundamental question, like it was when React challenges MVC, is: when has a devotion to a structure become a hinderance rather than an aid? Functions can be written in a way that avoids code duplication and provides for reuse without the complexity of building classes and instantiating objects.
It is my opinion that JavaScript has thrived because of its classless nature, and the ever steady march toward molding JS into its ancient ancestors is a fools’ errand.
What do you think? Tweet me.














