Live data from Hacker News

Why OO Sucks by Joe Armstrong (2000)

cs.otago.ac.nz

111–120 of 396 posts

Re: Why OO Sucks by Joe Armstrong (2000)

#111
post #69
post #31

Well, I disagree with 99% of this... I'm a guy that started with C, moved to functional programing, added C++, and now do all 3. > Objection 1. Data structure and functions should not be bound together Well, in my experience, in every almost every code-base (either from functional, or imperative programing), we end up with modules, witch are a set of function taking the same type as a parameter. This is very close to…

Upvoted because it's well-articulated, even though I disagree. > Well, in my experience, in every almost every code-base (either from functional, or imperative programing), we end up with modules, witch are a set of function taking the same type as a parameter. This is very close to binding the functions and the types... There is a key distinction: If I have two subsystems that use the same data in different ways, I…

> Upvoted because it's well-articulated, even though I disagree.

Appreciate it :)

> There is a key distinction: If I have two subsystems that use the same data in different ways, I can keep those concerns separate by putting the functions for each concern into a different module. Binding all the functions to the type mixes the concerns together and creates objects with way too much surface area.

This is where composition helps. Now, historically, indeed OOP programmers have not been the best at using composition. Now, looking at more recent projects, this has got a lot better.

> Also, most OO langs make a big ceremony out of each new type: create the class file, create the test file, blah blah blah. I want types to be cheap so I can make them easily and capture more meaning with less work.

Totally agree with that, the ability to define a type in one line and have it reflected though the entire code base through type inference is the one thing that I miss the most in C/C++.

Re: Why OO Sucks by Joe Armstrong (2000)

#112
post #86
post #77

A few notes: Binding data and functions together beats operating on global data visible to everything. One of the big wins of OOP is less exposed global data. A big problem with OOP in C++ was that it wasn't opaque enough. The headers needed to use an object contain info only useful to the object's private functions. This creates recompile hell. Multiple inheritance is seldom worth the headaches. Overriding a member…

> Binding data and functions together beats operating on global data visible to everything. One of the big wins of OOP is less exposed global data. “Passing state as parameters” is what solved the “everything operating on global state” problem. Binding functions and state permitted polymorphism/abstraction. > Multiple inheritance is seldom worth the headaches. Single inheritance is never worth the headaches. :) > Obj…

There are so many kind of polymorphism. Many of them do not require objects. Executing a closure is a form of polymorphism. As is manipulating a generic type.

Re: Why OO Sucks by Joe Armstrong (2000)

#113
post #8

Everything sucks, they just all suck differently. I still think OO provides a pretty easy mental framework for programming. You can get good results. Bit of discipline without going crazy and it works really effectively. Despite its shortcomings.

The basic situation is this. We often have a situation in which N operations contain M cases (for M different types).

Without OOP, we have the ugly organization of writing N functions that each dispatch M cases of code by pattern matching or switching on a numeric type field or whatever.

OOP lets us break these pieces of logic into separate methods. And then in the physical organizationof the program, we can group those methods by type. For any given type, we have N methods: each one implements one of those N functions just for that type.

This is a better organization because if we change some aspect of a type, all the changes are done in one place: the implementation file or section of file for that type. Or if a new type is added, we just add N methods in a new file or section; we don't have to change the code of numerous functions to introduce new cases into them.

Those who write articles opposing OOP never seem to constructively propose an attractive alternative for this situation.

It is this attractive program organization which swayed developers toward OOP, or even full blown OOP evangelism. It's not because it was hyped. OOP has concrete benefits that are readily demonstrable and applicable.

OOP is what allows your operating system to support different kinds of file systems, network adapters, network protocols, I/O devices and so on.

It's unimaginable that the read() system call in your kernel would contain a giant switch() on device type leading to device-specific code, which has to be maintained each time a new driver is added.

Re: Why OO Sucks by Joe Armstrong (2000)

#115
I agree with a lot of the criticisms in Dr. Armstrong's article, but I would say that they mainly affect languages such as Java that enforce OO; multi-paradigm languages that allow for OO but don't force it on you don't have these problems. I believe that OOP has valid uses.

> Objection 1. Data structure and functions should not be bound together

In languages like OCaml and C, one defines types separately from functions. Sometimes, however, I find that a function is best associated with a particular type. In OCaml, that's one purpose of modules. (The convention is to call the main type "t.") However, this organization shouldn't be forced on you.

> Objection 2. Everything has to be an object.

This objection only applies to languages like Java that force OO on you. In OCaml or C++, I don't have to use OO, but I still can if I want to.

> Objection 3. In an OOPL data type definitions are spread out all over the place.

Armstrong complains about having to decide what to inherit from when making a Time object. IMO this is a strawman; in Java, classes inherit from Object by default and I don't see any inconvenience. I do agree that it can be annoying that Time has to be object-oriented, and this is where the benefit of OO being voluntary comes in.

> Objection 4. Objects have private state.

I either disagree with or don't understand this objection. Dr. Armstrong lists three ways to deal with state.

His third option is to use pure functional programming. I see both the beauty and practical value in making functions be functions in the math sense, that is to say, mappings from elements of the domain to elements of the codomain. Then, you get equational reasoning. I am sympathetic to this idea. Nevertheless, languages like Haskell aren't for everybody.

His second option is to control access to mutable variables with scope. You can implement a pure function in an imperative way, and that can be a form of encapsulation. This is a good approach, too.

Dr. Armstrong's first option, which he says is the worst, is the idea that objects maintain hidden state which people control via methods. To me, this isn't about state, but rather encapsulation and abstraction. The idea is that when one, say, inserts into a hash table, the person doesn't think about the implementation ("hash the key and walk down the corresponding bucket"), the person thinks of the abstract problem domain ("map this key to this value"). The hash table interface hides its internal state behind the methods. Even in a programming language like C, one writes functions that operate on, and mutate, structs to abstract things away.

Although the second option is good, I see it as orthogonal to the first option, not a superior alternative. If you are going to confine state to within a function, ultimately, don't you have to do mutations on the local variables, and therefore call some kind of method or impure function on them? However, perhaps I am misunderstanding this fourth point.

A lot of arguments, including this submission, pit OOP against FP and argue that FP is superior to OOP. Even though I use FP, I also think that OOP can be useful. They are not opposites and don't have to conflict.

OCaml is infamous for its object layer, yet I ended up using it for a project. I wanted to describe UI "widgets" such that I could compose arbitrary different types of widgets. Before deciding on objects, I had considered first-class modules or a record of functions, but ultimately decided that objects were the most readable choice.

In my OCaml program, I mainly viewed OOP as a way to abstract different types into a common idea. Widgets are all different, and they have different behaviors, but they all have a position in space, a length, and a width. One can also reposition them (mutation!). To me, the purpose of OO is to express ideas such as these. I note that when I used OOP here, I cared less about state and more about the abstraction of what a "widget" was, via dynamic dispatch. It is bad when the language forces OO on you, but it has valid uses.

Re: Why OO Sucks by Joe Armstrong (2000)

#116
post #71

Earlier quoted context omitted.

I think this might be a little unfair to JavaScript. No doubt it's a multi-paradigm language, but there's a huuuge FP community in JS, and loads of code bases (esp. in React) are written in a very functional style. Definitely not comparable to passing function pointers around in C.

Almost everyone I've come across who writes JS in a "functional style" has done it because they've had prior experience using a FP language and are applying those lessons to JS. I believe the OP is talking about those FP languages, such as Haskell and Clojure, which have a very different programming experiences. While JS supports it in many ways, it's still not a style inherent in a multi-paradigm language like Javas…

You can get maybe 80% of the way there, but non-FP dependencies can still hurt you. That's also a problem with clojure dependencies on Java libraries, but less so because at least the clojure ecosystem mostly buys into the FP paradigm.

Re: Why OO Sucks by Joe Armstrong (2000)

#117
post #97

That's a bit weird to see a seasoned programmer harboring those views. I remember that when learning OOP I was equally confused. "I can do all that with functions and structures already." And indeed you can. There is nothing you can't technically do without OOP. OOP is not a programming feature, it is a software engineering feature. It allows for cleaner APIs and higher levels of abstractions. IMO the core feature of…

The problem with placing operator overloads within the definition of one object is — which object do you look to when trying to add two different types of objects and the assumption is TypeA.+(TypeB) is the same as TypeB.+(TypeA)? You put them in an inheritance perhaps, but that might unnecessarily complicate your type classification. Okay, so you use some sort of interface, perhaps with a default implementation. Well, interfaces aren’t unique to OOP, but they do add a bit of confusion — when looking for an implementation you might now have 3 places to look (Possibly 4 mentions if default implementations aren’t allowed).

Really there’s an easy conclusion to this — allowing and preferring user defined operators or operator overloads is a hotly debated topic and one where there appears to be no right answer — about the only conclusion you can draw then, is that operator overload is not exclusive to OOP: https://softwareengineering.stackexchange.com/questions/1809...

I’d also suggest that with functional programs, there are limits to how much you should cram in to one program, and that a smart way to modularize your code would be to, for example, follow the Redux reducer pattern and build or compose larger state objects and operations from functions that operate on just parts of the state object—this way you isolate written changes in a similar way to private OOP variables, where it’s just not expected (or even “in scope”) to modify other parts of the global state. Additionally, you can as in OOP control access to state by encouraging the use of “selector functions” or not directly accessing state. You could make your functions take smaller typed structs of state, really, functional programming is at least as expressive as OOP programming. I’ll say that both allow you to make mistakes like mix concerns, or use lots of globals, perform magic with meta-programming or overloading, or not be expressive enough to create your own DSL in—OOP or Functional, these concerns are in my experience shared by basically any language.

Re: Why OO Sucks by Joe Armstrong (2000)

#118
post #65

Earlier quoted context omitted.

I don't think what I'm about to say is necessarily inherently true, but it reflects how things seem to work in practice: It seems to me that part of the problem is that OO doesn't force you to have discipline and/or without constant vigilance (which product owners are never willing to schedule for) the system inevitably gets out of control over time. On the other hand, it seems to me that the core principles of funct…

I wish more languages would let you do stuff like mark reference parameters to methods as unable to be changed or reassigned within the method, get a readonly reference to a list without having to make a copy, that sort of thing. It doesn't have to be forced, just give me the option so I can get a guarantee on something if I want to.

If you mark all fields and variables in Java as final, you get pretty much this experience?

If I could go back in time and unilaterally make one change to Java, it would be to make `final` default. But if you just get in the habit of using it (the IDE helps), non-final variables look broken. And once objects have all-final fields, immutability just starts spreading upward in your code.

Re: Why OO Sucks by Joe Armstrong (2000)

#119
post #35

This doesn't contain his most famous line on the topic: You wanted a banana but what you got was a gorilla holding the banana and the entire jungle. https://www.johndcook.com/blog/2011/07/19/you-wanted-banana/

> If you want to reuse (or test) a functional banana, you don’t have to set up a stateful gorilla to hold the banana first.

...& if you don't want the stateful gorilla?

Re: Why OO Sucks by Joe Armstrong (2000)

#120
post #8

Everything sucks, they just all suck differently. I still think OO provides a pretty easy mental framework for programming. You can get good results. Bit of discipline without going crazy and it works really effectively. Despite its shortcomings.

Agreed. I remember thinking "what don't I get? Why do we need getters and setters?". After some years (and discovering Python), I realized there's nothing to get, it's just ridiculous overengineering 95% of the time. Same goes for a lot of stuff in OO. I attribute it to the corporate mindset it seems to thrive in, but I could be wrong.

Getters and setters make more sense in languages where you can't override attribute lookup.
Post reply on HN