
Was object-oriented programming a failure? (2015) - open-source-ux
https://www.quora.com/Was-object-oriented-programming-a-failure/answer/Wouter-van-Oortmerssen
======
delinka
Why are there still those who think any advocate of OOP is an advocate of "OOP
or Nothing! All things are Objects! All things are an instantiation of a
class! All things must derive from a root class! etc."?

OOP is a tool. And generally a useful one. Every new programming paradigm at
its inception was going to Save The World and make programming A Better Place.
Turns out, every one if these paradigms is a tool with uses at various times.

So OOP might only be useful in a limited number of cases. I find it
comfortable for categorizing functions: "Here's all the stuff you can do with
a String" or "All windows behave like this..." And if your language is dynamic
enough, you can add functionality to all Strings, not just your String
subclass.

I don't typically find OOP useful for processing many records of data. Perhaps
I might compose an object from a record of data so that a user might edit
their profile in a GUI, but batch processing doesn't usually lend itself to
OOP. But that's my experience and opinion; I bet someone has a good use case
for using OOP while dealing with copious amounts of data.

Back to the topic at hand: Was OOP a failure? No more than lathes are
failures. Not every handyman needs a lathe; not every programmer needs OOP.
But when you do need it, it's a useful tool.

~~~
thehardsphere
> Why are there still those who think any advocate of OOP is an advocate of
> "OOP or Nothing! All things are Objects! All things are an instantiation of
> a class! All things must derive from a root class! etc."?

Because there are many low skill, poorly-informed people who write code still
believe these things. In particular that "OOP" is automatically equivalent to
"better quality code." It’s a sort of cargo cultism that is present in a few
places.

~~~
shadowmint
The irony is that it probably does mean better quality code for most people.

Quality in practical outcomes for building projects, that is, not code
asthetics.

The problem is that 'functional code' means 'spagetti code' for many 'low
skill' people, and 'write once maintain never' perl style code for many other
'smart' people.

Both are rubbish, terrible low quality useless code outcomes.

OOP doesn't fix everything, but its a great lowest common demoninator for code
that does the job. Its not exciting. It has stateful bugs. ...but anyone can
do it and it gets the job done at scale; orders of magnitude better than any
other coding paradigm I'm aware of.

You want a hard problem to solve?

Go figure out a way to make functional programming scale the same way, you'll
start a revolution.

...but in my experience, its the frustrated 'smart' folk who want to write
their maintain-never code who push FP as a _replacement_ for OOP.

~~~
Buttons840
> The problem is that 'functional code' means 'spagetti code' for many 'low
> skill' people

I don't see how that is the case. Even in the most poorly written function you
have code that's working mostly on it's arguments (and maybe some global or
something, since it is poorly written) and then returns a value. How is this
function connected to the surrounding code? We know the answer, it's called in
a single expression and given arguments. You have a single isolated call for a
single run of the function.

In OOP you have to both instantiate a class and then call it's methods. By
simple line count it is twice as complicated to call as a function, and it is
twice as coupled to the code that calls it.

When I look into the internals of functional code I often find myself in a
single isolated function and the functions tend to be on the short side. When
I look into the internals of OOP code I often find myself in a large method
that is part of a class in an inheritance hierarchy and the method uses a
bunch of globals (err, I mean "object variables") and I have to read several
other methods to understand what's happening, because the method I'm
interested in depends on the state left over from other method calls.

In short, objects are a lot more powerful than functions, and thus "low skill"
developers have a lot more rope to make spaghetti with.

~~~
shadowmint
It's not about hidden state; that's just bad OOP. You shouldn't be looking at
the internals, that's the point. It's about modular encapsulation and reusable
components.

> a single isolated function and the functions tend to be on the short side

I can almost guarantee that code was not written by an inexperienced or low
skill coder.

If it was, you'd have a large complex function that took large complex state
as its input, and probably maintained some kind of hidden internal state in
some kind of async deferred loop after it returned or some combination of the
above.

Have you worked with inexperienced FP programmers?

It's not fun.

Inexperienced OOP is a lot easier to deal with, because the entity level API
validation is all you care about; you don't care about how hideously the
internals were implemented as long as the tests pass. There can be any number
of bugs and spaghetti _inside_ the object, but you don't care, because you
don't see it (until it manifests as bugs; but then you just add more tests and
make them go away until all the tests pass).

I think there's a pragmatic aspect to OOP that involves large scale
organizations collaborating on projects that you're not taking into account.

You could argue that a test suite for FP does the same job, and maybe it
does... but the point here is that someone has to define the module level
interface, and how it behaves as a state machine (regardless of if the state
comes in 'pure' and is passed around or is encapsulated internally); and
that's OOP, not an inheritance hierarchy.

~~~
rdnetto
> I can almost guarantee that code was not written by an inexperienced or low
> skill coder. > If it was, you'd have a large complex function that took
> large complex state as its input, and probably maintained some kind of
> hidden internal state in some kind of async deferred loop after it returned
> or some combination of the above. > Have you worked with inexperienced FP
> programmers? > It's not fun.

No pure FP language will allow you to do that without the function's type
signature reflecting that - it would need to return its value in some kind of
state/async monad.

Now, if you're talking about FP in a traditionally OOP language, then I agree
with you, but that's an apples to oranges comparison.

> Inexperienced OOP is a lot easier to deal with, because the entity level API
> validation is all you care about; you don't care about how hideously the
> internals were implemented as long as the tests pass. There can be any
> number of bugs and spaghetti inside the object, but you don't care, because
> you don't see it (until it manifests as bugs; but then you just add more
> tests and make them go away until all the tests pass).

This approach doesn't work for things that are difficult to test. e.g. you can
only ensure your types are thread safe by reasoning about their use of locks,
volatile, etc., because any attempt to test this is dependent on the
implementation details of your runtime (e.g. the JVM) and the amount of load
its under. Best case you get a flaky test, worst case you miss a bug that
blows up in production.

But this is a tangent, because TDD is not specific to OOP - it works just as
well with FP.

> but the point here is that someone has to define the module level interface,
> and how it behaves as a state machine (regardless of if the state comes in
> 'pure' and is passed around or is encapsulated internally); and that's OOP,
> not an inheritance hierarchy.

Pure state is an oxymoron. The idea is not that you pass a mutable argument
in, but that you don't have the ability to mutate data at all. At best, you
can return some instructions on how to mutate (e.g. the state monad), but its
the consumer of your code who decides what to do with that, which prevents you
from hiding side-effects, and simplifies testing.

Defining a module level interface and behaviour is just API design, not OOP.

------
geophile
I view OO as analogous to the earliest control structures added to programming
languages. We all remember "GOTO considered harmful", including generations of
programmers who weren't alive when the letter was written, and may not have
read it. Around that time, language designers realized that GOTOs were used to
implement the same patterns over and over: Conditional execution, looping of
various kinds. And we ended up with if statements, while loops, for loops, and
so on.

Similarly, unfettered access to state was seen to be problematic. If you are
implementing a skiplist, you don't want users of the list to be manipulating
the links directly. You want to expose only the operations, and have the state
accessible only to the implementation. That's encapsulation and
modularization. And then inheritance provides a way to modify modularization
slightly.

OO is really just a few ideas about organizing code and data, and you are free
to use them or not, just as you are still free to use gotos. The hype got out
of hand. I think OO madness was the first vastly overhyped software trend.
Things got bad with all the Janitor ISA Employee examples got trotted out to
explain OO to managers, and then some people believed OO was claiming to
excuse programmers from actually developing efficient code. Anyone using, say,
Java to build a complex software system realizes that OO is used to model
internal things that never get anywhere near a customer-facing API.

There were zealots, there were AbstractFactoryFactoryAdapterFactory nuts, and
the backlash against them is totally justified. But the core ideas of OO are
just obviously good ones, and usable in non-OO languages too.

~~~
hashhar
I agree with your view. Most of the programming language constructs and
ideologies are simply design patterns that been extracted into a single unit
and given a particular name.

------
coldtea
>Was object-oriented programming a failure?

Only ignoring the fact that almost ALL programs we care about, from OSes
(Windows, OS X) to Games, and from Office applications (MS Office, Open
Office) to graphics apps (Photoshop, etc) to NLEs (Premiere, FCPX, Avid), to
IDEs (Eclipse, IDEA, Visual Studio), to major compilers, JITs and runtimes
(LLVM, Oracle HotSpot, MS CLR) etc, including all major browsers people browse
the web through (Explorer, Safari, Chrome, Firefox) and all major Javascript
engines that power the web are written in an Object-Oriented way, and usually
in the way C++ defines it.

~~~
jstimpfle
True, kernels create resource abstractions, which are basically objects. But
they are written using a variety of approaches, and mostly in C.

Also true, graphical applications have elements that lend themselves to
"object" abstractions. But that's not all that goes on under the hood.

I have watched numerous talks from game architects (John Carmack, Jonathan
Blow, Casey Muratori, Mike Acton, and many less well-known) and OO just isn't
a big concern. "Data-oriented Design" is (to offer a different buzzword).

------
mpweiher
OO has been so _incredibly_ successful that we now take what it got us for
granted as we use it every day. It's been backgrounded.

Here's what Fred Brooks (Mythical Man Month and, more pertinently No Silver
Bullet) said at a panel 20 years after NSB:

 _A burst of papers came and said “Oh yes, there is a silver bullet, and here
it is, this is mine!” When ‘96 came and I was writing the new edition of The
Mythical Man-Month and did a chapter on that, there was not yet a 10 fold
improvement in productivity in software engineering. I would question whether
there has been any single technique that has done so since. If so, I would
guess it is object oriented programming, as a matter of fact._

[https://www.infoq.com/articles/No-Silver-Bullet-
Summary](https://www.infoq.com/articles/No-Silver-Bullet-Summary)

------
coldcode
Having been a programmer before OO was invented (or at least available to all)
I would have to say no. Was LISP a failure since generations of descendent
languages have replaced it? Was Fortran a failure because I don't write iOS
apps in it today? Of course not, all of these things are tools you can choose
to use or not. Whether something is a failure is up to the programmer and how
you wield them. If there was one single language/framework/concept/idea/tool
that was perfect we'd all use it - there isn't so we pick something and make
use of it.

~~~
flor1s
Just want to add that Lisp is still famous in symbolic AI and Fortran is great
for numerical computing (it’s a dependency of numpy)

------
moomin
There's people here claiming that the problem is OOP done wrong. Let's talk
about stuff that pretty much every OO language shares:

* syntax that favours inheritance over composition * inability to specify polymorphism over two input types * inability to specify polymorphism over return type (Both of these are symptoms of close identification of type and table) * Syntax that makes generics unwieldy to the point that many think they're just for collections * Inability to make third-party types expose your own interfaces (Clojure manages this. Some languages manage this through monkey-patching, but that's a cure worse than the disease.)

OO is broken. The biggest problem is that we're all so invested in it we have
trouble seeing there's another way.

------
indymike
Started programming in 1982. Object oriented programming was a huge advance -
especially in developer productivity. A side effect was the dramatic
improvement in developer tools: gui builders, IDEs, etc all improved
dramatically. Probably the watershed moment for OO was this NeXT video that
showed the difference: [https://www.youtube.com/watch?v=UGhfB-
NICzg](https://www.youtube.com/watch?v=UGhfB-NICzg)

~~~
zzzzzzzza
going from emacs to eclipse hardly seems like an improvement.

~~~
delinka
emacs to vim, however ... ;-)

------
jpalomaki
I think one major problem with OO was that many people did not really get
object oriented thinking (and I was probably among them). It is very easy to
do objects that are just dummy data container instead of smart things that
interact with each other.

Just think how many Java tutorials started with the procedural "Hello World"
example and then proceeded to introduce objects and taught the idea of
encapsulation by reminding how important it is to protect the private members
by creating a list of get/set methods that are used to access them.

This leads to objects with interface like this:

    
    
      class Person {
        public void setStomachContents(...);
        public void getStomachContents(...);
        public void setThoughts(...);
      }
    

While I believe a "proper" object would have interface more like this:

    
    
      class Person {
        public void eat(...);
        public void listen(...);
        public Event<ProcessedFoodItem> output;
      }

~~~
technion
One of my complaints on the subject is that academia is so fascinated with
OOP. I took multiple courses on the subject, and the issue I'm hitting is that
your "proper" example would probably have failed me a course, because the
"bad" example you've given is exactly what we were taught.

~~~
jpalomaki
Two books that affected my thinking on the subject were Domain Driven
Design[1] by Eric Evans and Object Thinking[2] by David West. Many years since
I read the books and I don't claim to have studied them in detail so I'm not
saying if they were good or bad, but at least I got some ideas out of them.

[1] [https://www.amazon.com/Domain-Driven-Design-Tackling-
Complex...](https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-
Software/dp/0321125215/ref=sr_1_1?ie=UTF8&qid=1489391539&sr=8-1&keywords=evans+object+oriented)

[2] [https://www.microsoftpressstore.com/store/object-
thinking-97...](https://www.microsoftpressstore.com/store/object-
thinking-9780735691308)

------
craigds
Was the word 'was' intended to suggest that OO has died off in some way?

Last I checked, _nearly everyone_ is doing OOP.

~~~
pjmlp
Even the FP languages that managed industry adoption, support some form of
OOP.

------
oblib
Funny how this subject has progressed. I recall writing perl code and being
pretty happy with the results until I heard that "functional" programming was
crap. Soon after Perl added a "OOPs" layer that coders either rejoiced over or
complained about and I couldn't help but think "Do I really need to write code
this way?"

After a couple decades of coding I've come to the conclusion that "easy" is
almost always better. There isn't much code I wrote 20 years ago that anyone
is using today but where it is in use it runs without needing to be updated or
maintained.

Most of my apps are now mostly written in Javascript, and I write them very
much the same as I did in Perl. I use a mix of both "functional" and "object
oriented" methods and don't worry about what others think of it.

Of course, I'm not doing "AI" or anything close to that. I make apps for
business management and they care a whole lot more about the UI, reliability,
and security, than what the code looks like. The only thing I ever get when
showing them code is a glassy eyed look of despair and worry that I won't
stop.

------
threatofrain
I don't think that OO is wrong for all problems, but I do take issue with the
fact that it almost always inherently means distributed state. If you have
multiple objects, then you probably have distributed state.

Sometimes your problem is inherently a distributed state problem, and that's
fine. But OO doesn't care if this is sometimes true. OO pushes people toward
distributed state architecture, and it unnecessarily encourages excess state
splitting even if the problem inherencies don't warrant it.

------
c_shu
One of the common nice features in OOP is polymorphism. You have a
list/set/collection of objects which are of the same type, but also of
different subtypes. They have the same behavior when calling some method and
different behaviors when calling another method.

OOP is not a failure. But overengineering is another thing. (Sometimes I heard
"Never write static function/method! Do it in OOP way!", though it doesn't
make the code simpler or cleaner)

~~~
rdnetto
A counter-point to this is that OOP languages lack support for ad-hoc
polymorphism. i.e. the ability for third-party code to define an
implementation of an interface for a pre-existing type. The two approaches
used to work around this are the adapter pattern, and explicitly taking an
object implementing the desired behaviour as a second argument (e.g.
Comparators in Java).

In contrast, most (typed) FP languages support typeclasses / traits, which
makes a lot of code considerably simpler.

------
watwut
It seems like he is ranting about the properties that allows us to keep
controll over larger codebase.

Data hiding (and immutability) are good thing even as they sometimes force you
duplicate data. So is separation between public and private, no matter what
exact syntax is used to achieve it. Interfaces when done right allows you to
reduce cognitive overload.

I could go on, but really oop was huge improvement over whar existed before -
especially when used where it fits well. Functional programming is improvement
too - especially when used where it fits - which is often place where oop fits
less. The problem is programmers who don't bother to learn them and then they
complain about not understanding them.

------
neals
As somebody who works on many different OOP-projects, could somebody tell me
how I should structure my software if not using OOP?

~~~
greydius
This is the basic stategy that I try to follow as much as possible:

Classes that hold data have no methods (beyond getters/setters). Classes that
implement behavior have no mutable state; they exist as namespaces for the
functionality that they provide.

I've been quite successful with this approach. It leads to code that is easier
to understand than a big ball of stateful objects.

~~~
mattmanser
Someone did this on a project I work on (C#).

Utter nightmare. Loads of repeated code as new programmers didn't know methods
existed, loads of extraneous DTO objects, lots of nested single line methods,
massive code bloat. Hard to find what actually does stuff, hard to use built
in editor functionality.

It's really not a good tactic imo.

I'm undoing it as I go, at one point after having worked on it nearly 4 months
according to git I'd still had a net negative on total lines of code, having
added a ton of new functionality.

Admittedly, it's one of those projects which has had a bunch of
freelancers/contractors work on it, but I personally really don't see what it
added to move the methods off the classes apart from confusion, code
duplication and code bloat.

I see the need for something, on the startup + enterprisey projects I work on
you always seem to end up with at least one mega class that ends up being a
beast, the Order, Person, Customer, Job or Project objects are usual culprits,
but most other classes don't need much past a few basic methods. I'm just not
convinced this programming tactic is it having now seen it in the wild.

~~~
coldtea
> _Admittedly, it 's one of those projects which has had a bunch of
> freelancers/contractors work on it, but I personally really don't see what
> it added to move the methods off the classes apart from confusion, code
> duplication and code bloat._

Moving the methods off the classes would actually lead to less code
duplication -- as now different data that need the same treatment can be
handled with the same methods.

"Loads of repeated code as new programmers didn't know methods existed" seems
like a bigger issue here...

~~~
mattmanser
_as now different data that need the same treatment can be handled with the
same methods._

That just doesn't happen enough in real life to design around.

In the rare instances when you do need to that, it's trivial to handle with
interfaces and a wrapped method that calls a shared function.

~~~
coldtea
> _That just doesn 't happen enough in real life to design around._

On the contrary, I think it does. Especially for web, enterprise and
application programming, 90% of the logic is the same tired data
transformations.

~~~
mattmanser
It'd be nice if you told us what code you're referring to. I've been giving
examples and rough technical outlines how I'd handle problems that needed code
sharing. So far you've given us zilch but naysaying.

Have you got any examples?

I've never had to write identical code on an Order class as a Person class.
Can you give me an example of 90% of the logic being the same on an Order and
a Person class?

Like in C#, the entity framework has mainly done away with all the "tired data
transformations". The equivalents like Hibernate, ActiveRecord, etc. have done
the same in other languages (and were the trailblazers). When I dip into a
data transformation these days it's complex, hand-coded SQL, the tricky bit
that takes time, with a simple data class to handle strong typing, trivial to
write in a minute or two with snippets and auto-completion.

~~~
coldtea
> _It 'd be nice if you told us what code you're referring to. I've been
> giving examples and rough technical outlines how I'd handle problems that
> needed code sharing. So far you've given us zilch but naysaying._

Sorry, why the complaining? We were talking on a more abstract level. Yourself
just gave some anecdote about "Someone did this on a project I work on (C#).
Utter nightmare. Loads of repeated code as new programmers didn't know methods
existed, loads of extraneous DTO objects, lots of nested single line methods,
massive code bloat", that's hardly an example either.

> _I 've never had to write identical code on an Order class as a Person
> class. Can you give me an example of 90% of the logic being the same on an
> Order and a Person class?_

Apart from the data contained without, which process would not be the same?
Most high level operations would be exactly the same: filtering would be the
same (it just needs to accept a predicate), ordering would be the same,
serialization would be the same, etc etc.

For a very simple example, you don't need:

    
    
      persons.sort("age", sort.DESC)
      orders.sort("created_at", sort.DESC)
    

etc, you just need:

    
    
      sortedPersons = sort(persons, cur -> cur.age, sort.DESC)
      sortedOrders = sort(orders, cur -> cur.created_at, sort.DESC)
    

And the same function can work with 100s of other classes and containers.

~~~
mattmanser
A better solution than that has been in heavy use for a decade in C#. Works on
anything that implements `IEnumerable`.

    
    
        db.Orders.Sort(o => o.StartDate)
    

I've also never found ordering code to be the bulk of my logic, but whatever.

Anyway, generics. Without having to muck around with funky designs for your
classes.

------
faragon
In my opinion, the main problem with "OOP", and other contemporary religions,
e.g. "design patterns", "TDD", etc., is that often you face arguments like
"with me, or against me", like if there were no other ways for abstraction,
design, QA, etc. Nowdays the buzzword focus moved to "deep learning" and
"cloud", our new BDD (buzzword driven development).

P.S. Link to the original interview:
[http://www.stlport.org/resources/StepanovUSA.html](http://www.stlport.org/resources/StepanovUSA.html)

------
tldrlol
It's hard to categorize exactly what OOP is exactly, though somehow we are
able to discuss this and mostly agree about it's scope.

It's more encompassing today than the traditional model of sending messages to
objects to make them change their internal state. This model doesn't exactly
lend itself to being great in managing complexity either.

What about the concepts of Encapsulation, Inheritance And Polymorphism? In the
form that they are often employed create more complexity and problems than
they solve in any non-trivial scope.

It's often said that naming things is one of the hardest problems in computer
science. This is particularly applicable to OO style of programming, where the
available code reuse capabilities are so limited as to force a programmer to
write the same blocks of code over, and over and over again in an increasingly
complex codebases, stitching up names along. Seriously, just grep an OO
codebase for terms such as "Adapter", or "Strategy".

You should also find it ironic that the only semblance of progress in the OOP
landscape in the past decade had nothing at all to do with OOP concepts. But
rather it's the incorporation of ideas from Functional Programming into
mainstream OO languages that have led to the biggest productivity gains.

Maybe it's a good tool in some contexts, fine. But as the de facto standard
across an entire industry of solving problems with Software? A mediocre
solution at best!

Object-oriented programming wasn't a failure.

It's an ongoing one.

------
crusso
For computers built in the late 80's and subsequent couple of decades, OOP was
a fine abstraction that furthered software development in many ways. When you
had one thread running your whole program, it was okay to have mutable data
all over the place with complex interactions between parts of your program.
Developers could keep it all straight in their heads, so OOP added some
structure that was very helpful.

Now that computer hardware manufacturers are moving toward providing more CPU
cores that allow for higher degrees of parallelization within single
applications - development strategies that make it easier to keep parallel
processes from working against each other are becoming more preferable.

Looking at OOP's success as binary is inappropriate. OOP was the right tool
for the time and hardware that was available. It served its purpose, but
unless its shortcomings on modern and near-future hardware can be addressed...
it will fall out of vogue and be regarded as the wrong choice to make.

~~~
umanwizard
Ehh, even nowadays, lots of programs aren't CPU bound or for whatever other
reason can't benefit from using more than one core per process.

~~~
crusso
But by the time you are CPU-bound, it's too late to change your programming
language and your whole development methodology.

There's an easy case to be made that starting with a functional programming,
easily parallelizable language from the beginning helps to mitigate the
growing pains that happen later when you discover that you need to take better
advantage of the hardware.

------
pdkl95
"OOP" means, in practice, two very different concepts.

It was probably C++ (and later Java) that interpreted OOP as a mandate that
your types should fit in some sort of hierarchy. Inheritance (usually with
polymorphism) was seen as a primary way to reuse common code. Fortunately,
more and more people are realizing the problems that arise when the real world
doesn't map easily to the overly-simple inheritance hierarchy. This type of
OOP failed a long time ago.

On the other hand, OOP in the original Alan Kay sense[1][2] is about message
passing. This happily lives as a key part of languages such as Ruby.

[1] "I invented the term Object-Oriented and I can tell you I did not have C++
in mind."

[2]
[http://wiki.c2.com/?AlanKayOnObjects](http://wiki.c2.com/?AlanKayOnObjects)

------
unclebucknasty
Part of the problem with OO is the other stuff we heaped on it, while still
calling it OO. So, we're not always assessing "pure" OO when we talk about it.
For instance, immutability and OO are diametrically opposed concepts.

Objects were supposed to encapsulate data (state) and expose operations that
would mutate that state in a controlled fashion. But, we then imposed this
immutability requirement, whereby we create these objects very explicitly with
long-winded builder patterns, then make copies of the data when necessary,etc.
At this point, we have effectively externalized the logic around the object's
state and the object itself is nothing more than a C-style struct.

Sure, immutability has its advantages, but we should acknowledge that it's not
a OO-friendly concept.

~~~
hasbot
Your comment reminds me of the class responsibility discussions we used to
have. Should we have gasStation->fillUp(vehicle) or
vehicle->fillUp(gasStation)? There is no right answer and depends on the
situation.

~~~
jimmaswell
What seems most natural to me is that the gas station would have a
fillUp(IFillableWithGas) method that takes an object with the IFillableWithGas
interface, which has a method that returns the amount it was able to take and
a method to put that much in. The gas station is the one "doing" the action
"to" things that are able to take gas, and it's the gas station's
responsibility to know how to pump up the gas from the tank and calculate the
price. gasStation->fillUp could look like (leaving it at a gas station with
only one pump for simplicity)

    
    
        float price = 0;
        while (!vehicle.gasIsFull()){
            Gas gas = this.undergroundGasTank.getGas();
            vehicle.depositGas(gas);
            price += gas.getAmount() * this.gasPricePerGallon;
            this.display(price);
        }
    

It would be out of place for a car or gas canister class to know how to use
the undergroundGasTank object and to calculate the price themselves.

~~~
hasbot
LOL. Who said anything about an underground gas tank, pricing, or a display?
If you're adding pricing, you have to add a payment system. It'd be out of
place for a Vehicle to know anything about paying a bill. Objects just _model_
reality; they don't have to mirror reality.

~~~
jimmaswell
It's just a demonstration of how the hierarchy works in the abstract. And it's
just displaying the price on the meter, not saying the "car" has to deal with
that. The driver would, or the player, if you look at this like game code,
which would make sense.

~~~
hasbot
Dude, it was just an example for a style discussion. You're missing the point
of the discussion and way over-engineering the example.

~~~
jimmaswell
I'm just saying I don't think the "There is no right answer" statement works
here because there seems to be one right answer to me.

~~~
hasbot
It's weird how inexperienced people are the most rigid and dogmatic.
Experienced people know that there are always multiple ways of doing
everything.

~~~
jimmaswell
If you have to resort to implying lack of experience is the only reason
someone wouldn't like your example, that doesn't reflect well.

------
ZakTaccardi
I started off a recent project in Java (heavy use of RxJava). Over time it
migrated to a largely Kotlin codebase, which lends itself well to either OOP
or functional.

I realized, so many of my method calls on my objects were only ever used once.
Sometimes I'd create a class which just had one method. I had to assign a good
name to this class, and it's method. I've since switched to heavy use of
extension methods in Kotlin, and found I was mocking less for many tests, and
writing less code that accomplished more. And variable naming was simpler.

At the end of the day, a good blend of OOP and functional programming are
where it's at

------
quickben
His points aren't OO. He claims overengineering. That can happen in any
setting.

~~~
thehardsphere
True, but it's more likely to happen in an OOP setting. Especially if
functions are not first class objects. Then you start wrapping things in
classes and turning them into methods when you otherwise wouldn't, and that's
how you eventually go down the road of FactoryFactoryFactoryFactories if
you're not careful.

~~~
seanmcdirmid
It's just likely to happen in a functional setting. E.g. That quadruple
indirect function applied via some obscure algebraic pattern can be just as
bad as an FactoryFactoryFactoryFactories.

We just don't see it because FP is not as common, but spend any amount of time
with some Haskell programmers and you'll see the hazard is just as real.

------
alkonaut
It's not a failure, and it was an improvement over some paradigms. But it's
been oversold and parts of it are terrible. It was sold on the promise of
_reuse_ but accomplishes it at the expense of understandability and
maintainability. As such it's a huge foot gun: it's very easy to solve complex
problems with complex solutions, and that's not a feature it's a bug.

The right level of OO is "very little". Some mostly-FP languages like F# are
closer to the ideal level of OO than the mostly-OO languages.

We learned a lot from the Java age, and new languages show it (Swift, Rust,
...)

~~~
jimmaswell
>It was sold on the promise of reuse but accomplishes it at the expense of
understandability and maintainability.

I have never dealt with code in practice that was less maintainable and
understandable because of OO. Do you have a specific example?

~~~
alkonaut
I think it's usually the case that mutability and inheritance is overused
leading to deep and/or unnatural abstractions and code that is hard to reason
about. Working with a hierarchy many levels deep with overrides on every level
means it's very hard to reason about the code as the call stacks ride an
elevator up and down the class hierarchy.

Don't get me wrong - this is not an inherent drawback with OO, this is because
it's _applied incorrectly_. Making bad abstractions or a class hierarchy 10
levels deep is _bad_ , and it's possible that the same inexperienced developer
would just make another mistake in another paradigm, leading to some other
problem instead. My issue is perhaps more with the design of popular OO
languages (Java, C#, C++) than with OO as a concept.

A very good OO language could be made by simply encouraging best practices and
removing the biggest warts (no null, immutability by default, support for sum
types, encourage pure functions, discourage deep class hierarchies...).

Experienced programmers can write maintainable code in any paradigm, but I
think the paradigms should be judged by how well it helps average programmers
write maintainable code.

~~~
jimmaswell
A codebase I work on at the moment has some hierarchies go to at least 6 or 7
levels, and I haven't had a problem with it. The way it's used doesn't hurt
the ability to reason about it, it's just a logical progression of categories
of objects getting more specific as they branch out. This is at the same time
that a lot of composition and components are used.

I'd say excessively deep class hierarchy or bad abstractions are still a lot
better than similarly "bad" imperative or other code, not sure about
functional though.

~~~
alkonaut
> it's just a logical progression of categories of objects getting more
> specific as they branch out.

That's the benefit of it. On a type abstraction level it's perfect to write
Organism > Animal > Dog. That's the benefit of inheritance. The drawbacks are
more subtle though and manifest like mad stacktraces that are very brittle to
change (what happens when I change what I return from this method? Who are the
downstream and upstream users? What does this stacktrace mean? When it becomes
difficult to reason about is when you have all these kinds of abstractions
executing at the same time - which easily happens.

at Dog.CreateName at Animal.CreateName at Dog.SetNewName at Animal.ResetName
at Animal.Create at Organism.Create...

------
Pxtl
Oortmessen/Aardappel's point here isn't that OOP is dead. I've seen his code
(he runs the OSS Cube engine games and has made multiple hobby languages), he
writes in C++ and uses objects where needed.

His point is in slavish love of OOP concepts. Of excessive abstraction and
storing state everywhere. I've worked on multiple projects where I can only
describe the code as "bureaucratic". Oodles of little classes imperiously
demanding you work through them to get anywhere inspite of terrible mismatches
and the overcomplication it creates.

------
nabla9
Pure OOP programming (as Alan Kay intented) never took off in the large scale.

The good thing about these OO-inspired class based languages (C++, Java, etc)
is that it has forced people to write their spaghetti code inside modules
(classes) with documented interface. They also made using algebraic data types
common.

~~~
Ace17
A must read, from Alan Kay himself:
[http://lists.squeakfoundation.org/pipermail/squeak-
dev/1998-...](http://lists.squeakfoundation.org/pipermail/squeak-
dev/1998-October/017019.html)

"The key in making great and growable systems is much more to design how its
modules communicate rather than what their internal properties and behaviors
should be."

------
Koshkin
When using any methodology one could either be successful or fail. OOP, in
particular, has been very successful as a user interface engineering
methodology. Windows API is one example. Even when taken to the extreme
(Smalltalk, Ruby), it can be relatively successful. It is just that as
everything else it is only an approximation to the sheer complexity of the
world we are trying to model, and so one has to be careful enough not to end
up following the road to complexity hell - the one that is paved with the good
intentions to try and use the OOP as a way of managing complexity in the first
place.

------
SNBasti
Adding my two cents :

To some point I can follow the argumentation of the author. However, I do not
see any superior alternative to the OO paradigm especially combined with Unit
testing. Thus, HN, what are the alternatives to OO ?

~~~
mmphosis
procedural / functional / declarative / concatenative

I would not call these alternatives, as others have commented these are all
tools, no one is superior. In my opinion, C++ is a failure. I wouldn't call
Object Oriented a failure. I do think OO could be way better.

~~~
flor1s
I've been studying about C++ lately. It has proven to be a lot harder to learn
than PHP, JavaScript, Java, C# and Haskell. It's one of the most powerful and
widely used languages around however, so calling it a failure seems rather
unfair.

------
Kequc
Objects are useful. But shouldn't define an entire application unless it's
useful to do it that way. In an enormous number of cases it's a better idea to
use something else.

So, yes. OOP, being that absolutely everything needs to be an object is absurd
and failed. But the people who take it the other direction and say nothing
should be an object are just writing even more complicated, more difficult to
reason code.

Use tools as tools and drop the ideologies, for a happier and brighter world.

------
dr0verride
> Underneath all of this lies the fallacy of thinking that you can predict the
> future needs of your code

The point of OOP isn't to predict the future. You should be actively aware
that you cannot know the future and leave youself room for change.

------
k__
The idea is good, but the wide spread implementations are rather bad.

Funny that with JavaScript a rather undervalued OOP model (prototype based)
got such a spread :)

~~~
mpweiher
Sturgeon's Law:

"Sure 90% of OO is crap. That's because 90% of _everything_ is crap"

[https://en.wikipedia.org/wiki/Sturgeon%27s_law](https://en.wikipedia.org/wiki/Sturgeon%27s_law)

~~~
k__
There are laws for everything :D

~~~
otalp
Or more precisely, 90% of everything.

------
comboy
> It is as if mathematicians would start with axioms. You do not start with
> axioms - you start with proofs.

Oh?

------
kwhitefoot
No.

