(If you’re not a programmer, or a particularly good programmer, you may skip this post and still lead a fulfilling life…)
Object Orientation is a joke. It does not solve as many problems as it ends up creating. Collectively, programmers could work on improving abstraction & problem solving skills. Instead we busy ourselves learning object patterns, libraries, higher-order hacks, and a variety of questionable micro-architecting techniques.
So how is Object Orientation (OO) broken? Let me count three ways:
- OO conflates modeling with algorithms. There are two fundamental skills every programmer needs: first, the ability to create meaningful data-structures that explicitly bound the problem & solution domain, and second, the ability to transform & compute from one data structure into another. OO conflates these skills and encourages programmers to attempt solving two different types of problems simultaneously. This allows for insufficient attention to each task, and results and in a more brittle solution.
- OO promotes the use of stateful code. “What’s wrong with holding state in a variable?”, you ask. Quite a bit! The vast majority of what we program could be translated into a functional approach, eliminating 99% of stateful code. The advantage to functional coding is a much tighter guarantee on your invariants: values don’t change out from under you; once a binding is made it is ‘locked-in’. By having spurious stateful variables, you weaken your guarantees one value-binding at a time, increasing the surface area to code-rot (future coders not understanding implicit assumptions) and abstraction bugs ('overloading’ the meaning of variables by 'clever’ use of state)
- In practice, Inheritance is broken. Proof by scenario: 3rd party class A provides a variety of non-final public methods, some of which it references, with assumptions, in private or final methods (i.e., non-public or non-overridable). Programmer Bob produces class B which extends/inherits from class A, and overrides a few of the non-final public methods provided by class A. Hell breaks loose, as A’s inner assumptions are now violated. Is it Bob’s fault? Not really, there is no way he could have known that A made those assumptions. Is it the author-of-A’s fault? Perhaps, because he failed to code against every possible future. That’s neither a practical nor agile expectation to assume that author-A should have coded his logic in a 100% future-proof way. In any event, it’s a non-optional burden added to the production of any library written in an OO language
Now, I’ll leave you with practical advice for working more effectively in OO languages:
- Treat the world as though there are only two types of classes: classes for modeling your input or output data domains, and classes that do things. Not only will your code be far better de-composed, you’ll find yourself more accurately modeling your data, and more easily codifying your algorithms.
- If you’ve followed suggestion #1, you may end up with many more static functions, or classes filled with functions, but devoid of member variables. This is a good-thing. You’re half-way to functional programming now. Resist the temptation to introduce state where you don’t need it.
- If you’re providing a library for the future, serve up interfaces and help your clients dodge the hell-bullet of inheritance-gone-wrong.
Feedback welcome in the comments section.