The thing is... functional programming has its own version of a lot of these problems, as well as its own problems.<p>The easiest example is the base class fragility problem. This is just a special case of the compounding fragility of any reusable component, where fragility increases with the width and depth of its dependents. If, instead of a class, a function is reused by many other functions it will suffer the same problem. Any changes to that "base" function will affect all functions which invoke it down the dependency chain.<p>I believe the actual issue is that isolating and defining abstractions from the landscape of necessary implementations is actually very difficult. AKA "programming is hard".<p>I think in a lot of cases it is impossible to correctly model abstractions, since different use cases will push and pull on different parts of the "boundaries" of the given abstraction. In other words, reality is messy and our computer models are usually extremely naive.
Indeed, functional programming can lead to spaghetti code just as easily as any other paradigm. I’m really growing weary of all these posts around the Internet claiming that some particular style of development is better than another, it’s such a very shallow metric.<p>In this particular article, I’m with it on inheritance, I haven’t used it in many years. But I don’t at all follow the author’s argument against encapsulation.
>If this can happen, and it does, the author of the Derived class must KNOW how the Base class has been implemented. And they must be informed about every change in the Base class since it could break their Derived class in unpredictable ways.<p>Yes...? If you are manually overriding implementation details you must be aware of the implementation details and the contract the parent class is meant to fulfill as well as invariants it must hold.<p>>With Black Box programming, we can be completely ignorant of the implementation since we cannot inject code into the Base class by overriding one of its functions. We only have to concern ourselves with the Interface.<p>>This trend is disturbing…<p>it is not a trend and it should not disturb anyone. It seems author wants to change the behaviour of a type... without knowing or understanding the behaviour to start with.<p>>But if a parent and child could arbitrarily switch places, then clearly something is wrong with this model.<p>If a parent and child can arbitrarily switch places then it's obviously not a hierarchical model. Classes are not folders, they are a convenient subset of type theory. A 'Company'-related file is not a subtype of a 'Document'-related file, or vice versa. They aren't related, let alone related hierarchically.<p>>If you look at the real world, you’ll see Containment (or Exclusive Ownership) Hierarchies everywhere.<p>>What you won’t find is Categorical Hierarchies.<p>You won't find any hierarchies in the 'real world', they are abstract mental models that we, humans, use to organize things. Which one is more applicable depends on what you're looking at and thinking about.<p>I won't comment in depth on the latter 2 sections as they're comparatively short and nonsensical.<p>Don't get me wrong, I love FP and write Haskell and Elm relatively frequently, but this is not an indictment of OOP as much as it is an indictment of poor practices. And I know that's thrown around a lot as an excuse for the real pitfalls of OOP, and I will refuse to say that it's not "true OOP" for that reason, but, it's at least not <i>good</i> OOP.
Delegation is the right way to go. Containment hierarchies is a nice way to phrase it. Roman numerals had fervent defenders back in the day. You can use OOP in a sane way if<p>1. You avoid extends at all costs (avoid inheritance)<p>2. All classes are declared final, implement one or more interfaces ( you get polymorphism and abstraction)<p>3. Split data and code and use immutable data or declare all data as private with no public getters and setters (more encapsulation)<p>4. Ignore anything ever said by OO thinkers and architects because they will eventually ask you to do the above three with a domain specific language in 30,000 words
Every once in a while I see this article, and every once in a while I fear that junior programmers are going to read it as if it is at all accurate.<p>This is a great article that represents the fundamental problem of OOP - that developers don't actually use it.<p>Instead, we have a lot of procedural programmers writing code that masquerades itself as "object oriented", when in reality it's imperative functional decomposition that we're calling OOP because we don't know any better.
I don't necessarily think paradigms are the problem. The real problem is too much code is just that - too much code. Projects grow to huge sizes, and anyone under time pressure to either produce or extract code under business pressures is bound to get frustrated.<p>In an ideal world, regardless of the paradigm we choose, we should be looking to do more with less code.<p>For instance (and this is rather extreme example) use a dictionary in Python that occasionally pickles its contents to a disk for your mom and pop bread shop, as opposed to a full Docker / SQLite / React spin up.
I always believed composition and interfaces was saner than inheritance, but this was sneered at during the 90s and 2000s.<p>Still, OO isn’t all bad.<p>It’s perfectly suitable within a self-contained project or library. i.e., a hidden implementation detail.<p>But there are API land mines if you expose non-final classes for public use.<p>API design is fundamentally hard, and every language reverts to
some sort of versioning.