
Why is OOP still so widely spread? - ingve
https://stackoverflow.blog/2020/09/02/if-everyone-hates-it-why-is-oop-still-so-widely-spread/
======
didibus
The hate is mostly a cultural misunderstanding.

What happens once something reaches the top is that you start to have people
with lots of experience in it that are becoming more and more aware of some of
the small warts. And they start to heavily complain about them.

The people with less experience listen to those complaints, but don't have the
understanding to the nuances and minutiae involved to really understand what
the problem is and how big a problem it is, if it means the entire paradigm is
garbage, or just some details that can still be improved on, and other small
things where there might be better ways to approach it.

So, the less experienced start to think it must just suck. And they don't want
to spend their effort learning something with so many issues that clearly some
of the smartest devs say has tons of problems and there are better approaches
for.

This eventually leads to the cultish flame wars and all that which we see way
too often when discussing technicalities. The problem being, most people do
not actually understand what is bad or good and the trade offs at play, thus
when they debate, they instead pray on their affiliation and beliefs of what
they've read but did not properly understand.

~~~
sebastos
I think this is a really important comment that deserves to be discussed.

You can see this on display in virtually every hackernews thread. Somebody
will say something like "I sort of like X, but my problem with it is Y". But
what they don't tell you is their experience level, the context of how they
came to believe Y, or really any supporting understanding of whether Y is an
actual technical tradeoff that needs to be considered. It's sort of an overly
grandiose, performative way of saying "oh yeah I tried haskell once, and I got
stuck on this thing, so I never came back to it."

As one of the novices just trying to allocate my time, I'm constantly trying
to understand whether, say, it's worth really understanding C++ at a deep
level, or whether I should just try to learn Rust. All too often, I find this
devolves into me scouring the internet for "C++ is ok but the ownership model
is so primitive that I would never start a new project in it" and comparing it
to "My problem with Rust is that it's still such a nascent language I can't
trust it to have the libraries I need". Who are these people, and why are they
saying these things? Are their gripes relevant to me? I have no way to know!

Reading some comments on hackernews, I often come up on a comment that seems
to be speaking another language. At first I'm intimidated into thinking that
there's a secret club of intellectuals that understand exactly what this
comment is talking about. But then I start to wonder.. is this actually elite
minds speaking in a very high-level way with extremely advanced context? Or,
is it just some overly opinionated junior person who just assumes everybody is
working on the same web tech stack they are, and speaks with that implicit
assumption? When they say "OOP is now considered an anti-pattern, most
companies are moving towards reactive FP", do they really mean "I work at
snapchat and the ads group I work for is moving away from OOP. My friend at
amazon said he's doing the same thing"?

~~~
seibelj
> _Reading some comments on hackernews, I often come up on a comment that
> seems to be speaking another language. At first I 'm intimidated into
> thinking that there's a secret club of intellectuals that understand exactly
> what this comment is talking about. But then I start to wonder.. is this
> actually elite minds speaking in a very high-level way with extremely
> advanced context? Or, is it just some overly opinionated junior person who
> just assumes everybody is working on the same web tech stack they are, and
> speaks with that implicit assumption?_

I love HN don’t get me wrong, but my coworkers and I like to poke fun at it.
Some jokes are “why didn’t you just use rust?” and “Well what did Paul Graham
have to say about it?” when debating something. It’s a culture like any other.
I would say a lot of super smart people are here, who have deep knowledge on
the most esoteric niche subjects, and provide a lot of sage wisdom and advice.
But there are a lot of cranks too (including myself!).

~~~
phist_mcgee
My favourite HN stereotype is that every comment chain involves the next
poster correcting the last poster over a tiny detail, and then descending into
long threads arguing minute details of no consequence.

I think this forum attracts a non-trivial number of people who have a
hyperfocus issue beginning with the letter A.

~~~
cmendel
In this instance wouldn't 'preceding poster' be more correct than 'last
poster'? ;)

~~~
hrishios
Something something argument!

~~~
coldtea
You failed to provide an explicit argument!

~~~
yvdriess
Meta-rant about how HN discussions fail to stick to the original topic

------
hn_throwaway_99
> If everyone hates it, why is OOP still so widely spread?

Most importantly, not everyone hates it. There are definitely warts involved,
and IMO the 2 biggest warts are now largely understood:

1\. People understand the pitfalls of inheritance now, so you'll see
"composition over inheritance" MUCH more than you'll see inheritance as the
recommended way to do things.

2\. I don't know how widespread this feeling is, but as someone who moved from
Java to Node/Typescript a couple years ago, I feel like I can confidently say
_structural_ typing, in practice, is MUCH easier, better and fun to work with
than _nominal_ typing. I can think of times I literally spent days trying to
work through some refactoring in Java that was a nightmare because of the
constraints of nominal typing, where the structural typing approach of
TypeScript makes it trivial.

~~~
seanmcdirmid
> I feel like I can confidently say structural typing, in practice, is MUCH
> easier, better and fun to work with than nominal typing.

Structural typing is crazy flexible, but you pay for it with worse type error
reporting (forgetting something in an interface is now 100 errors rather than
1) and the inability to encapsulate (a structure type can't model private
members, of course). There was a lot of research in addressing these problems
in the 90s, but for some reason none of that work has made it into any
mainstream structurally typed language today.

~~~
humanrebar
There are other ways to encapsulate besides private member functions. And,
honestly, private member encapsulation is overrated. I rarely see a design
that would have been dramatically improved by language-enforced member
accessibility restrictions. The problems are typically more basic than that,
like complete disregard of the Single Responsibility Principle.

~~~
Xenograph
> There are other ways to encapsulate besides private member functions.

Could you elaborate a bit here? I've searched for solutions in this area
before without much success. I'd be interested to hear more.

~~~
mumblemumble
I'm obviously not who you're asking, but I'm going to cheekily show up with my
own thoughts on the subject, anyway:

I'm coming to the opinion that, if you need private member functions to retain
encapsulation, that's a strong sign that your design was never properly
encapsulated in the first place.

The motivation for making something private is to prevent people from breaking
your object by messing with things they shouldn't. Generally speaking, only
real way for it to be possible break an object is if its internal state is
complicated enough to allow that to happen in the first place. Which is itself
a failure of encapsulation.

Somewhat more concretely: If you've got to private fields A and B, where any
change to A _must_ be accompanied by some corresponding change to B, and the
logic for enforcing that rule needs to be enforced at several places within
your class, then, at the level of abstraction your object is operating at, A
and B represent a single logical entity, and should never have been
represented as individual fields in the first place. They should have been
_encapsulated_ into their own object.

Even more concretely:

Don't do this:

    
    
      class Thing {
        val counter = 0;
      
        fun foo() {
          val x = counter;
          counter++;
          ...
        }
    
        fun bar() {
          val x = counter;
          counter++;
          ...
        }
      }
    
    

And don't do this:

    
    
      class Thing {
        val counter = 0;
      
        fun foo() {
          val x = counter_next();
          ...
        }
    
        fun bar() {
          val x = counter_next();
          ...
        }
    
        private fun counter_next() {
          val x = counter;
          counter++;
          return counter;
      }
    
    

Do this:

    
    
      class Counter {
        int state = 0;
    
        fun next() {
          val x = state;
          state++;
          return x;
        }
      }
    
      class Thing {
        val counter = Counter();
    
        fun foo() {
          val x = counter.next();
        }
      }
    
    

Very abstractly: Composing objects is the core idea behind OOP. In general,
the more object-oriented design is the one that favors object composition over
other language constructs whenever possible.

Also, this is all arguably a separate issue from using privates simply to
avoid cluttering your public interface when factoring code. If you're working
in a language that doesn't really have good nested functions, private methods
are your next best choice.

~~~
Xenograph
Thanks for the detailed explanation, but I realize that I was misreading the
whole time and so you answered a question that I actually didn't mean to ask.
Apologies.

Instead of 'private member functions' my mind read 'member functions'.

For instance, I'd love to be able to create functions that operate on a
Vector3 interface type in Typescript, but don't have the clunky syntax of

> AddVec3(AddVec3(v1, ScaleVec3(v2, DotVec3(v4, v5))), v4).

Classes in Typescript solve this just fine, so that I can do

> v1.add(v2.scale(v4.dot(v5))).add(v4)

But then I lose the benefits of structural typing. I still have yet to find a
nice solution here.

------
nitwit005
Language support is a bit of a distraction. It's a pattern in languages that
have no "official" support for it.

Go find some old C code for doing something like compressing a file. You'll
likely find a set of functions where the first or last parameter is always a
pointer to some struct or array with the current state of the compression
process. If you converted that code to C++, and made it an object, that
pointer would be the "this" pointer. The support for objects is just
recognizing the common pattern.

Inheritance is similarly recognizing that a lot of code had structs or arrays
with multiple function pointers.

The language support just makes those patterns a bit cleaner and less error
prone.

~~~
nomel
The more I used C, the more I ended up using structs as instances and
functions that looked like:

    
    
        void mything_somefunction(MyThingStruct *mything, ...args){}
    

The weirdest thing was some of the crusty C guys in my group saying "Eww, is
that objects?" No, it's maintainable, and it avoids collisions.

~~~
vbezhenar
At this point I don't understand why people don't just use C++ for such a
code. Of course bringing all C++ features is another matter. But getting some
object-oriented C code and transforming it into C++ code is pure win.

~~~
thu2111
A lot of it is/was driven by the historical instability of the C++ ABI, itself
driven by instability in the language. If you made an object with a C based
pattern, you could export a binary compatible interface and use dynamic
linking. If you exported the same object as C++, even if it boiled down to the
same thing, your users might get crashes because two compilers disagreed on
the right way to compile it.

That's the origin of COM. It's basically the C mything_mystruct pattern with a
_lot_ of additional stuff on top. Actual COM objects were usually implemented
in C++ though.

------
blt
OOP is a nice feature for a language to have. The backlash was against the
religious fervor around OOP. People were claiming that OOP is the _one true
way_ to organize software. Java's designers went so far as to eliminate the
concept of free functions from the language. Almost everyone agrees this was a
bad idea.

Yegge's anti-OOP rant is mainly about this design in Java. Norvig's
presentation on design patterns points out that some OOP tropes are
compensating for missing non-OOP features like first-class functions.

Python's standard library is a good example of how to use OOP effectively. For
example, `multiprocessing.Process` is a class because it explicitly manages
state.

~~~
acdha
Dogma and also specific bad implementations - a significant percentage of the
complaints I’ve heard from other developers were basically Java’s cumbersome
design and the enterprise software complexity fetishists. Python developers
complain about it orders of magnitude less because it’s usually not a problem.

There are two biases skewing perception, too: the first is simply that people
using other languages or writing newer Java well are probably not writing blog
posts about how their language is less hassle than the business.

The second is that OOP is so much more popular that people forget to adjust
for things like skill levels for a mainstream versus niche language. There are
tons of jobs in OOP languages so there’s a ton of code written by people who
weren’t going to write great code in any language, whereas a lot of less
widespread languages - especially those built around an academic concept -
will self-select programmers who are trying to improve their craft. This is
telling you more about the job market and how much companies value quality
than the languages.

------
antirez
OOP is great. Certain interpretations of OOP that certain popular languages
adopted are bad, but the problem is not really OOP. The idea of objects is one
of the most powerful ideas in programming, because it is able to bring a level
of modularity that is otherwise very hard to accomplish. For instance popular
very high level languages like Ruby and Python are so easy to use and to build
things with, because you have such initial collection of objects of all the
kinds that are so trivial to use and versatile. The Array object may have a
lot of methods in Ruby, but such methods are self contained inside its
implementation, and to have a lot of tools for such data structure is great.
This idea, that we give for granted when using Ruby or Python now, is quite
impressive.

~~~
shados
Having a collection of methods associated to an object isn't really OOP
though. You can have one without the other.

There's also not a huge benefit to having data.sort() vs Array.sort(data).

OOP is a lot more than that. One can argue its great, one can argue it sucks,
but either way, a bunch of methods grouped together isn't really what is being
debated.

~~~
antirez
I consider "true OOP" what SmallTalk introduced. And the most fundamental
thing in SmallTalk OOP is the encapsulation of complexity in the idea of an
object, and the ability to pass messages to such objects that can be other
objects, including "blocks". There is more than that to OOP, but I think that
the fundamental idea is that code and functions operating on a given software
component are defined within the concept of a class, and that objects only
communicate with the other parts via messages. From that, a lot of things
happen that are not obvious given this simple idea of OOP. For instance every
object knows how to turn itself into a string, or to compare it with another
one of its kind or of different kinds. And so forth.

~~~
dnautics
While that's true historically, SmallTalk has more in common with some
functional languages (like erlang) than it does with even Ruby, which is
directly a SmallTalk derivate.

I think when everyone talks about OOP today they mean the lineage that
descended from C++, which broadly is: Java, Javascript, C#, Python, and Ruby,
to a lesser extent Go.

Contemporary OOP is the enforced semantic association of data with their
methods, encapsulation of private data, and shared memory.

~~~
antirez
Ruby and C++ OOP don't belong to the same lineage. Ruby is effectively
"Smalltalk alike" OOP IMHO.

~~~
dnautics
It is under the hood but all of that is heavily encapsulated to make it more
like other algol languages that people are familiar with.

~~~
andrekandre
thats really interesting

what are the big differences that make ruby more algol-like?

and conversely, what are the smalltalk features that make it less so?

------
caseymarquis
Hearing people say that they dislike OOP is like hearing people say they
dislike power drills. It's one tool of many, and it has its time and place. I
think what most people truly dislike are situations where someone has tried to
use a power drill to cut down a tree, and refuses to spend time learning about
chainsaws. Building a compiler? Try functional programming. Building a fault
tolerant service? Try the actor model. Building a set of reusable components?
Try OOP.

~~~
enriquto
But a power drill is a single tool, OOP is more like a collection of
techniques. I prefer Pike's analogy that OOP is like woodworking. Sure, it is
a self-consistent body of knowledge, and there are very beautiful things that
you can make using wood. But that does not mean that everything that can be
build in wood sould, nor that basic tenets of woodworking (e.g., the
"direction of the grain") make any sense at all when you are using different
materials.

~~~
amdelamar
That's a great metaphor for OOP. What is the full quote or reference from?
This is all I could find:
[https://interviews.slashdot.org/story/04/10/18/1153211/rob-p...](https://interviews.slashdot.org/story/04/10/18/1153211/rob-
pike-responds)

~~~
enriquto
Yes, that seems to be it.

Pike's quote from that interview:

(...) let me say that I'm not much of a fan of object-oriented design. I've
seen some beautiful stuff done with OO, and I've even done some OO stuff
myself, but it's just one way to approach a problem. For some problems, it's
an ideal way; for others, it's not such a good fit.

Here's an analogy. If you want to make some physical artifact, you might
decide to build it purely in wood because you like the way the grain of the
wood adds to the beauty of the object. In fact many of the most beautiful
things in the world are made of wood. But wood is not ideal for everything. No
amount of beauty of the grain can make wood conduct electricity, or support a
skyscraper, or absorb huge amounts of energy without breaking. Sometimes you
need metal or plastic or synthetic materials; more often you need a wide range
of materials to build something of lasting value. Don't let the fact that you
love wood blind you to the problems wood has as a material, or to the
possibilities offered by other materials.

The promoters of object-oriented design sometimes sound like master
woodworkers waiting for the beauty of the physical block of wood to reveal
itself before they begin to work. "Oh, look; if I turn the wood this way, the
grain flows along the angle of the seat at just the right angle, see?" Great,
nice chair. But will you notice the grain when you're sitting on it? And what
about next time? Sometimes the thing that needs to be made is not hiding in
any block of wood.

------
scoofy
OOP is really interesting to someone like myself that comes from a philosophy
background. In a python framework, i find object to be very useful in
conceptualizing my programs (i'm more able to hold the code in my head).

I, however, often see objects used in bizarre ways. Often to reduce written
lines, or to take a concept, and attach another concept to it in a fairly ad
hoc way. This is never helpful.

The most problematic times i have with object is when the concept behind them
become too general. E.g. If a have a program with a deck of cards, i can have
card objects, with rank and suit, and i can have deck objects, with 52 cards,
shuffle and deal methods. That's fine, but if i have an object that's just
"poker game" that tries to shove all those concepts into one object, it seems
to become very unwieldy, very quickly.

~~~
dheera
OOP is nice when it is used concisely and when objects correspond 1:1 to real
things.

This is painful use of OOP (actual code from an Android app):

    
    
        Camera.Parameters params = mCamera.getParameters();
        params.setRotation(90);
        mCamera.setParameters(params);
    

This would be NICE use of OOP:

    
    
        mCamera.setRotation(90);
    

OR

    
    
        mCamera.setParameters({"rotation": 90});
    

This is painful use of OOP:

    
    
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inSampleSize = 4;
        Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length, opts);
        mImageView.setImageBitmap(bmp);
    

This would be nice use of OOP:

    
    
        mImageView.setImage(new Bitmap(data = data, sampleSize = 4));

~~~
choward
For the camera example, I would rather do:

    
    
        Camera camera = createCamera({"rotation": 90});
    

If you need another camera with different parameters then create a new one.
You can build the options before the creating the cameras to avoid
duplication.

    
    
        Bitmap bitmap = createBitmap({data: data, samepleSize: 4});
        ImageView imageView = createImageView(bitmap);
    

In the case where you are mutating image view, it's an optimization to reuse
the same memory that could be handled by your language/framework so you don't
have to think about it. For example, like with react it could create an
internal representation of what is rendered and then diff it with the new
rendering and reuse the internal representation of image view and mutate it
for you so you don't have to think about doing the optimization yourself.

~~~
teekert
As a Python programmer, all I see is heaps of very similar and the same words.
It looks like mess, I'm sorry.

~~~
jschwartzi
That's because you're telling the compiler what the type of the variables is
ahead of time so the compiler knows whether you're using the type correctly.
As opposed to in Python constructing an object and adding functions to it one
by one at run-time, and only checking that the type is used correctly when the
type is used.

There's a trade-off being made between conciseness on one hand and fast
feedback on the other. Python leans toward conciseness and Java/C++ lean
toward fast feedback. In Python you can express complicated ideas quickly, but
you can't necessarily express correct ideas quickly. Whereas in C++ you can
express correct ideas quickly but you can't express complicated ideas quickly.

If it's costly for you to correct defects in deployed software then you might
prefer the fast feedback of C++ or Java rather than the flexibility of Python.

~~~
dheera
That part is fine, but Java idioms seem to routinely think that

    
    
        String string = new String("string");
    

isn't enough repetition, and so they take it a step further:

    
    
        StringFactory mStringFactory = new StringFactory(StringFactory.FOO || StringFactory.BAR);
        StringOptions stringOptions = new StringOptions();
        try {
            String string = mStringFactory.createString(StringFactory.STRING, "string", stringOptions);
        } catch (java.lang.string.StringException e) {
            runOnUIThread(
                new Runnable() {
                     try {
                         // facepalm
    

I'm exaggerating ;) but as a Python programmer myself, this is what comes to
my mind whenever someone says the word "Java" to me. Obviously not for
strings, but for more advanced constructs (e.g. Bluetooth) I often _do_ see
this much repetition in Java code. It's almost like someone designed this
language to prank engineers.

~~~
arethuza
That a reasonably parody of a lot of Java code - but I don't think it's really
a property of Java the _language_ but some odd principles that seem to be
popular (or used to be popular) in the Java community.

BTW You missed:

    
    
       public static final String STRING_STRING_CONSTANT = "string";

------
cooljacob204
Who is this everyone?

Everyone I know loves OOP.

I am primarily a Ruby developer so I know I'm in a bit of a bubble but
still... The title is pure click bait.

~~~
ausjke
Exactly, while FP is a good addition in some cases, where is the "everyone"
that hates OOP? OOP is still 1000x more widely used and loved than FP to say
the least.

~~~
alexbanks
"Everyone" in this post is being defined as "Everyone in my extremely small
tech bubble"

~~~
throwaway894345
Part of the problem is that “OOP” is poorly defined and lends itself to no-
true-Scotsman arguments. If you criticize OOP for its characteristic use of
inheritance, people retreat to “ _true_ OOP is about message passing” or “
_true_ OOP is about encapsulation” and “inheritance has nothing to do with
OOP”. Feel free to replace “inheritance” with any criticism of OOP, such as
the gratuitous use of mutability relative to other paradigms or the remarkable
popularity of gratuitously large object graphs (the “banana with a reference
to the gorilla holding it with a reference to the entire jungle” problem).
Everyone insists their own definition of OOP is the one true definition, but
none of these purely theoretical definitions absent any of the faults
typically attributed to OOP actually exist in the real world (or perhaps they
do exist and we just call them “data oriented programming” and “functional
programming”).

~~~
Jtsummers
For a parallel in a totally different domain, see Umberto Eco's definition of
fascism [0]. It is a list of 14 properties typical of fascism, but it is not
necessary to actually possess them all to be considered fascist (and they're
mutually contradictory).

The same thing happens with FP and OOP. Both are too broad to be defined
concisely, and the definitions, when collected, are often contradictory or
necessarily exclude what others would consider valid <paradigm> languages.

Any discussion about these paradigms and their relative merit or "goodness"
has to be clear about which subset of OOP and FP properties are being
discussed and compared.

An example: A popular view of many current FP proponents is the idea of
immutability as a key requirement of FP. But this necessarily excludes Common
Lisp, a multi-paradigm language with the ability to use many other FP ideas.
Instead, CL would be included under FP (or include FP as one of its paradigms)
by someone focusing on things like higher order functions, being able to
construct functions at runtime via closures, etc.

The same can be used to understand OO. Message passing is a property of some
OO systems. Inheritance and class hierarchies are a property of others,
possibly overlapping with the first. Closely tying methods to classes (see
Java) is another common property. But Java and Smalltalk are both considered
OO and both contain ideas absent in the other. Which of those ideas are OO,
which are ancillary. And which OO ideas are present in one but absent in the
other, does it invalidate the other language as an OO language or does it just
mean it has a different view of OO?

[0]
[https://en.wikipedia.org/wiki/Definitions_of_fascism#Umberto...](https://en.wikipedia.org/wiki/Definitions_of_fascism#Umberto_Eco)

~~~
throwaway894345
I find it's more helpful to think about these labels as regions in a
continuous multidimensional space. One such dimension is im/mutability, and
you have languages like Haskell that exist on an extreme of that continuum and
then languages like Java which exist nearer an opposite extreme in which
mutability is common, and languages like CL where mutability is permitted but
relatively infrequent. Similarly, another dimension is the frequency of
inheritance, another is the aggregate cleanness or spaghetti-ness of object
graphs (I'm sure there's a mathematical term for this), and so on. CL permits
some mutability, but it pretty clearly belongs to the cluster that we
typically call FP, and while definitions for FP do label slightly different
but largely overlapping regions in this multidimensional space, there is
relatively little variance.

OOP on the other hand is very poorly defined. There is a tight little cluster
of languages which are commonly called OOP, but the defining features of that
cluster are generally negative so "OOP proponents" began arguing that while
those languages are OOP, the things that unite them aren't actually defining
characteristics of OOP. Advocating for other regions in this space for which
to apply that label is problematic because they either exclude other
traditionally-OO languages or the described region overlaps too much with the
"functional" and "data-oriented" regions (one can retort, "per your
definition, Haskell is also an OO language"). So in their loyalty to the term,
"OOP" proponents instead make arguments about what _doesn 't_ define the
language (note that not all proponents make all of these claims):

* OOP may or may not involve inheritance.

* OOP may or may not involve message passing.

* OOP may or may not involve a high degree of spaghettiness in object graphs

Ultimately they'd prefer the term be semantically useless than useful and
negative.

Ironically, the only thing that unites all OOP advocates is a fondness for the
term.

I do invite OOP proponents to prove me wrong by coming up with a _common_ ,
semantically useful ("meaningful" in the formal sense of the term) definition
that describes all traditionally-OO languages and generally excludes most
data-oriented and functional languages.

Note that a common rebuttal is that you can write bad code in any language and
with any paradigm, which ignores that the claims are about the frequency and
not a binary proposition about whether or not the language precludes a
particular anti-pattern. The extent to which a Java program doesn't exhibit
the criticisms above is the extent to which that program is not OOP, and very
probably data-oriented or functional in nature.

------
Animats
Objects as encapsulation are fine. The author's claim that modules do the same
thing is incorrect. Modules don't, in most languages, have instances. You get
one set of data. Bundling data with functions is way better than global data.

Inheritance got caught up in the "is-a" mindset of 1980s AI, and turned out to
be only marginally useful. Being able to have an object as a field of another
object is almost as useful. A point I make occasionally is that there needs to
be a good way to find the owning object when you do that. Is there a language
where, when B is a field of A, you can find A from B? I've plugged for syntax
for finding the owner in Rust, where backpointers are difficult.

Order of initialization for inherited objects is a huge headache. If B
inherits from A, what in A is B allowed to call or reference during
construction? This sort of thing needs language support. Same for order of
destruction.

Multiple inheritance is usually a mistake. If you reach the "diamond pattern",
your code is too cute.

~~~
fanf2
Abstract data types in the sense of CLU / Liskov give you modularity and
encapsulation without being object-oriented.

~~~
garethrowlands
True dat. It's common to conflate abstract data types and objects. Similarly,
it's common to conflate types and classes.

------
dpc_pw
OOP is a superficial lowest common denominator of programming. Everyone can
understand on a superficial level (cat is a animal, dog is an animal, cat does
meou, dog does bark, kind of thing), and proceed to write programs. That's why
it is popular.

OOP works on low complexity, small projects, but quickly falls apart at
certain point, but then it's just head scratching and finger pointing ("this
ORM is just bad, next time we will use a different one").

More experienced people figured out some way around OOP to make it more
robust, so whenever OOP is criticized they just do the "oh, you just doing it
wrong: _insert excuse and advise here_ ".

People who really though it through, and tried different approaches are the
ones that hate it and are vocal about it. They see through the folly. They can
tell how core principles of OOP are bad ideas. How encapsulation at object
level is usually pointless and costly, how inheritance doesn't make sense, and
so an so.

~~~
teekert
I would really appreciate some examples of oop being "wrong" and the problem
solved in a better way. I just don't see why its bad, it makes sense to me.
Our lib has classes and submodules with functions. A filetype benefits from a
class that contains methods to manipulate said file but other common operation
are better put in a function imho.

Just saying "if you are really smart you'll see that oop is bad" just sounds
so... Empty.

~~~
alquemist
In small doses, OOP is invaluable, especially for defining modules and their
interfaces. Alas, OOP advocates, especially in the old days, oversold it.
Several major flaws:

* "Everything is an object". This creates unnecessary confusion between data and modules and sometimes even functions.

* "Everything is a message". This encourages splitting state between a myriad of objects, each hiding some tiny bit of mutable state that changes whenever it receives a message. Reasoning about such a state graph is impossible for any non-trivial application.

* "Everything is an interface", which leads to tests tightly coupled to implementation due to mock over-usage.

* "Everything is an inheritance hierarchy". Practice has proven that composition is better than inheritance.

~~~
kazinator
No, no, no.

Everything is a pointer-wide cell of bits, with a type tag.

Now we're cooking with gas!

------
t0astbread
Regardless if OOP is a good idea or not, I think there's an issue in how we
introduce people to it and the role it plays in programming at large: I'm
fresh out of school and I was never taught anything other than OOP. In fact,
no one ever mentioned that anything else even exists and when I brought it up
during a feedback round people didn't know what I meant when I talked about
"programming paradigms".

All we were ever taught was basic imperative programming, then OOP and then
several years (!) of just OOP frameworks (Android, ASP.NET, Angular and the
like). We never talked about functional programming, we never talked about
software architecture in general (outside of those frameworks).

There was a subject where we explored "computer science fundamentals" like
some algorithms and data structures and, among other things, logic constraint
programming. But that subject was so small and unimportant to your grade that
you could just sleep through it.

~~~
lovegoblin
> I'm fresh out of school

This is pretty vague. Is "school" here, like, a 4-year comp sci degree? A
bootcamp? A 2-year diploma?

~~~
t0astbread
It's hard to describe due to differences in school systems across countries
and continents. But in my country it's called a "vocational college" it's 5
years long and ends with a diploma. After that you typically get a job or
study at a university. It's also specialized in a particular discipline (in my
case that's "programming and software engineering" other schools offer
chemistry, agriculture or metalworking).

------
shados
A vocal minority (of which I am part of!) hates it.

To the vast, vast majority of software developers, it's "just how you program"
(most don't even know there's alternatives).

It's really hard to go in an organization where hundreds or thousands+
developers live or breath through OOP as the gold standard, and suggest to do
it differently. Thus the status quo lives on.

~~~
loktarogar
It's a stretch to think that the main reason that people don't use FP
languages is ignorance or an inability to affect change.

I don't enjoy the functional languages out there, at all. I enjoy some
functional concepts within an OOP language, but I would be fine with just a
pure OOP language if I had to.

~~~
shados
Why is it a stretch? Only a tiny itsy bitty minority even know what FP is (a
little more these days because of some JS frameworks and reactive programming,
but still).

Then among the people who do know about it, an even smaller fraction learnt
about it first, or in the same depth. Among those who did, very few learnt it
in a practical way (Learning ML in college is unlikely to get someone to use
FP to build production software, especially before ReasonML was a thing).

With all that, is it a stretch to think people don't use FP because they don't
know about it? No, I don't think so. It could be 100% objectively superior in
every way and people still wouldn't use it in those circumstances. And its'
far from being "obviously" better.

------
tobyjsullivan
I was confused about OOP for about the first decade of my career. I always
thought I was an experienced OOP programmer because I had been working with
object-oriented languages like C#, Java, and Ruby.

Eventually I sat down and read what OOP actually was. I immediately realized
that I'd never worked on a single object-oriented architecture despite a
decade of working in object-oriented languages.

I can't stress this enough. Using an object-oriented language does not mean
you are building an object-oriented system. If you cannot differentiate your
classes from C structs, you are probably not building an object-oriented
system. If you have functions that manipulate objects, rather than objects
manipulating each other, then you are probably not building an object-oriented
system.

This article seems to conflate these ideas in the same way. It seems to say
that "the success of languages who happen to be OOP" somehow implies "OOP is
still one of the dominant paradigms right now". I don't see any other
explanation for that claim beyond this inference.

Based on all the systems I've worked on at various software companies (heavily
weighted to SaaS), I would be legitimately surprised if it was true that "OOP
is still one of the dominant paradigms right now."

edit: Decided not to explicitly recommend the Byte article[0]. It's good but
doesn't go deep enough to get the nuances across unambiguously.

[0][https://archive.org/details/byte-
magazine-1981-08/page/n75/m...](https://archive.org/details/byte-
magazine-1981-08/page/n75/mode/2up)

~~~
imtringued
I think your comment is a very round about way of saying that you should keep
your code base as simple as possible. Just because your language can do OOP
doesn't mean you have to. Not everything needs inheritance, polymorphism,
encapsulation. Point free style is also something that lends itself to abuse
in FP. At some point you're losing more than you're gaining. With more
experience you learn to just keep it simple and boring.

------
stickfigure
I don't understand the perceived antagonism. I like FP, I like OOP. Most of my
objects immutable, and "change" methods return a new instance of the object
with the expected change. It's a great way to code.

~~~
raspasov
I agree with you. What language are you doing this in?

~~~
stickfigure
Mostly Java, but also Typescript and Python. The only language I use
professionally that seems actively antagonistic to FP is Go.

I do wish Java had made `final` the default for fields and variables. Lombok's
`@Value @With` takes away a lot of the pain though.

~~~
imtringued
Languages with immutability by default are the best. It's kinda like safe vs
unsafe in Rust. You can do lots of things with immutability or safe Rust but
when you need mutability or unsafe Rust then you just add the necessary
keyword.

The "dangerous" parts of the application are now highly visible and neatly
separated from the harmless parts.

~~~
stickfigure
I really wish Ceylon had taken off, it was (is?) a better "better Java" than
Kotlin. Aside from having intersection and union types before typescript,
everything was immutable by default... and you had to type out the full word
`variable` if you wanted mutability.

------
m463
I'm pretty sure a lot of the popularity of oop actually came from modularity
which came with it (although I do find inheritance useful, just not multiple
inheritance).

I think C would be 10x more useful language if it ditched include files and
had "import" like python

~~~
teawrecks
What does that mean? Import for C doesn't make sense to me because 1) C code
is never executed during compilation, and 2) C doesn't even support bare code,
everything has to exist inside a function. So what would be the desired
behavior from import in C?

~~~
sumtechguy
I can take a stab at it. I think what trips many new C people is the fact that
include is just what it says on the tin, include. You can put anything in
there and it is subject to the pre-processor. Many
books/faqs/stackoverflow/videos however implicitly tie library include and
headers together. So the idea that include means include this library comes
somewhat from that. It tripped me up some 27+ years ago when I started on C.
The actual include a library comes from a different part of the system, the
linker. The includes just handily have the bits needed to have the external
references to it so the linker knows what to do. You do not need them in the
include to do that. Since they were including those they usually have
predefined bits in there.

Like you say pythons import is a different beast and it can run code at
runtime when it comes across that statement. Some training is not clear on
that. Like you point out import does not just import the file it runs the
thing. If the file only contains def's then it effectively just defines a
bunch of functions/objects and does nothing else But it can. C is not like
that. It is more copy the whole file here and apply the current state of pre-
processor rules.

~~~
m463
yes, includes are pretty much all syntactic, no semantic.

------
taeric
I'm still convinced it is not OOP that is bad, per se, but the idea that you
can fully encode anything into a taxonomy of types.

At a very high level, they can guide the conversation well. As soon as the
boots hit the ground, though, the lines between subsections of a design are
ridiculously arbitrary and not at all disconnected from each other in a
meaningful way.

In physical systems, this can be blurred when you have more obviously
consumable parts of an object. Think the brake pads of a bike. That said, the
wheel of many bikes is also a consumable part of the braking system. Such that
the question is less "where is the separation of braking from drive train" and
more "what parts are easily removable from the bike?" And it is definitely the
case that that question is not necessarily built up in a taxonomy, Though it
is certainly usably described in a variety of them.

~~~
jschwartzi
You can't really separate a taxonomy of a system from your desire to make
statements about specific things. So your ability to use OOP effectively
depends on your ability to decide whether the statements you're allowing
yourself to make about your types are the kinds of statements you consider
meaningful.

One could easily change the taxonomy from "wheel" and "brake pad" to "spinning
surface" and "stopping surface." And if you want to construct a bicycle by
composition, you know that in order to implement brake() you need two items
which implement SpinningSurface and StoppingSurface. The SpinningSurface could
easily be of type WheelRim, but it could also be of type BrakeDisc. And in
both cases the StoppingSurface is of type BrakePad with the difference in how
BrakePad is applied to SpinningSurface.

And with this taxonomy you could also allow users to use Shoes, WaterBottles,
Wrenches, and a whole host of other objects as StoppingSurfaces.

So the problem isn't with trying to encode anything with types, the problem is
that people try to encode everything with types. You have to pick your
battles, and you have to devise your taxonomy such that you can make
meaningful abstractions. That remains an art form.

~~~
taeric
Indeed, I typed "anything with types", but I really meant in a total sense.
Such that I did mean "everything with (one set of) types."

I tried to make it clear that I do find high level taxonomies nice. Just the
further you zoom in, the less useful a strict adherence to that will be.

------
ForHackernews
> [OOP] continues to puzzle programmers. If they are used to top-down
> programming or functional programming...

What the heck is "top-down programming"? I've been writing code for close to
20 years and this is the first time I've encountered this term.

Google reveals results like this one [0], that explain it as "essentially the
breaking down of a system to gain insight into the sub-systems that make it
up."

So, in other words, literally any kind of programming? All programming
paradigms are about building abstractions to avoid repeatedly dealing with
low-level details.

Is this really a thing that people talk about?

[0] [https://dzone.com/articles/how-does-top-down-programming-
wor...](https://dzone.com/articles/how-does-top-down-programming-work)

~~~
recursivecaveat
They are using it as a synonym for procedural style it seems. That's not
really correct, you could write any style in a top-down or bottom-up order.

------
kentonv
People don't like (implementation) inheritance, for good reason. But that's
not the core of OOP, that's some weird crap people piled on top of OOP in the
90's.

Object-oriented programming, fundamentally, is about associating code with the
data it manipulates. Code + data = object. Two essential follow-ons:

* Encapsulation: Your object provides an interface composed of methods, without allowing callers to reach in and mess with the data inside except by calling those methods. This allows your implementation to evolve without breaking callers.

* Abstraction/polymorphism: Objects with different implementations can implement the same interface thus making them interchangeable. This enables code which operates on such objects to be reused across wildly different use cases.

These fundamentals exist in basically all large systems. Example: Linux file
descriptors are objects. Different kinds of file descriptors (e.g. disk files
vs. sockes) implement the same interface (syscalls, e.g. read/write), and you
cannot reach directly into their implementation from userspace, which allows
the kernel implementation to evolve over time. You really can't _not_ use OOP
in these scenarios.

The opposite of OOP is separating code from data. In anti-OOP, you declare
your data structure completely transparently, without declaring any kind of
"methods" that apply to it. Code modules interoperate by operating on the same
underlying structure. This tends to lead to sclerosis as adding new features
to the data structure without breaking existing code can be quite difficult.

My hot take: The philosophy of REST (though less often the actual
implementation) is disturbingly anti-OOP.

~~~
mwcampbell
You say inheritance was added to OOP in the 90s. I don't know the history
here, but I know Smalltalk has inheritance. So was that a late addition to
Smalltalk?

I'd also like to know why you think REST is disturbingly anti-OOP. It does
impose a separation between the implementation of a resource and its
representation, right? So multiple implementations could have the same
representation and the same verbs. So in that sense, it's like OOP, isn't it?

~~~
kentonv
> You say inheritance was added to OOP in the 90s.

Looking it up, I think I was wrong about that. Early OOP did in fact have
implementation inheritance.

I guess what I should have said is, OOP originally had three legs. One of them
turns out to be bad but the other two seem fundamental to large-scale systems
programming.

> I'd also like to know why you think REST is disturbingly anti-OOP.

So, this is pretty abstract, but REST philosophy seems to put a lot of
emphasis on representations of data while discouraging communication of
operations on the data. The way to operate on the data is to GET the
representation, modify it, and then PUT it back -- not to POST a message
saying "please perform operation F". I've heard several hardcore REST
advocates specifically argue against communicating operations, deriding it as
"RPC" (which I guess they see as derogatory?).

In practice I think most people only follow this philosophy when it makes a
reasonable amount of sense and ignore it when it doesn't.

------
decafninja
I think OOP is fine.

What people really hate is "enterprise OOP" and its related ecosystem.

It's like Agile. Agile is fine. But people hate "enterprise Agile" and the
whole ecosystem around it.

------
mdoms
Despite the wailing and gnashing of teeth on places like HN, OOP has been
wildly successful. It's not popular by mistake, it's an outlandishly good,
imperfect problem solving tool.

~~~
C1sc0cat
As are COBOL and Fortran in their respective areas.

Though I have written telecoms billing systems in Fortran (and some Pl1/G) and
worked on Fortran simulations of Breeder reactors n my Time - so I guess I am
a Real programmer Tm

Its about using the tools you have for the right job some times oop is right
some times not

------
mesaframe
Honestly, this blog brings nothing new to the table. I expected more from a
stack overflow blog. But was heavily disappointed.

------
giancarlostoro
I think multi-paradigm is better. I hate that in Java I _have_ to have classes
to do most things. Whereas in C I can just have a function. I wish more
languages approached things like D or Python. Let the developer figure out
what they actually need and fully empower them.

~~~
teawrecks
Java is trying to force a code architecture on the devs. It's useful in
enterprise situations where devs cycle in and out but the code base has to
stay. You never have to guess where or how something is defined. C/C++ on the
other hand gives you 1000 ways to shoot the person who replaces you in the
foot.

~~~
p2detar
Exactly. This is what people bashing Java just don’t seem to understand.
Training a new Java employee on an existing code base is far cheaper than on a
C/C++ codebase. Speaking from personal experience.

~~~
giancarlostoro
I've found it just as simple to teach someone a Python codebase, and I do have
OOP in most of my python projects, but sometimes I don't and that's okay,
because not everything needs to be an instance of a class. D is not as
prevalent but I'm certain showing someone around a D code base wouldn't be too
complicated.

------
temporallobe
Over the last 23 years of my career, I have concluded that there is no
intrinsically bad or good paradigm; They’re just all different, each with
their strengths and weaknesses. Just as you wouldn’t kill a fly with a
sledgehammer, you wouldn’t choose a big, heavy OOP language like Java to write
up a simple script to copy some files around, would you? No, Python or Perl
would be better suited for such things. But using scripting language for large
Enterprise-level software begins to fall apart at some point. Suddenly you’ll
find yourself wishing that you could name and encapsulate data structures, and
then perhaps extend the functionality of a module, and you might even find
yourself mimicking concepts of classical inheritance - and eventually you’ll
end up with a mess that would have been much cleaner with some kind of OOP.
Take Javascript, for example. In the days before ES6, many large JS Enterprise
libraries were written with strange prototype hacks that did their best to
mimic classical inheritance with varying degrees of success. A framework
called Dojo tried solving this with convoluted constructs like “declare”;
Whole transpiled languages like TypeScript and Coffeescript were created just
to make it easier for developers to write “clean” classic OOP-style code. My
point is, OOP is and has been useful in all manner of problem solving, and no
matter how hard we try, we always come back to it in some way. Perhaps the
question of why it’s so prevalent is misguided, driven by misunderstandings,
culture, trends, and a desire to shun what’s old and promote what’s new.

------
geophile
People like and use useful abstractions, and OO offers them: encapsulation,
modularity, polymorphism, inheritance. (If you don't like inheritance, don't
use it.)

People hate bloat, complicated ways of doing simple things, and
AbstractFactoryAdapterFactoryAdapterFactories. These abominations got built in
Java, an OO language.

Toss out all the religion and all you have are a few useful programming ideas.
I was around when a popular "software development tool" of the day was a
template. (No, not what you are thinking. I mean, a piece of plastic with
shapes cut out of it.) You could use to draw flowcharts. Then, "structured
programming" came along, basically the OO of its day. Structured programming
meant no GOTOs. Instead, use the things that GOTOs usually implement: while
loops, if/then, if/then/else. Keep functions to no more than "a page" (i.e.,
entirely visible on an old 24x80 screen).

Structured programming was uncontroversial. People recognized progress and
adapted it. This happened when there were very, very few independent software
companies, and there was a miniscule market of software developers. I can see
though, how it could have gone wrong if there were companies intent on
exploiting structured programming by turning it into a complicated fad
requiring salesmen, consultants, trainers, and all the other profit-making
paraphenalia.

------
allo37
I've seen "OOP" defined as "I have a base class and a couple of derived
classes", and then I see "OOP" where you have this behemoth of factories,
controllers, managers, classes with at least 6 layers of inheritance, etc.

Which OOP are we talking about?

~~~
jariel
The later is not OOP those are Design Patterns, sometimes used in OOP, often
Java, that can sometimes be overwhelming and cumbersome.

~~~
allo37
Maybe from a purely semantics standpoint they're not, but from what I've seen
they go hand-in-hand. I think if you went around saying you "knew OOP" but
didn't know what a factory was, people would look at you funny.

~~~
jariel
Outside of Java you don't see a lot of those specific patterns (ie Factory)
used. Certainly not in TypeScript or Python for example.

------
mumblemumble
> OOP encapsulates data by default

That ideas's been nagging at me lately. In his paper, _The Early History of
Smalltalk_ , Alan Kay wrote, "doing encapsulation right is a commitment not
just to abstraction of state, but to eliminate state oriented metaphors from
programming."

Basically all code I've ever seen in OOP languages is _incredibly_ stateful.
And it makes a lot of reuse difficult, because that stateful behavior makes it
difficult to confidently compose things from smaller pieces. That stateful
behavior means that the class's internals aren't truly encapsulated. You still
need to understand those details about how its state changes to interact with
it successfully, even if you can't observe the state directly.

([http://worrydream.com/EarlyHistoryOfSmalltalk/](http://worrydream.com/EarlyHistoryOfSmalltalk/))

------
cryptos
> good OOP practice means you provide getter and setter methods to control
> access to that data

It is this superficial understanding of OOP that led to a somewhat bad
reputation. At least in the form "getX" and "setX" it would be more of a data
structure with mostly useless methods around the fields. If a programmer is
able to set each and every field from the outside through a setter, there is
no encapsulation at all. To have objects that deserve this name, a method
should be more like a "transaction" on the object, so related fields should be
changed in one shot.

Apart from that, I don't think it is useful to think in separate camps (OOP vs
FP) here, since both approaches are complementary in many cases. It is not
like you have to decide for the one or another theses days, since most common
languages support OOP and FP style.

------
fsociety
I’d take a guess the majority of OOP-haters hate it because “when you have a
hammer everything looks like a nail” syndrome.

That syndrome can lead to over-abstraction and tight coupling of objects.

~~~
_jal
I must admit that the first time I encountered a factoryFactory, I questioned
what I was doing with my life.

------
xiaolingxiao
Avid Haskeller here. It really depends on the domain. I find OOP to be a
really good abstractions for building GUIs, a domain that FP falls short, FRP
nonwithstanding. I've been using Swift to build mobile apps on iOS and I find
its OOP abstraction a joy. So there's a data point there.

~~~
ahartmetz
I would really like to hear your opinion about the problems of FRP (for GUIs,
in case there are other popular uses). I use C++ and QML, a "declarative"
(it's a somewhat fuzzy concept) language, for GUI programming daily. I have a
bunch of techniques in C++ to tame mutable state, including use of a quasi-
functional style where possible. More... "functionality" seems like a good
idea in general, hence my curiosity what doesn't work.

------
Barrin92
Like many others have pointed out I don't think OOP is universally hated. That
aside I think the flavour of OOP that is unwieldy is predominantly statically
typed OO languages like Java.

I've always liked Smalltalk's philosophy on many things and a key feature of
its idea of OO is dynamism and 'late binding of all things'. Popular OO
languages like Ruby or Python borrow heavily from Smalltalk and they're great
to use and very popular.

It's the combination of static typing and OO I think that leaves a bad taste
when it comes to OOP, and I think that's also reflected in newer languages. A
lot of younger statically typed languages like Rust or Go seem to have ditched
the OO paradigm, and embraced FP.

------
znpy
My take: oop ain't that bad after all. Functional programming people are
actually just a very loud minority. Everything has drawbacks.

------
jtsuken
There is a generation of programmers that grew up being told that the only
right way is to: ``` >javac

    
    
      public class Main {
        public static void main(String[] args) {
            System.out.println("This will be printed");
        }
      }
    
      >java Main
    

Also, there is no way you could get things done, without spending a year
studying what each of Class, static, void, System, args, etc meant. It's
hardly surprising there will be a number of people. who realise that that's
neither the only nor the most efficient hammer to drive in all types of nails.

------
jkuria
“Object-oriented programming is an exceptionally bad idea which could only
have originated in California.”

\-- Edsger Dijkstra (1930-2002)

~~~
Rochus
Just that it didn't originate in California, but in Norway, see
[https://en.wikipedia.org/wiki/Simula](https://en.wikipedia.org/wiki/Simula).
What he probably meant was Smalltalk, but ironically the original Smalltalk-72
only had a subset of features of Simula. And another famous Dutchman is even
the inventor of one of the most popular OO languages of today.

------
quicklime
I don't hate OOP. Sometimes an OO design is nicer than a non-OO equivalent,
but the problem is that many people run with that and try to apply the pattern
everywhere (especially if they're from a Java background where that is the
norm). I think the reason is:

Some people like flexibility, but most people just like having a detailed set
of rules to follow.

I think this is the reason behind a lot of trends in our industry: GitFlow,
Scrum, Kanban, TDD, even FP.

------
JMTQp8lwXL
It's what gets taught first in higher education. I first learned OOP, and I
was neither here nor there about it. I didn't learn about FP until completing
my degree program. FP clicked for me, my team uses it, everyone else in my
company uses OOP. Nobody seems bothered we use FP, but also nobody's checking,
either. It's not that I dislike OOP either, it's that FP feels like a much
more natural fit.

------
polygotdomain
These clickbait titles are ridiculous. 1) Everyone doesn't hate it, and 2) you
can not like something and still find it useful.

------
EliRivers
Like programming languages, there are two kind of programming paradigm.

The ones that get complained about, and the ones that don't get used.

~~~
nottorp
Agreed, also I have a feeling most complaints about OOP are actually
complaints about what C++ has become.

~~~
arethuza
Or the Hammer Factory Factory Factories abstractions found in the Java world
at one time...

~~~
EliRivers
I have a codebase in which the naming convention somehow went so wrong that
many classes with "Factory" in the name were _made_ in some kind of Factory
class, but are not themselves factories :/

It also has classes with "Iterator" in the name that are _not_ iterators.
They're containers, over which you CAN iterate. You'll be pleased to hear,
however, that the actual iterator is NOT named an "IteratorIterator". The name
of the actual iterator class contains no clue that it is an iterator.

------
hermitcrab
When I moved from C to C++ all those years ago, OOP was a revelation.

------
phendrenad2
I'm glad to be part of the anti-OOP backlash that's become trendy in recent
years. Unrestrained OOPness leads to the kinds of "Java-isms" we all know and
love. MyApp::Core::BeanStringFactoryProviderImpl. Stuff like that.

However, if you turn your back on OOP entirely, where does that leave you? You
have to go down the functional programming route.

FP has it's own problems. Ever see a large FP-style JS program? It resembles
procedural code. Functions strewn around the codebase with no hierarchy or
compartmentalization. Anything can (and will) call anything. You pipe data
along from function to function, but you quickly find that the chunks of data
that you're sending keep... growing... because you can't keep the entire
codebase in your head, and you can't remember that variable X is equivalent to
Y in all cases, so you just pass Y along also.

------
morphicpro
Encapsulation is only really an issue if you don't follow the law of demeter.
write better public facing methods if you want better Encapsulation.

Inheritance is really just about writing better namespace and domain /
contexts of your code.

Polymorphism is really only ever an "issue" I've seen when dealing with strong
typed langs and all the langs where it has become an issue they provide
interfaces to aid in Polymorphism.

I don't think anything about what was listed is #1 exclusive to OOP and 2
doest not already have best practices to address in OOP and other langs.

Everything that was written about was not about the problems they solved but
the patterns used to address the problems. I think that makes it too
subjective to be constructive.

I will say though there is nothing fun about mocking complex state in tests
for a rails app let alone if that state is shared or easily mutated.

------
agentultra
Richard Feldman gave an interesting talk on this in 2019 [0].

He was trying to answer why functional programming isn't mainstream but the
opposite is what we're posing here and I think it's for many of the same
reasons.

 _Network effects_ : a lot of these languages were mainstream earlier on and
got buy in from a lot of folks who are invested in their continued adoption
and success.

 _Platform exclusivity_ : some companies push their own language ecosystems on
their platforms and those languages are often OOP/multi-paradigm languages.

Specifically to OOP we have to ask why is the particular style of C++/Java OOP
the norm? Why didn't Eiffel, Smalltalk, or Self reach the same market?

[0]
[https://www.youtube.com/watch?v=QyJZzq0v7Z4](https://www.youtube.com/watch?v=QyJZzq0v7Z4)

 _edit_ : forgot the link -- oops.

~~~
formerly_proven
Functional programming was arguably the first type of higher-level PL to be
invented, so it should've had the most opportunities at network effects.

~~~
Scarbutt
The problem was computers weren't ready for FP at the time, so C won.

------
dragonwriter
> If everyone hates it, why is OOP still so widely spread?

The premise of the question is false.

There are a few people who hate OOP, and a larger numbers who hate (or at
least dislike) the conditions in the period of unquestioned OOP hegemony when
that square peg had to be shoved in every available round hole.

------
debaserab2
From
[https://news.ycombinator.com/item?id=18250466](https://news.ycombinator.com/item?id=18250466):

"OOP is just a mental model. Deep down everything is made of bits. The church
of OOP has failed but if something looks like a duck, walks like a duck and
talks like a duck it probably is useful to make a duck class. We're now down
to fighting for nuances. You can do most things with OOP or without OOP but
each path has some upsides and downsides and most of the time it's good to use
some things it provides where it makes sense and not get too religious about
it. The great architect has the foresight on how the code will be used in five
years and design it accordingly."

------
ipnon
The Turing machine implicitly includes time as a sequence, and the lambda
calculus does not. It is easier for the amateur programmer to reason about
time as a sequence. So the lay person begins programming easily writing
imperative programs and struggling writing functional programs. The years turn
the amateur programmer into the experienced one. Before they only understood
imperative programming, now they understand functional too. But they still
work with the amateur programmers who only understand imperative. They both
use imperative in order to work together.

There is something universal in our understanding of temporal logic that makes
objects changing over time an intuitive model for a computer's internal state.

~~~
nec4b
"There is something universal in our understanding of temporal logic that
makes objects changing over time an intuitive model for a computer's internal
state."

But that is exactly what a computer does: changes state over time. Languages
ignoring that fact are prisoners of their own niche and will never be as
popular as those which don't ignore the hardware.

------
ilaksh
I like functional programming and have been doing it off and on for years.
Mainly with Ocaml.

But I have never really understood the desire to move to pure functional
programming for the following reason:

I always end up with a group of functions that are repeatedly passing around
the same variables. It might only be two or three or four variables, but quite
often it seems that I can make the code less noisy by assuming that the state
is attached to the instance already and so it doesn't constantly need to get
passed around.

And I know someone is going to say I am just not factoring things properly,
but after a number of years of repeating that experience, I don't buy that
anymore.

------
topkai22
One thing I haven't seen any mention is that there are well understood
methodologies for mapping business analysis constructs to OOP code. I still
see a lot of "person fills out this form, then it gets validated, and then it
sends a message" type code out there. Those sorts of IT applications map
nicely to objects in a well understood way. Yes, you can absolutely do it with
FP or whatever pardigm you like, but other parts of the organization such as
business analysts are often used to producing requirements in a way that
aligns to OOP concepts.

------
exclipy
> JavaScript is increasingly functional with the introduction of classes in
> ES6.

Wait, what?

------
zaro
> If everyone hates it, why is OOP still so widely spread?

Maybe not everyone hates it.

------
jokoon
Because it's taught because it's a good way to compartmentalize code when you
distribute the task of writing code. Writing code is in teams.

Like a lot of things, it's a matter of culture in academics or elsewhere.

This article doesn't talk about the drawbacks of OOP, one is the tendency of
programmers to make things abstract when it's unnecessary. And it doesn't even
try to explain why people hate it.

In france we call an regular subject point a "maronnier", which is tree that
gives fruits every year, fruits everybody likes.

------
collyw
OPP is still quite a nice way to organise things. I think it is miss-used and
misunderstood to an extent. Overuse and applying it to everything probably
isn't going to end well hence the hate for Java "factory factory" type code.

Say you have a string, in Java, Python or whatever. It it more natural to
uppercase it in an oop style mystring.upper() or a functional style
upper(mystring)? Personally I think it makes things more manageable to keep
the data and functionality together.

------
superbaconman
> good OOP practice means you provide getter and setter methods to control
> access to that data.

I know almost nothing about "OOP', but I was under the impression this was bad
OOP?

------
andrewprock
My guess is that it is slighly better than the other prevailing paradigm: DB
oriented programming.

In DB oriented programming, instead of god objects that store global state for
everything under the sun, there is a god database that stores global state for
everything under the sun.

Historically, software engineering has been a cat and mouse game of
referencing global state, finding some clever way of hiding it, and then
finding an even more clever way of referencing it again.

Lather - rinse - repeat!

------
hibbelig
It's unclear to me how the addition of classes to Javascript has made it more
functional. Is this a bug in the article, or am I missing something?

------
jasonhansel
What I really wish is that we had a popular language with support for
existential types. They provide a very nice way of unifying OOP-style
encapsulation with FP-style parametric polymorphism and generic programming.

For more info, see the docs for the Haskell extension:
[https://wiki.haskell.org/Existential_type](https://wiki.haskell.org/Existential_type)

------
bborud
Polymorphism does not really depend on inheritance. Go is an obvious counter-
example.

Also, it isn’t like OOP is one programming paradigm. It is several that make
up one region of a landscape. And within each paradigm there is room for
styles.

Finally, if X is better: then ask instead how you (yes, you) will make other
people use, and like, X. People change languages because they find something
that helps them achieve goals.

------
pwinnski
We complain about the things we use, and wrestle with. There are fewer
complaints about, say, Lisps, because there are fewer people using Lisps.

------
odyssey7
“usually it turns out that their undergraduate curriculum has not recovered
from the transition from Pascal to something like C++ or Java.”

Also: “what has become our past, forever remains so”

— Dijkstra, on trendy 90s/millennium OOP in academia.

[https://www.chrisdone.com/posts/dijkstra-haskell-
java/](https://www.chrisdone.com/posts/dijkstra-haskell-java/)

------
renewiltord
Gonna go out on a limb here and make a hypothesis that is highly likely to be
false but which I think is interesting: maybe it's just because namespacing is
a natural thing in OOP and that makes auto-complete easier. So the advent of
auto-complete and namespacing without OOP will end the popularity of OOP.

------
nybblesio
I feel the Story of Mel is appropriate for this thread. And to quote the
legend himself, "If a program can't rewrite its own code, what good is it?"

[http://www.cs.utah.edu/~elb/folklore/mel.html](http://www.cs.utah.edu/~elb/folklore/mel.html)

------
tayistay
Count me mostly a hater. OOP as typically done (C++, Java) is bad for two
reasons:

1\. Heavy use of reference semantics prevents local reasoning about code. 2\.
Inheritance is really brittle. A subclass can break superclass invariants.

I don't think anyone really contests either of those... it's just a matter of
how much you can put up with.

------
d23
> [...] the object oriented programmer as “a greek philosopher or 19th century
> naturalist concerned with the proper taxonomy and description of the
> creatures and places of the programming world.”

This is a good one if you extend it a bit further: they are concerned with the
proper taxonomy and it usually happens to be wrong.

------
svachalek
There's a certain "thought leader" segment of programmers that are pushing
hard for FP, but the article assumes everyone hates OOP rather than trying to
justify that assertion.

It ends with talking about how loved Scala is as a language, while most of the
Scala code I've seen is more OOP than FP.

------
Ericson2314
OOP doesn't mean anything, so by definition, or lack therefore, it cannot be
or not be widespread.

Rather, people need buzzwords do dress up their non-thoughts on software
architecture, and no new ones supplanted OOP's so they are still in use.

Maybe someday "container" will replace "object" :/.

------
Ensorceled
This is kind of a follow on to the problem of "if all you have is a hammer,
every problem looks like a nail"; to over stretch the analogy, this article is
like asking "now that we have power drills and sawzalls, why do people still
use hammers".

Because some problems still nails?

------
threatofrain
OOP is coming back notably in the front-end, where a few popular frameworks
model the GUI as a composable hierarachy of objects, some with internal state
and some more like stateless functions; plus some apparatus to deliver state
from the parent to some deeply nested child.

~~~
cuddlecake
Can you name one or two of those popular frameworks?

Having state in a closure does not imply that it's OOP, so I'd really like to
see those frameworks for reference.

------
axilmar
Just use what is the best tool for the job, people. No need to use only one
way or another.

I am using FP together with OOP when it makes sense, with great results. Both
approaches have their advantages in specific contexts.

------
agumonkey
\- still taught as the main paradigm in classes ?

\- still the main target in interviews (GoF pattern much) ?

------
flowerlad
Why is OOP still so widely spread? Because everyone loves it. Other paradigms,
such as functional, are as old as OOP, but OOP won because it is awesome.

The premise of the question _" If everyone hates it..."_ is invalid.

------
marsdepinski
The internet, where every fresh out of bootcamp grad can be an expert... OOP
works and once you understand how to use it, very powerful to create solid
software without getting all dry in the mouth.

------
kasperni
Brian Goetz had a great talk about this "FP vs OO: Choose Two"

[https://www.youtube.com/watch?v=8GWZE2Y2O9E](https://www.youtube.com/watch?v=8GWZE2Y2O9E)

------
srtjstjsj
An author who thinks _Scala_ is not OOP is simply not credible.

Scala was invented to merge OOP and FP.

The article is nonsense. It offers no alternative and then wonders why the
thing everyone uses is still popular.

------
SPBS
This articles hits the head on why I think OOP is hot air. Everything that OOP
espouses is achievable through a different way from what an OOP language like
Java chose.

Abstraction and Encapsulation? Every programming language lets you do that
with functions (or some other way).

Inheritance? Even OOP die-hards favor interfaces over inheritance.

Polymorphism? Interfaces (like in Go).

What's left to distinguish OOP with? The bad choices that Java made, like not
allowing standalone functions i.e. Execution in the Kingdom of Nouns. That's
what everyone hates on when they say they hate OOP, they hate Java's style of
OOP.

When you look at the 'virtues' of OOP it all falls apart because other non-OOP
language achieve the same thing without being Java.

------
baggy_trough
Inheritance is usually bad, but encapsulation and composition are good.

------
Nginx487
It is widely spread and will remain spread, because it's a universal paradigm
of mapping real-world objects into program code, and it does not have any
alternatives. Period.

------
x87678r
from the wiki page [https://en.wikipedia.org/wiki/Object-
oriented_programming](https://en.wikipedia.org/wiki/Object-
oriented_programming)

>Significant object-oriented languages include Java, C++, C#, Python, R, PHP,
Visual Basic.NET, JavaScript, Ruby, Perl, Object Pascal, Objective-C, Dart,
Swift, Scala, Kotlin, Common Lisp, MATLAB, and Smalltalk.

So pretty much every popular language out there. Doesn't look so hated. :)

~~~
Closi
Lots of those languages are often not applied in an OOP way, eg python.

------
beastman82
Because there are untold legions of programmers being taught it and Java in
school. Most people have never seen other styles much less coded in them.

------
ryanisnan
> you can have your class Cake and EatCake() it too

Cake should inherit Food or Pastry or something and Eat should be made a
generic that accepts a base class

------
nenadg
there is no problem with oop, just nobody ever 'did it properly™', and even if
it did, it didn't

/sarcasm

------
jerf

        1. A → B
        2. ¬B
        ∴  ¬A

------
glaive123
I love OOP. Hope it stays widely spread. Simplicity beats performance for me
every day of the week.

------
keb_
Uncle Bob goes into this every now and then during his talks.

See:
[https://youtu.be/zHiWqnTWsn4?t=2263](https://youtu.be/zHiWqnTWsn4?t=2263)

------
Simulacra
Because it’s easy to learn.

------
vvpan
Oh boy. Here we go, here I am commenting on a subject on which _everybody_ has
an opinion. A lot of people say that "OOP" is just a tool. Or that it is
overused. Or that it isn't used properly. I will say that even though I
sometimes use objects I am not a fan of almost every "object-oriented"
codebase that I've had to work with. The issue is that OOP is presented as an
abstraction that, if you understood it, would provide for good readable code.
The way I judge good principle is whether when, inevitably, junior to mid-
level programmers start working on the codebase will they be able to preserve
some amount of sounds structure. I would say that OOP offers very little here,
as I've seen even senior developers write what to them was "good OOP code" but
in practice nobody could work with.

Here are some things that OOP does not give you:

* Is your state normalized, i.e. saved only in one place? You do not know.

* Is your execution predictable? Parent to child? And how do you do it when it's reversed.

* What should be public and modifiable and what should be intermediate state internal to the object. And should intermediate computed values be stored next to values determining the true state of your application? (even though there are "public" and "private" modifiers it is quiet difficult to determine what is truly public and cannot be modified through some method. This makes it more difficult to understand what the state of your application truly is and what are intermediate convenience values).

* Are there limitations on passing state around? Or can large chunks of state be passed to multiple actors in the form of classes who change it concurrently or might store it for later use?

* How much state should be in a single class? In other words: how many classes can a class encapsulate and how complex could those classes be?

* Should something that has no state be an object or just a function (in some languages you are not given the option at true, but can't say that it's awesome).

* Should you be allowed to use event buses and how to prevent spaghettification? (cause events really are akin modern goto statements).

* etc.

Basically the ability to compose the state, type and methods is so wildly
open-ended that almost always what I see is just an ever expanding convoluted
bloat of state spread ts chaotically that it become extremely difficult to see
what the state of your application is at any moment. Everybody has their own
idea of what an object _is_, what should be an object and how they should come
together. And that is for every developer on the team. So you can follow the
absolute best of OOP practices and still end up with a mess.

Let's look at a counter-example. It is not a system that claims to be
universally usable but that is the point. I'll use the, quiet banal, example
of React. Yes, it is a framework, and in a way it does have objects, but
really it borrows heavily from functional programming in the sense that it
says that state is king and the single most important thing in your program.
That you _must_ have strong constraints as to how your state is created,
organized and modified. (In contrast to a class, which is state that you can
pass around as much as you want and the whole codebase could modify it at
will).

* The application is always a predictable tree of dependencies.

* State is either stored separately altogether (using a state-store such as redux, mobx, etc.) or bound to a particular element in the tree hierarchy.

* State only flows down the tree, ideally immutably.

* A component (unlike a class) cannot modify state of anything outside of itself.

* Only "has-a" relationships are allowed - no polymorphism.

* Only event can be passed up.

* State is essentially a collection of easily inspectable primitives. Meaning that even though a component can _contain_ another component a class is not a valid member of component state.

While a system like this could be built using OOP primitives (classes).
Nothing about OOP suggests this system. Yes, you can build it, but can build
something absolutely unrelated. And, really, it enforces things that are the
antithesis of many things that "proper OOP" espouses.

Perhaps the main thing of any system is to create a predictable and well-
structured relationship between elements of state. I think that wonderful
examples of the basis of such a system are Go and Rust. To be honest, I barely
know the languages, but from what I see is that they make _type_ the most
central element of the language. If you have your types well-defined and be
separate from how the types are used you are already suggesting many things
that could prevent state-sprawl. A struct defines the basic primitive around
which your program is based.

* Struct has no private intermediately computed values. If you do not want to recompute something - memoize, do not bloat the state with random data that is inseparable from you base state.

* Structs provide a very predictable "has-a" top-down dependency between state

* No inheritance, so composition is enforced.

* Keeping types and functions that operate on those types makes it very explicit what a function does - is it a method or is it a function?

------
throw1234651234
Because you can do functional programming in OOP. In the sense that it was
originally intended, which is just writing pure functions to avoid side
effects.

~~~
dddbbb
Intended according to whom?

~~~
throw1234651234
The definition: "It is a programming paradigm in which function definitions
are trees of expressions that each return a value, rather than a sequence of
imperative statements which change the state of the program"

There is no reason you can't do this in C# or Java.

------
dustingetz
Okay, OOP sucks but programmers can recognize it because it's in their field.
But what about the domains we don't have expertise in? OOP sucks because
literally everything sucks, across all domains, all of civilization is 100%
dysfunctional. Take healthcare, for example.

