top | item 16943512

Goodbye, Object Oriented Programming (2016)

35 points| larryfreeman | 8 years ago |medium.com | reply

39 comments

order
[+] thorell|8 years ago|reply
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.

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.

Diamond problem? Okay, granted. But this still solvable in most languages with interfaces.

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.

[+] tabtab|8 years ago|reply
If you have to tell too many people that they are "not doing it right", then perhaps its too hard to do it right. If you build a paradigm that only Sheldon Cooper can get right and complain when non-Sheldon's "can't use it right", there is a bigger problem. It was supposed to make software design easier and "more natural". If it takes lots of training to get right, that's not "natural".

In general, I find OOP fairly well suited for building utilitarian API's, but NOT for domain modelling. Domain modelling is where OOP failed bigly. When UI/GUI's got more complex, they outgrew OOP's ability also and became a mess. There seems to be a size/scope limit to OOP of subject matter.

[+] jdonaldson|8 years ago|reply
I doubt there's very few OOP hardliners on here, I'm certainly not. So, let me play devil's advocate here a bit.

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.

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.

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.

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!

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.

[+] dvfjsdhgfv|8 years ago|reply
I can't wait for his "Goodbye, Functional Programming" article.
[+] _bxg1|8 years ago|reply
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).

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.

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.

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.

"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++.

The Hierarchy Problem, once again, is solved by composition.

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.

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.

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.

[+] toomchsauce|8 years ago|reply
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.

Why is functional programming better? The author doesn’t really delve into that

[+] amarka|8 years ago|reply
Goodbye Larry, see you in 5-10 years when OOP is back in style!
[+] jstimpfle|8 years ago|reply
Will it come back? Maybe it will be hot among the next generation of programmers that failed to learn from the past. Just like the mistake that is explicit asynchronous programming (e.g. callback hell in node.js) when (cooperative) multitasking has existed for 50 years!
[+] stagger87|8 years ago|reply
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?".
[+] bb88|8 years ago|reply
In Java everything has to be a class.

I prefer C++/Python style where things don't have to be classes. They can just be independent functions.

[+] pbiggar|8 years ago|reply
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.
[+] whitepoplar|8 years ago|reply
Any chance you can talk more in depth about this? I'm really curious! FP seems wonderful, but there are few side-by-side code examples out there.
[+] youdontknowtho|8 years ago|reply
These posts are tedious, like a stereotypical newly converted non-smoker or vegetarian cornering you at a party.

The same arguments about the diamond inheritance problem, and blah blah blah. Funny gun-foot meme...check.

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.

Queue the people saying OO is really message passing.

Then the Rust people. I guess the world has always been this way, but it makes me think we are screwed as a species.

[+] jstimpfle|8 years ago|reply
People need to put it their way to learn. And to some readers these thoughts will be actually new. That's how opinion/experience/knowledge spreads.
[+] suyash|8 years ago|reply
Exactly the post is titled one sided and arguments are completely biased. The author should have started with the post with disclaimer about his pet language.
[+] romanovcode|8 years ago|reply
It is always seems kind of cute when someone discovers something new and thinks it's a silver bullet.

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.

[+] lou1306|8 years ago|reply
Just being nitpicky here, but F# is not "purely" functional (and is not "pure-functional" either). But its OO subset is fairly small indeed.
[+] Zyst|8 years ago|reply
Did you read the end of the article? I mean I get what you are talking about, but I think the author went out of his way to say that he doesn't think FP is going to be a silver bullet.
[+] nathanaldensr|8 years ago|reply
I'm shocked that in the 17+ years .NET's been around, we still hear people say that .NET is a language.
[+] salex89|8 years ago|reply
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...
[+] RealNeatoDude|8 years ago|reply
This article is about OO+[bad language design/patterns].

You can do OO without sharing state with your parent(s).

[+] awinter-py|8 years ago|reply
not sure FP handles fuzzy categories better than OOP

isn't fuzziness why we have topic models and, more generally, ML?

[+] tomphoolery|8 years ago|reply
the year annotation on this article got me :)
[+] kazinator|8 years ago|reply
> For efficiency sake, Objects are passed to functions NOT by their value but by reference.

What that means is that functions will not pass the Object, but instead pass a reference or pointer to the Object.

This is confused garbage, and goes rapidly down hill from there.

Reference semantics is required for OOP. The reference is necessary because that is 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.

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".

I'm surprised this blogger's Smalltalk experience didn't set him straight.

> 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.

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.

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!

> The Constructor will have to Clone the passed in Object.

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.

Such a requirement doesn't always apply.

> So much for efficiency.

When such a requirement doesn't apply, the construction of the similar object or 'deep cloning' will not just be inefficient, but wrong. 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.

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".

The second situation may require planning and design work. Indeed, not objects can be easily copied.

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.

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.

[+] praneshp|8 years ago|reply
[2016]

(not that it adds any credibility ....)

[+] sctb|8 years ago|reply
Updated. Thanks!
[+] _zachs|8 years ago|reply
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.

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.

[+] amag|8 years ago|reply
> Every problem he brought up is easily solvable by writing good code.

I'm curious, how? Would you mind use one of his examples along with some good code?