
The faster you unlearn OOP, the better for you and your software - jxub
https://dpc.pw/the-faster-you-unlearn-oop-the-better-for-you-and-your-software
======
mabbo
I'm always confused when people criticize OOP, because most of the time the
criticisms they use are just plain bad programming. Or they're using hyperbole
that isn't really useful.

You want to know why OOP is useful and common? Because it's easy. Easy things
allow for faster development, faster onboarding of devs. Humans need a mental
models of things and OOP very explicitly gives it.

But like most easy things, OOP still works well enough even when it's done
badly. That's not a bad thing. Working software beats non-working software.

We shouldn't be telling people "stop using OOP! It's only for idiots!". OOP
will be here forever. We should be teaching people how to do OOP right, what
the pitfalls are that lead to bad design, and how to take badly designed OOP
and fix it.

~~~
chx
> You want to know why OOP is useful and common? Because it's easy.

With as much proof as you have given, let me offer you a counterargument: it
is common because academia loves OOP. It's easy to teach, it's easy to test.
It is most decidedly not easy and very often not useful.

My favorite example of how everything falls apart in due time is the color of
a car. That's it, right? A car has a color. A Porsche Panamera might be a
"carbon grey metallic" and it's stunning, but that's just one color still.
Aye, up until the Mini Cooper tells you they need _two_ colors. This world
doesn't fit the OOP straightjacket. Your programming course does but the real
world doesn't and when it doesn't then pain follows.

~~~
fmap
> it is common because academia loves OOP.

Absolutely not! I doubt that anybody was ever taught OOP in an academic PL
course, unless it was really an "introduction to programming" course, or their
professor was working on this topic at the moment. The meaning of a program in
an object oriented language with imperative features and inheritance is not
pretty.

There are aspects of object oriented programming that are useful for
structuring programs (hidden state) and others which are a recipe for disaster
(recursive types). This complexity is always swept under the carpet when
teaching OOP. Classes/inheritance/objects are always taught via imperfect
analogies, which should tell you everything you need to know about how "easy"
OOP really is.

No, the reason it is taught so widely is purely practical. It's a popular
paradigm and a lot of practical programming projects might need an OOP
background.

\---

Edit: Just to be clear, I'm not trying to say that OOP is bad per se.

The information hiding and namespacing aspects of objects are really useful,
both in theory and in practice. It's just that I think that implementation
inheritance is an imperfect way of facilitating code reuse and not something
you should teach to new students...

~~~
scarface74
_The information hiding and namespacing aspects of objects are really useful,
both in theory and in practice. It 's just that I think that implementation
inheritance is an imperfect way of facilitating code reuse and not something
you should teach to new students..._

And most professionals agree with you. “Prefer aggregation over inheritance.”

Which by the way Resharper makes really easy. You add a private variable to
your class of the type you want to aggregate and it creates wrapper methods in
your aggregating class that just calls your other class.

------
eitland
I read this quickly to see if this was the piece that should convince me.

It was not. It is, IMO, a collection of strawmen.

People have abused OOP? Yes.

But

\- citing FizzBuzz Enterprise Edition (which is really funny even for us
Java/.Net developers because it is so horribly wrong)

or writing this

\- _Because OOP requires scattering everything across many, many tiny
encapsulated objects, the number of references to these objects explodes as
well. OOP requires passing long lists of arguments everywhere or holding
references to related objects directly to shortcut it._

again IMO, demonstrate that the author never really understood OOP.

What probably is true however is that a lot of people should unlearn the OOP
they learned in school.

~~~
bvrmn
> What probably is true however is that a lot of people should unlearn the OOP
> they learned in school.

Can you provide references for proper OOP?

~~~
hoorayimhelping
[https://en.wikipedia.org/wiki/SOLID](https://en.wikipedia.org/wiki/SOLID)

I wish they would have taught me this in school. Instead, I learned that a cat
is an animal, and a car has wheels, and a car is a vehicle. But not what any
of these things have to do with one another and how to actually use them.

~~~
bvrmn
I saw many SOLID code bases hard to grasp and maintain because implementation
hides data flow. The most evil workers are [D]-purists.

------
jryan49
> The vast majority of essential code is not operating on just one object – it
> is actually implementing cross-cutting concerns. Example: when class Player
> hits() a class Monster, where exactly do we modify data? Monster's hp has to
> decrease by Player's attackPower, Player's xps increase by Monster's level
> if Monster got killed. Does it happen in Player.hits(Monster m) or
> Monster.isHitBy(Player p). What if there's a class Weapon involved? Do we
> pass it as an argument to isHitBy or does Player has a currentWeapon()
> getter?

Not saying this is the right way to do things but, if you're actually going to
go 100% OO on something:

Player.hits(Monster) returns Hit

Hit takes a Player and a Monster in constructor, and has with(Weapon)

You end up with:

Player.hits(Monster).with(Weapon)

Then Hit reaches into said objects and deals with changing the HP, and XP. You
then have encapsulated the details in the actual Hit itself, which seems
correct.

It does read kind of nicely IMO...

~~~
crazygringo
Great point... but doesn't it continue to prove the author's point that this
is needlessly complex?

It strikes me as bad design if something as simple as an action (hit) now
needs to become it's own _class_ that is instantiated merely to execute a
single function and then have to delete itself. That just feels like insane
overhead/boilerplate, no?

The argument here is that it's far better to have player and monster be simple
data structures, and a single function _hit(player, monster, weapon)_.

~~~
jryan49
The Hit class may be a Singleton and only instantiated once. Creating a class
is like 3 actual lines. Also at least in Java the Hit class can be an inner
class of the Person class. It just feels like name spacing in that case.

It is needless complex if the code is simple.

This solution is more flexible that just a pure function. If you have
different players who use different hit strategies how do you handle that with
just a pure function? Lots of if statements in the function? Passing in
lambdas in every case you call the function? Then you could curry the function
and call it something different too and that works I guess. OOP shines when
you have lots of different ways things can work in different combinations. OOP
is a tool like other programming paradigms, you use it when it solves your
problem better than the other ways.

~~~
gameswithgo
Languages that force you to use the singleton pattern really ought to just let
you write A FUNCTION

~~~
jryan49
A lot of OOP languages have added method references, and lambdas in this day
and age.

------
hliyan
This has been shared on HN many years ago, but I'm linking again in case there
are younger engineers who might be unaware of this classic rant: _Execution in
the Kingdom of Nouns_ : [https://steve-yegge.blogspot.com/2006/03/execution-
in-kingdo...](https://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-
of-nouns.html)

~~~
nyc111
That was great. I read it for the first time. Similar scenarios happen in so
many other fields. Some bad idea takes hold. Then schools teach it. Then more
people invest time learning it so that they cannot admit it is bad and this
goes spreading like wildfire and become sacred...

~~~
hliyan
And then someone discovers that the old way was better and gives it a new
name. When I was in school, functional programming was called "programming".

------
ced
I've never liked classical OOP much, but multiple dispatch is a lovely
paradigm. One doesn't define _classes_ per se, but rather just plain old
boring structs.

    
    
       struct Player
           xp::Int
       end
    
       struct Monster
           hp::Int
       end
    
       function hit(p::Player, m::Monster)
           p.xp += 10
           m.hp -= 20
       end
    

The nicest thing is how one one doesn't need inheritance to "add a method" to
an object. One just defines my_function(s::String) to be whatever, and it
doesn't interfere with anyone else's code.

~~~
jcelerier
> One doesn't define _classes_ per se, but rather just plain old boring
> structs.

in which language are there differences between classes and structs ?

~~~
wffurr
"struct" here is meant in the same sense that the author of the post refers to
"PoD objects". Just data in public fields.

Whereas a "class" is usually thought of as private data exposed only through
methods.

There is no language that enforces this distinction; it's purely by
convention. C++ makes it a little simpler by having a different default access
level.

In any case, you are being needlessly pedantic and missing the point.

------
crazygringo
A lot of these initial points I don't think are relevant -- you can model your
data in objects, data structures are complex because business needs are
complex, data models wind up having implicit graph dependencies as well...

BUT, "cross-cutting concerns" is where I think the main valid argument is. In
my experience, OOP is just way too _restrictive_ of a model, by forcing you to
shoehorn data and code into an object hierarchy that doesn't reflect the
meaning of what's going on.

So I totally agree with the conclusion: just store your data in "dumb" arrays
with hash tables or database tables with indices... be extremely rigorous
about defining possible states... and then organize your functions themselves
clearly with whatever means are at your disposal (files, folders, packages,
namespaces, prefixes, arrays, or even data-free objects -- it all depends on
what your language does/n't support).

~~~
gerbilly
>In my experience, OOP is just way too restrictive of a model...

Maybe, but if it's cross cutting concerns that bother you, just combine OOP
with an aspect oriented programming library.

~~~
coolaliasbro
Exactly! So long as the developer approaches the solution with the expectation
of scaling and extensibility from the get, this should not be a problem.

------
corebit
> Data is more important than code

Nope. Right there at the beginning is where the author goes off track.

Computation itself is the most important aspect of computing. Code and data
are just complexity to manage.

> Do I have a Customer? It goes into class Customer. Do I have a rendering
> context? It goes into class RenderingContext.

I whole heartedly agree with this. The naive approach to domain modelling is
to classify the primitives of a domain into classes and stop there. In
actuality, the processor of those primitives is likely what your class should
be, and those primitives ought to be methodless data structures.

I.e., OrderFulfiller instead of Customer and Part classes.

~~~
matwood
I disagree. SICP says "“In programming, we deal with two kinds of elements:
procedures and data.” If we reduce that further it is really just data.

~~~
corebit
There is no one without the other.

The data is unintelligible randomness without some algorithm to process it

The code cant exist without some data schema to reference and has no value if
there's no data instances to process.

------
agumonkey
The problem with OOP is that it became so ubiquitous. Everything had to be OO,
millions of hours spent trying to fit everything inside absurd taxonomies.

There's good bits in OO. You can find articles about how parameterizing large
`switch` statements into objects can lead to obvious improvements.

My only conclusion is to bet on biodiversity~. I learned so much in relational
(db) logic, functional programming, logic programming, stack languages (forth
threaded code) etc etc. As soon as your brain sense something useless discard
it and find another cool trick/theorem to grok.

------
jmartrican
I think for enterprise type software OOP works well. It easily allows us to
re-use code and solve common problems once in a parent class and have that
solution easily propagated to child classes.

However, when developing a video game, I ran into quite a few OO design
conundrums that IMO were the hardest programming problems to solve in my
career. I started looking into data driven design, and while I never changed
my code to implement it, it looked like it might have been easier for the
video game. I do not know for sure. But I do know that getting OO right in the
video game I was implementing was daunting. Maybe I was doing it wrong. The
one issue we kept running into was how to design it so that the flow of
dependencies flowed in one direction. That is to say, classes should not
require references to classes that were higher up the food chain, and vice
versa. It sucked when you realize that your Bullet class requires a reference
to the BattleField class when the BattleField object was not being passed down
through all the intermediate objects that separated the two. I would be
willing to say that it could have been poor design, or rather not realizing
that dependency earlier in the process to deal with it. But many things we did
not know till the requirement or change came up. Then it was programming
somersaults to deal with it. Eventually we did get better at re-arranging
things as things came up, basically we got used to having to change a lot of
the design at a drop of a dime.

I do not know if data driven design would have helped, but it did sound like
it was worth a shot. I must admit though, I do remember a data driven program
i worked on, and it bothered me how much data had to be passed around that was
not relevant to the method/class that was using it. And a lot of data got
lumped together out of convenience.

------
partycoder
Bashing imperative + structured + OOP is valid if you have a viable
alternative. That viable alternative is proper namespacing, modularity and
functional programming.

If your alternative is another form of spaghetti your problem is not OOP. Your
problem is the way you build abstractions.

If your procedures and functions, the foundation of your program, are poorly
thought, then you laid a shitty foundation for everything that follows.

------
koonsolo
A language has 2 main purposes:

1\. communication

2\. representation of concepts

1 is pretty obvious, and for a programming language this means communication
between a person to a computer

2 might not be as clear, but if you know that people cannot count in languages
that have no numbers, it becomes obvious. There is a tribe that only has 0, 1
and many, and guess what, they can't tell the difference between 7 and 8.

Now back to programming languages and their communication between computer and
programmer: the old programming languages were very close to the computer. As
languages evolved, they started to be become 'human', where it is easier for
us to read and write them.

OOP in that sense leans very close to concepts of normal humans. Objects,
things objects can do, objects have separate responsibilities, etc. It's easy
for a human to have such a model inside his head, because we already do this
every day.

Now as a programmer, most of the things that I need to do is make a
representation of the real world into a program. Since the real world is made
up of things that do stuff, it's easy to model it in such a concept.

Most arguments against OOP always come from either a theoretical or academic
background.

But in the real world, with real companies, real problems to solve and real
programmers, OOP is used. Because it lends itself really well for representing
the real world in a computer model.

EDIT: not saying that anyone that doesn't use OOP isn't a real programmer. But
those people are more into the algorithmic or mathematical problem space, not
a problem space where a real-world concept needs to be modeled. Most software
is like the latter, and therefore most programs are OO. Is it the best
solution for everything? Definitely not.

~~~
hliyan

      OOP in that sense leans very close to concepts of normal humans. 
      Objects, things objects can do, objects have separate responsibilities, etc.
    

This is not entirely accurate. Human languages are closer to functional
languages: they have verbs that operate on nouns. Verbs are not attached to
nouns, but rather, the operation of the verb is dependent on the noun.

~~~
dwaltrip
I think the claim may have been that the brain is usually doing something more
akin to "noun.verb(...)", rather than "verb(noun, ...)".

It's a very interesting question. The concepts of agency and intention are
very important in human cognition. If we hear a sound, we wonder if some
intentional agent (predator, enemy, etc) that we need to be aware of caused
the sound. Or if it was something inanimate like the wind rustling a tree.

The OOP paradigm seems to map more closely to agents taking action. But
perhaps my speculations aren't well grounded. I'm not sure.

~~~
mercer
It _is_ a very interesting question. As an FP fan, I'd argue that we model the
world primarily in terms of the actions we want to perform, with the objects
secondary. But I'm obviously biases.

Furthermore, perhaps how we actually model the world mentally is or should not
bear much of a relation to how we do so in code.

I haven't made my mind up about these things, even though I lean towards the
FP approach in my day to day coding. But I love (constructive) discussions
about the issue because somehow I feel they're about more than just 'making
shit work'. Aside from the occasional flame-war I really like the discussions
on HN about this stuff, and usually there are at least a few comments that
give me new insight into both OOP and FP.

------
jabajabadu
This article seems to fit the template: Here are some abstract reasons why
paradigm X is bad, and here is a class of problems that have a more
straightforward solution in paradigm Y, therefore paradigm Y is better than X.

The real message here is that if you have a problem that nicely maps onto a
relational database then use the database-like approach instead of OOP.

In my domain, I work on algorithms for a very specialized class of graphs
whose structure and manipulation must obey a diverse set of constraints. I
have tried implementing the core ideas using multiple popular paradigms but so
far I did not find anything better than OOP.

------
alasdair_
> OOP programs tend to only grow and never shrink because OOP encourages it.

Most long-lived programs tend to grow, because people add new features to
them. This isn't something unique to OOP.

As for growth of OOP programs in particular - does no one ever refactor
anything? Shrinking OOP code through refactoring is a daily occurrence at
almost every job I've ever had.

------
adnzzzzZ
>The vast majority of essential code is not operating on just one object – it
is actually implementing cross-cutting concerns. Example: when class Player
hits() a class Monster, where exactly do we modify data? Monster's hp has to
decrease by Player's attackPower, Player's xps increase by Monster's level if
Monster got killed. Does it happen in Player.hits(Monster m) or
Monster.isHitBy(Player p). What if there's a class Weapon involved? Do we pass
it as an argument to isHitBy or does Player has a currentWeapon() getter?

As an indie dev this is something that I struggled with early on and my
solution so far has been to choose the most obvious place where all those
things should happen and just do it there (in this case it would be on the
Player, in other less obvious cases it gets more fuzzy). What does the non-OOP
solution for this problem look like?

~~~
geowwy
> when class Player hits() a class Monster, where exactly do we modify data?
> Monster's hp has to decrease by Player's attackPower, Player's xps increase
> by Monster's level if Monster got killed. Does it happen in
> Player.hits(Monster m) or Monster.isHitBy(Player p). What if there's a class
> Weapon involved? Do we pass it as an argument to isHitBy or does Player has
> a currentWeapon() getter?

I don't see how this is a problem unless you think programming objects
correspond with physical objects.

My first thought is make a separate Swing class representing the player
swinging their weapon. There's probably an even better way to do it but this
gets around the issues mentioned above.

    
    
        class Player {
          fun takeSwing {
            swing = new Swing(
              this.currentWeapon,
              this.location.offset(this.direction)
            )
            if swing.killedMonster {
              this.xp += swing.monster.level
            }
          }
        }
    
        class Swing {
          fun new(weapon, location) {
            this.weapon = weapon
            this.monster = findMonster(location)
            if this.monster != null { this.monster.takeHit(this) }
            this.killedMonster = this.monster != null && this.monster.dead
          }
    
          fun damage {
            return this.weapon.baseDamage
              + this.weapon.bonusDamage
          }
        }
    
        class Monster {
          fun takeHit(swing) {
            this.hp -= swing.damage - this.defence
            if this.hp <= 1 { this.die }
          }
        }

~~~
segmondy
Good example, I think that's why people struggle with OOP, they do think that
"programming objects correspond with physical objects". This is the same
reason they struggle with storing states in databases because they try to map
OOP to tables.

------
lispm
Some things never die. comp.object on usenet (15+ years ago) had a regular
'guest' explaining why table-oriented programming is better than OOP:

[http://www.oocities.org/tablizer/top.htm](http://www.oocities.org/tablizer/top.htm)

~~~
antialias
In the context of creating a formal model for decision-making, yes table-
oriented design can be a superior choice.

[https://www.hillelwayne.com/post/decision-
tables/](https://www.hillelwayne.com/post/decision-tables/)

------
Const-me
OOP is not a silver bullet but for some classes of problems it's the best tool
available.

That's the reason why all good rich GUI frameworks are OOP-based, including
HTML DOM we use on the web. GPU APIs, OS kernel APIs are OOP-based as well.

~~~
mercer
I don't necessarily disagree, but wouldn't you agree that libraries like React
seem to pull GUI's toward a more FP approach?

~~~
Const-me
This react? [https://reactjs.org/](https://reactjs.org/) Their web site says
following:

> Component-Based

> Build encapsulated components that manage their own state, then compose them
> to make complex UIs.

Wouldn't you agree that components managing their own state is a textbook
definition of OOP?

They even have inheritance-based examples on their main page:

> class HelloMessage extends React.Component

~~~
mercer
Yeah, that's a fair point. React isn't purely functional, but in practice I'd
say it still leans heavily toward a functional approach

You're encouraged to keep state only in top-level components, or in a
functional-style state management library like Redux, and pass the data as
props/parameters to pure components that are just functions. There's a huge
emphasis on immutable data, and composing your various components/functions,
passing them as props, etc.

The fact that React switched to using classes makes it seem less functional
than it is, and honestly I'm not entirely sure why they decided to do so.

Anyways, you're not wrong, but the point I was trying to make is that React is
definitely much more functional than other/older approaches to GUIs, and is
popular in (large?) part because of that difference in approach.

~~~
Const-me
> You're encouraged to keep state only in top-level components

Doesn't state grow unmanageably large for complex GUIs?

> React is definitely much more functional than other/older approaches to GUIs

I'm not sure about that. Take a look, both projects are much older:
[https://github.com/dotnet/reactive](https://github.com/dotnet/reactive)
[https://reactiveui.net/](https://reactiveui.net/)

~~~
mercer
> Doesn't state grow unmanageably large for complex GUIs?

Yes, and there are various ways to make this less of a problem. Still, React
generally favors explicitly passing props down the component hierarchy,
keeping the actual UI bits pure functions and composing them in various ways
that is typical of FP.

> I'm not sure about that. Take a look, both projects are much older:
> [https://github.com/dotnet/reactive](https://github.com/dotnet/reactive)
> [https://reactiveui.net/](https://reactiveui.net/)

Perhaps I should've specified that React, _as a very popular_ 'GUI' library,
is much more functional than many of the _very popular_ libraries that came
before it.

Anyways, my point was not that it's the first of its kind, or 'fully' FP, but
rather that it's an example of how FP-style UI libraries can be a good
solution, and even be popular _because_ they're less OO in nature.

~~~
Const-me
> it's an example of how FP-style UI libraries can be a good solution

On the lower level, FP approach indeed sometimes causes much cleaner
architecture, even for GUI code.

My point is, there’s no good alternatives at higher levels, where you want to
build complex systems by combining components developed by different
people/companies.

> and even be popular because they're less OO in nature.

That’s debatable. I don’t think the main reasons why React is popular are
technical ones. Facebook is popular, and half year ago it’s market cap
exceeded $600B. It’s $392B now but still it’s a huge company with 2.2B monthly
active users. Many people want to achieve such success and view their
technology as a silver bullet.

P.S. I’d like to add that OOP and FP are almost completely orthogonal. Here’s
a good article about OOP in FP languages: [https://medium.com/@gaperton/let-
me-start-from-the-less-obvi...](https://medium.com/@gaperton/let-me-start-
from-the-less-obvious-thing-7f49e87a45ca) And many traditionally OOP languages
adopted a lot of FP stuff: C#, JS, to lesser extent even C++ have now a lot to
offer for functional-style programming.

------
DanielBMarkham
There's something very important here. It also tends to be overstated. As a
former OOP guy, I struggle with explaining what's going on with people that
don't see it yet.

Perhaps beginning with praise might work best. OOA as a group analysis tool is
probably one of the most powerful things coming out of computer science in the
past 50 years. Oddly enough, nobody does it much. Many if the problems this
author brings up with OOP actually work for the best in OOA.

It's not all bad. But there are problems with where we are. Big problems. We
need to understand them.

------
3pt14159
> At its core, every software is about manipulating data to achieve a certain
> goal

> This part is very important, so I will repeat. goal -> data architecture ->
> code.

Wait, what? No. That isn't what you just said. You said my goal was my goal
and manipulating the data was the way to achieve that goal.

Take Shopify. They had a goal: Make a ton of money by running ecommerce
stores.

They used OOP. They IPO'd and they're doing great.

You can argue all you want about how they would have done better if they'd
done some other programming style, but the reality is that almost every
startup that I see win in fields like Shopify's (where there are a ton of
different concerns with their own, disparate implementation specificities[0])
do so with OOP codebases.[1]

In large corps like Google non-OOP with typed languages like Go might work
great. Streams of data and all that. But for startups it's too slow. OOP is
agile because you get some data and you can ask it "what can you do?" and you
can trick functional or logical programming languages into kinda doing that
too, but they do it poorly.

[0] Even wording this in a non-OO way was a stupid waste of time. I could have
just said "different models and methods" and 99% of the people here would have
nodded and the 1% would have quibbled.

[1] Some startups like WhatsApp are a bit of an exception, but even YouTube
used Python.

------
VLM
Sometimes the best way to decide what to do, is a OOP-like 100,000 line long
legal code. Sometimes the best way to decide what to do, is something short
and sweet yet possibly not entirely clear, like the Ten Commandments. When
what the original designers chose was correct, everything will work quickly
and reliably. When they don't, you'll suffer for a long time. Given that,
you'll spend almost all of your wall clock time suffering and complaining
about the designers selection being wrong. With a side effect of most of your
suffering will be due to poorly implemented examples of the dominant paradigm.
"AKA OOP SUX"

In summary, given all of the above, there are two true statements that OOP
works AND simultaneously you'll spend almost all of your mental effort on OOP
not working. Generally, OOP being inappropriately hyper dominant at this time,
means that non-OOP solutions will utterly master some very low hanging fruit
for first movers who abandon OOP.

I've seen some truly horrific object relational mappers trying to connect OOP
to inherently functional software APIs, hardware device interfaces,
"chronological engineering" in general, and persistent data stores. Not
surprising if you're working in those areas, abandoning OOP will lead to
massive success.

------
ttty
> The vast majority of essential code is not operating on just one object – it
> is actually implementing cross-cutting concerns. Example: when class Player
> hits() a class Monster, where exactly do we modify data? Monster's hp has to
> decrease by Player's attackPower, Player's xps increase by Monster's level
> if Monster got killed. Does it happen in Player.hits(Monster m) or
> Monster.isHitBy(Player p). What if there's a class Weapon involved? Do we
> pass it as an argument to isHitBy or does Player has a currentWeapon()
> getter?

You have a function that has access to these objects. Based on that it will
update the player and monster.

    
    
        Function onAttack(from as player, to as monster, weapon) 
        player.addXp(weapon.xp)
        monster.addHealth(-weapon.damage)
    

Probably you'll want to have immutable data instead of mutating this.

(I'm on mobile so I can't put too much code)

The reason you do this is to decouple code. You don't want the player to be
aware of the monster, at least not in this scenario.

------
bunderbunder
I'm not sure that I agree 100% with all the points raised in this article,
though that's possibly just a reaction to what reads to me as invective.

Here's another bit of food for thought along those lines, though: If you take
all the elements of what's typically considered to be good object-oriented
design to their logical extremes, you end up with a bunch of objects that each
have exactly one operation, and are configured at construction time. They may
have some very simple internal state (think counters and caches), but you
probably want to keep that to a minimum.

The end result starts to look very, very similar to functional programming. An
interface with one method is essentially a function. Constructor arguments do
basically the same job as closures. Etc.

When you're looking at things from that perspective, the big difference is
that functional languages almost force you to work that way, whereas it takes
consistent, conscious effort to do it in OOP.

------
dejaime
I pretty much believe that all we have are bad solutions. OOP is a bad
solution that is acceptable at a set of problems. Data oriented designs is an
also bad solution that is acceptable at a set of problems. Anyone who has ever
used any paradigm for big projects can do a write-up about how bad that
paradigm is.

The problem of OOP is not OOP, but actually knowing only OOP. That creates a
lot of hammer and nail problems. The same would be true if data-oriented had
the same popularity, and everything was data oriented.

So, unless you ARE going to give me a __good__ solution, a silver bullet, it
is silly to state that a whole paradigm is an absolute inferior. Especially
when all you can give me is examples of bad paradigm-tech-problem matches or
snippets of incompetent usage.

------
anothergoogler
> Instead of a well-designed data store, OOP projects tend to look like a huge
> spaghetti graph of objects pointing at each other and methods taking long
> argument lists.

Uh, what? FP projects are the ones with crazy argument lists, has OP even
heard of the Law of Demeter? Does FP magically prohibit a huge spaghetti graph
of functions and ad-hoc types pointing at each other?

> The main point is: just because my software operates in a domain with
> concepts of eg. Customers and Orders, doesn't mean there is any Customer
> class, with methods associated with it.

What an observation, it's all a bucket of bits so why name anything? Rub your
hands together, mutter an incantation and voila, software without all that
obnoxious structure!

------
harimau777
When I'm coding, I often find myself in a situation where, in order to reach
my goal, I need to use a "bad" language tool (e.g. eval), violate some
principle of good coding (e.g. avoiding side effects), or just have to write
ugly code. I've come to the conclusion that a lot of writing good code comes
down to recognizing those situations and stepping back to find a way you can
change your design or strategy to avoid needing the ugly code.

I've never quite liked OOP, but I struggle to say exactly why. I wonder if
some of it is that the class structure and hierarchies makes it difficult to
step back and change the design in order to avoid having to write ugly code.

------
coolaliasbro
This is coming from a business consultant (BA/PM and configuration primarily),
but in my experience, it seems like the OOP paradigm is fine in most cases and
is leveraged in a functional/compositional fashion typically, so I fail to see
the issue with OOP a paradigm. Generics and polymorphism can be used to
basically create a functional system that only uses domain specific classes to
handle edge cases.

In short, OOP as currently used, in my experience working on numerous
RIA/municipal/county government enterprise document management systems, seems
perfectly adequate to the tasks at hand and can be used in an effectively
functional way.

~~~
smnplk
What is the point of OOP then, if you are using it in a functional way ? This
just proves author's point.

Do you truly use it in a functional way though, that would mean, that you care
about separation of state and identity. If you are mostly using immutable
collectons/objects with pure functions, then it's fine, but this is not OO.

------
rafaelvasco
Don't know why people keep insisting on this. OOP is a model. Functional is a
model. Data oriented is a model. We as programmers just have to use them , in
the most effective way possible to architect a solution to a problem. No one
model of those can substitute any other. They complement themselves. There is
bad OOP and effective OOP, just as there is bad Functional and effective
Functional. The models are never bad by themselves. The programmers are. Any
programmer that bashes OOP in favor of any other model is just making a fool
of himself and exposing his ingenuity.

------
segmondy
I think most people forget that Edsger W. Dijkstra was a computer scientist
not a software engineer. He most likely wrote programs, but not build software
systems. As much as I've enjoyed most of his writings and musings, one must
bear in mind that they most likely apply to programs not software systems
built in the large. If you are writing one little program and have one type of
data, it's easy to begin with data. When you have a complex system operating
on 500 different types of data, it becomes easier to encapsulate with OOP.

------
makecheck
OO bugs that I see are actually in the “invisible” parts of objects, as these
require more experience to know what is really going on. For example, failing
to implement necessary operators (or worse, implementing them in ways that are
subtly incorrect). Knowing how to implement object “glue” properly is
something that just doesn’t come up if you’re using simpler programming
styles, and in cases like these it’s better to pick the simplest and most
maintainable approach that will suit the task to avoid pitfalls.

------
dnautics
Should be pointed out that this refers to C++/Java/Ruby/python style objects,
and not smalltalk/erlang style objects, which is a message passing model for
data storage.

~~~
snazz
Could someone enlighten me as to how Java style OOP differs from Smalltalk's
variant? I've read the Alan Kay quote on how he's sorry for focusing on
objects instead of message passing but I'm still unsure on how Smalltalk is so
much better not having used it.

~~~
timbit42
This may not answer your question and may not be 100% correct.

Message passing means that objects have their own data and do not have shared
access to it. This makes multi-threading and parallelized code very easy to do
because you don't have to worry about data changing unexpectedly. Clojure, and
other languages, achieve this by making data immutable, which has a similar
effect.

As you mentioned, after Alan Kay used the term "object-oriented" to describe
Smalltalk, people focused on the objects instead of the messages and created
languages designed around the idea of being object-oriented instead of around
message passing (I believe Objective-C and Ruby do message passing), thereby
missing the benefit. All OOPLs not based on message passing should die.

Also, unlike Java, Smalltalk has no classes. Any existing object can be used
as a template to create a new object.

------
in9
I really think these kind of articles are valuable in the sense that they make
us question the way we code our applications.

But I still think it's too easy to point to a problem without discussing
possible solutions. I know the functional paradigm, focused on data streams
and procedures, is where he is pointing at. But how does this facilitate the
graph reference problem, for example?

The thing with oop, besides that is easy, is that is diffuse. Any o'll
tutorial will have an order+client example.

------
akerl_
"One must never change the order here!"

This is presented as a basic truth and then not really backed up, as far as I
can tell. Why must I apply the order as the author believes?

------
vnorilo
I find that I generally agree. However, I have the intuition that good data-
oriented design requires an exceptionally solid understanding of the problem
domain.

You might say that any good design requires that. I'm not going to disagree.
But if there's a place for OOP, maybe it is as a preliminary abstraction,
something to hold the chaos at bay while we build our understanding of the
task at hand.

Of course, preliminary abstraction has a nasty habit of becoming permanent.

------
kumarvvr
I didn’t try to forget OOP per se, but I slowly adopted the authors guidelines
regarding a data first approach. Now most of my objects are just wrappers
around data, rather than analogies to real world objects.

However I mostly am working on web apps so maybe this approach is more
suitable to such apps.

When working on desktop apps, during my initial days as a programmer, I found
OOP based ui systems easy to grasp, but then this could be due to lack of
experience.

------
oliwarner
It's crazy how passionately people get behind their preferred paradigm. I
think they all have a place, and can all be abused severely.

I'm all for people —at least those who don't answer to me— picking one and
running with it, but if you're going to try and tear another one down, at
least make sure you understand what it does for the people that like it. TFA's
author does not appear to.

------
hota_mazi
> Object-oriented programming is an exceptionally bad idea which could only
> have originated in California. > — Edsger W. Dijkstra

I don't understand why Dijkstra gets quoted so often when he has been
demonstrably wrong on so many topics (see his opinion on BASIC too) and he was
such a dogmatic and unreasonable person overall.

------
Michaelanjello
I completely agree. For a DataStore in Python, I may often use a Pandas
DataFrame or such. For random label-based access it can have an index too.

Unfortunately, when asked to design an OOP architecture in a job interview, if
you don't adhere to its religious enterprisy notions, you can risk failing the
interview.

------
dmitripopov
Encapsulation never was my favorite aspect of OOP too, in fact I always try to
create different classes for data and code - it brings in a lot of benefits.
But OOP patterns described by GoF are brilliant things in terms of code reuse
and maintenance costs.

------
theFatemaLive
Learning and developing projects in Distributed Systems using Elixir made me
realise the same..

------
mromanuk
> the Customer concept is just a bunch of data in a tabular form in one or
> more DataStores, and “business logic” code manipulates the data directly.

where lives this business logic? are different functions accessing the same
data and modifying it? problems appears.

------
luord
Most of the problems pointed out can be reduced into "confusing indirection as
abstraction", which _is_ a sin of many OOP developers, particularly those
obsessed with design patterns.

IMO, OOP is not inherently any more flawed than any other paradigm.

~~~
ricardobeat
This claim is not refuting any of the points presented.

------
smnplk
Reading some of the comments here reminded me of a great talk by Stuart
Halloway called Narcissistic Design.[1]

[1] [https://www.youtube.com/watch?v=LEZv-
kQUSi4](https://www.youtube.com/watch?v=LEZv-kQUSi4)

------
ffanon
Previously on HN:
[https://news.ycombinator.com/item?id=13850210](https://news.ycombinator.com/item?id=13850210)
"Was object-oriented programming a failure?"

------
dragonwriter
> For concurrency and multi-threading, I typically glue different logical
> components via message passing

There's a word for the programming paradigm where you glue logical components
together via message passing...

------
jcolella
Interesting article. Though, the article should provide alternatives and speak
to how use other types of programming paradigms might solve the issues that
the person in the article is stating.

------
flavio81
Well, obviously the guy is not using Lisp(or Julia), because his problems are
easily solved by multiple dispatch.

Blame mediocre OOP languages (Java & friends), not OOP itself.

------
hota_mazi
OOP is successful because it's very good at modeling the world that surrounds
us. As much as people like to hate on inheritance and recommending composition
instead (a reasonable advice), the bottom line is that you will encounter the
pitfalls of inheritance only on very rare occasions.

And inheritance enables so much flexibility and ease of maintenance that
nothings comes close to it, not even FP.

Specialization and polymorphism(s) are the reasons why OOP is around,
successful, and will remain so for a while. Anyone pretending it's bad or
broken is just click baiting and does not understanding the fundamental
issues.

------
jryan49
> Encouraging complexity

Picking a satire piece on how something can be abused is not a great argument
of "this thing is bad".

For example, I'd argue anything written in an OOP language is going to be more
readable than this (from the obfuscated C contest)
[https://www.ioccc.org/2018/algmyr/prog.c](https://www.ioccc.org/2018/algmyr/prog.c)

Also, complex systems tend to benefit from OOP because complex systems can
have multiple combinations of behaviors. Something IMO OOP is useful for.

------
arunc
1\. Stop teaching OOP with C++. 2\. Document the anti patterns.

OOP is not bad otherwise. I can't see how GUI frameworks can be easy and
powerful without OOP.

------
thanatropism
I'm a simple man. I don't have an advanced education in computer science (I
did have a SICP-inspired first course in programming as an undergrad and an
algorithms course in grad school using Dasgupta and Kleinberg/Tardos).

Like everyone who's doing stuff with data, I live in Python now. I'm fairly
conversant in functional idioms (wrote a monad tutorial when it was all the
fashion), but like objects because they're a straightforward way to keep data
and code together in a bundle that can be passed around and serialized.

The typical situation for me is machine learning - I could have "fit_to_data"
functions that return matrices or otherwise sum/product types (as they called
it in Haskell) containing the estimated parameters and
"predict_from_param_struct" functions, but having the whole thing in a bundle
erases the whole problem of having to remember a weight matrix comes from a
logistic classifier and not a linear regressor. That, or use an idiom like

    
    
         data LogisticParams a = LogisticP (Matrix a)
    

(I don't remember Haskell syntax anymore) but I'm not sure how I'm better
served by that. The scikit-learn-type idiom where every regressor is expected
to have .predict and .fit methods helps me build new regressors while
reutilizing all of the scikit-learn cross-validation/hyperparameter search
tooling. The idiom above would require me to study the hierarchy of types
upwards and whatever advanced features of the language they're using; but even
if the scikit-learn team is using features of Python outside my understanding
(say, async, or low-level numpy/communication with C libraries) I'm still able
to adhere to a convention.

\---

That said, have y'all ever heard of Formal Concept Analysis [1]? It seems to
me that a lot of the malaise about OOP is that tutorials and examples and
maybe even production code (what the hell do I know) are struggling to define
ad hoc concept hierarchies -- is it Kitchen.Lights.off() or
Lights.off("kitchen")? What scikit-learn (and the universe around it that
tries to adhere to the dialect) is simply to embed data (parameters which are
derived from data) in code that knows how to use it. No one's trying to decide
how TopologicalSpace.MeasurableSpace fits with
IntegrableFunctions.ProbabilityMeasures...

[1]
[https://www.researchgate.net/publication/275540145_Formal_Co...](https://www.researchgate.net/publication/275540145_Formal_Concept_Analysis_-
_Overview_and_Applications)

------
LaserToy
Give a man enough rope and he’ll hang himself.

------
jtdev
“OOP apologists will respond that it's a matter of developer skill, to keep
abstractions in check.”

In my experience, the proliferation and use of ORMs makes keeping abstractions
in check nearly impossible... in fact, I see ORM use as the primary design
decision leading to the bastardization and convolution of sound OOP design.

~~~
segmondy
The conversion is about OOP, not ORM

------
sunseb
Yeah I agree so much. OOP is good when you are in school and you a have
perfect use case like Vehicule, Car, Bicycle, but when you work on something
else, you end up with abstract, absurd and bloated objects. OOP is only
profitable for IT consultants, because they can sell books and bill many hours
working on this mess.

