I feel like the author doesn't understand the design part of OOD. Yes, you can inherit yourself into rigidity. OOP doesn't prevent you from making design choices that turn out to be bad, or are bad in the first place.<p>You can't reuse a class without reusing the whole world? That's the purpose of dependency injection and depending on interfaces instead of implementation. Decoupling.<p>Diamond problem? Okay, granted. But this still solvable in most languages with interfaces.<p>I'm not really drinking the OO Kool-Aid here. I lean functional when I get the chance, but this article reads like someone who's against rope because they hanged themselves.
I doubt there's very few OOP hardliners on here, I'm certainly not. So, let me play devil's advocate here a bit.<p>For the monkey-banana-jungle problem, it seems the developer started from a monkey-banana type in a previous project, rather than just the monkey. It seems in this case you would refactor the existing monkey-banana class, and extract a plain "monkey" class that satisfies both projects.<p>I've done things like this in the past, and it's a headache, but it's less painful than starting over from scratch. Most OOP languages will offer good type checking for the refactoring process, and can easily catch any errors. Also, dead code elimination can remove most of the unused methods and types from a large codebase.<p>Diamond inheritance is a bigger problem. However the example they give is terrible. Why wouldn't the powered device type be a common ancestor? One way forward here is to use composition plus an interface to satisfy a new top level type with shared functionality. It's ugly, but gives you some form of consistency over types that need to be loosely coupled.<p>The fragile base class problem is equally stupid imho. Counting is managed in two different ways from two different methods? Yikes! They also didn't think to test this, and the change passed all of existing automated tests? Yikes!<p>You can shoot yourself in the foot with functional programming as well. Anything that is shared can become fragile. Forming abstractions that cut across multiple concerns is still problematic and error prone. It's common to bring a jungle when you need a banana no matter what PL technique you use.
Also see Yegor Bugayenko's essay, "What's Wrong With Object-Oriented Programming?"`<p><a href="http://www.yegor256.com/2016/08/15/what-is-wrong-object-oriented-programming.html" rel="nofollow">http://www.yegor256.com/2016/08/15/what-is-wrong-object-orie...</a><p>and also the essay "Object Oriented Programming is an expensive disaster which must end" had an interesting conversation here on Hacker News:<p><a href="https://news.ycombinator.com/item?id=8420060" rel="nofollow">https://news.ycombinator.com/item?id=8420060</a>
This is overly simplistic and ranty. Sure, the OOP community got high on its own supply for a decade or two and is now getting some well-deserved criticism, but that doesn't make OOP the devil and it certainly doesn't make all of its claimed virtues null and void (no pun intended).<p>The "Banana Monkey Jungle" problem applies to any paradigm that involves defining things in terms of other things, including functions that call other functions. You avoid it by writing code that's well-decoupled, no matter what paradigm you're using.<p>The diamond problem is well-documented and has been solved or worked around by numerous variations on inheritance (referring to methods by their class explicitly, composition, etc.). It's a real problem with Java's "pure" inheritance, but the author doesn't really add anything new to that discussion.<p>The fragile base class problem is mostly a problem of poor interface definition (read: documentation). Assumptions were made because there was ambiguity, and then those assumptions went from true to not true.<p>"Object Oriented languages don’t make Contain and Delegate easy to do. They were designed to make Inheritance easy."
It's clear this author has spent most of his time in Java. It's true that vanilla Java makes it difficult/annoying to implement delegation, but C# can do it just fine, as can TypeScript and (I believe) C++.<p>The Hierarchy Problem, once again, is solved by composition.<p>The author naively suggests that encapsulation is bad, but what he really means is that hiding values behind their functions is bad (debatable, but not crazy). Encapsulation is an essential building block of writing any nontrivial amount of code. Functions themselves are encapsulation. Libraries are encapsulation.<p>Finally, in the Polymorphism section, he actually bothers to distinguish the principle from how it's been traditionally applied inside OOP, unlike throughout the rest of the article.<p>OOP is flawed. OOP as passed down by the Java priests from On High circa 1995 was extremely flawed. But I'm weary of reading people's rants about it, especially when they can't distinguish ideas like encapsulation and polymorphism from OOP, and can't distinguish OOP from Java 1.0. Essays like this throw the baby out with the bathwater. These days some of OOP's critics are just as zealous as its proponents were in the 00s.
Golang solves the problems talked about in this article. Except for “encapsulation” which is really just... the author doesn’t like pointers which is non specific to OOP.<p>Why is functional programming better? The author doesn’t really delve into that
I feel that whenever someone complains about OO, it almost always starts with "I tried mapping everything to a class" and I always want to ask "Why?".
Yes! This is basically why my new language is functional, and not OO. I bought in the OO dogma in college, but programming in functional languages is just so much easier.
These posts are tedious, like a stereotypical newly converted non-smoker or vegetarian cornering you at a party.<p>The same arguments about the diamond inheritance problem, and blah blah blah. Funny gun-foot meme...check.<p>I'm not even saying it isn't true. I'm saying that it's boring. Functional programming has it's own set of stupidity and anti patterns. If your favorite language doesn't have any that spring to mind...give it time.<p>Queue the people saying OO is really message passing.<p>Then the Rust people. I guess the world has always been this way, but it makes me think we are screwed as a species.
Hello, OOP (2018)<p>I just recently wrote a Lisp compiler and assembler (for VM) using OOP.<p><a href="http://www.kylheku.com/cgit/txr/tree/share/txr/stdlib/compiler.tl" rel="nofollow">http://www.kylheku.com/cgit/txr/tree/share/txr/stdlib/compil...</a><p><a href="http://www.kylheku.com/cgit/txr/tree/share/txr/stdlib/asm.tl" rel="nofollow">http://www.kylheku.com/cgit/txr/tree/share/txr/stdlib/asm.tl</a><p>Even abused inheritance for logic re-use: see <i>defopcode-derived</i> macro in the assembler.<p>The OOP system is my own---now compiled. :)<p>It's a pleasure to use and makes the code look good.
No bo
It is always seems kind of cute when someone discovers something new and thinks it's a silver bullet.<p>On a side note, .NET is not a language, it's a framework, like JVM. In fact F# runs on .NET and it is purely functional.
I get what he is talking about, but to be honest alI never encountered a situation where I intentionally or unintentionally got to diamond inheritance. I just didn't... As for the add/addAll example, the smart thing to do is just not put too much in the public method or just declare it final...
> <i>For efficiency sake, Objects are passed to functions NOT by their value but by reference.<p>What that means is that functions will not pass the Object, but instead pass a reference or pointer to the Object.</i><p>This is confused garbage, and goes rapidly down hill from there.<p>Reference semantics is required for OOP. The reference is necessary because that <i>is</i> the object. The object's "value" is a concept from the record or structure types of non-OOP languages like C and Pascal. If we pass the value, we are not passing the object, but a copy.<p>In high level languages, we don't even see the reference as a separately declared reference type; that is a low-level concept from "Blub OOP".<p>I'm surprised this blogger's Smalltalk experience didn't set him straight.<p>> <i>If an Object is passed by reference to an Object Constructor, the constructor can put that Object reference in a private variable which is protected by Encapsulation. But the passed Object is NOT safe! Why not? Because some other piece of code has a pointer to the Object, viz. the code that called the Constructor.</i><p>The charitable way to understand this bizarre nonsense is that because the caller of the constructor has a reference to the object, it has access through the reference to the object's "value", and by going through that reference, it should be understood as bypassing the encapsulation of the container which also holds that reference as a private variable.<p>This is laughably confused. Encapsulation means just that the binding is private: the newly constructed object holds that existing object in a private slot. Encapsulation doesn't mean that the embedded/aggregated object's contents are also private to the aggregator. Those are protected by that other object's class!<p>> <i>The Constructor will have to Clone the passed in Object.</i><p>Only in some very specific circumstances when it is necessary for this parent object to have its own instance of an object similar to the one which is passed in: either so that it can mutate this instance without having an effect elsewhere, or else so that it has a snapshot facsimile of the passed object which is immune from changes elsewhere.<p>Such a requirement doesn't always apply.<p>> <i>So much for efficiency.</i><p>When such a requirement doesn't apply, the construction of the similar object or 'deep cloning' will not just be inefficient, but <i>wrong</i>. For instance container object will expect the contained object to react response to events, but instead it actually has a dead copy which isn't receiving calls from anywhere.<p>It's clear from the semantics whether "we want to be composed of that actual object" or "we want to be composed of a similar one, in a similar state to that one's current state".<p>The second situation may require planning and design work. Indeed, not objects can be easily copied.<p>Some other solution may be required, like splitting that object into some state that is easily copied and some part that remains shared. This need not even require a split, just a suitable copy operation.<p>Linux has clone() system call for processes with a bazillion flags to copy this and not copy that; kind of the same thing. Sometimes we share the address space and file descriptors and signal handlers, sometimes we don't.
For anyone not wanting to read the opinion behind the click-bait-titled article, here's the TLDR: the author never learned how to write OO code and is now declaring it dead.<p>Every problem he brought up is easily solvable by writing good code. FYI, I'm a big proponent of FP, but I'm not a proponent of disparaging things I don't fully understand.