Live data from Hacker News

Why OO Sucks by Joe Armstrong (2000)

cs.otago.ac.nz

291–300 of 396 posts

Re: Why OO Sucks by Joe Armstrong (2000)

#291

Earlier quoted context omitted.

That sounds wise but it doesn't really mean anything. There are things that suck about a Ford Pinto and there are things that suck about about a Tesla Model S, but saying that they both have their downsides is technically true while obscuring the fact that the Tesla is a muuuuuuuuuuuuuuch better car.

Is there a name for this particular argumentative fallacy?

False equivalence - even if they are similar in one respect doesn't erase the other differences. Saying both a bicycle and a truck can move things on roads and can kill you if run over by one are technically true but misses many other larger differences.

Re: Why OO Sucks by Joe Armstrong (2000)

#292
post #247
post #72

Earlier quoted context omitted.

Admittedly I'm somewhat of a FP fanboy, but I seriously cannot disagree with you more on this. Functional Programming (and Logic Programming) are better than other paradigms because, unlike Java (or C++, or C#...) there is an emphasis on correctness , and the people working on FP compilers (like Haskell and Idris) are utilizing mathematics to do this. No idea on your opinion on mathematics, but to me Math/Logic reign…

Functional programming has no relevance to the correctness of code. You'll notice that it's virtually unheard of to use any FP languages in critical software. Instead they use languages that lend themselves well to code reviews, static and dynamic analysis, model-based design and proofs, etc. Like C, Ada and some domain-specific stuff. The kind of "correctness in the small" offered by Haskel through its type system c…

>You'll notice that it's virtually unheard of to use any FP languages in critical software.

Erlang powers around 40% of the world's phone networks; and if it's not mission-critical I'm not entirely sure what is.

For that matter, Whatsapp is also written in Erlang and Jane Street does trading applications in OCaml. Without making a judgement on whether or not they should, both Whatsapp and Jane Street create very large apps and have created successful businesses with FP.

> Instead they use languages that lend themselves well to code reviews, static and dynamic analysis, model-based design and proofs, etc

I can't tell if you're being serious; are you suggesting that Functional Programming doesn't lend itself to proofs? Really? Have you ever heard of Coq or Idris or Agda? They literally have modes to prove the correctness of your code.

What about functional programming doesn't lend itself to code reviews? I did F# for a living for two years and we had regular code reviews. I also used the .NET performance profiling tools which worked fine for F#.

> The kind of "correctness in the small" offered by Haskel through its type system can be obtain also in languages like C++, Swift and others.

Uh, no. Sorry, that's just flatly wrong.

Yes, static analysis tools are awesome, but you will never get the same level of compile-time safety from C++ that you will from Haskell or Rust or any number of functional languages. The type systems offer very little information, making it impossible for the compiler to shield anything.

Re: Why OO Sucks by Joe Armstrong (2000)

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

Rust is immutable by default, optionally mut, and you lend different kinds of references & (immutable-- can have many) &mut (mutable reference-- must be unique)

Re: Why OO Sucks by Joe Armstrong (2000)

#294
post #150

Earlier quoted context omitted.

> Isn't a method call a message, and the return value a message back? It is! In my view, the point that Alan Kay and Joe Armstrong are trying to make is that languages like C++/Java/C# etc have very limited message passing abilities. Alan Kay uses the term "late binding". In Kay's opinion, "extreme late binding" is one of the most important aspects of his OOP [1], even more important than polymorphism. Extreme late b…

C++'s vtable is also late binding, since you don't know which implementation you're calling until runtime. And there's no such thing as "extremely late binding". > In C++, for example, the only kind of late binding that you have is abstract classes and vtables. That's not true, you can always have a "send_message(string id)". Few people do it because you lose static type safety. And some languages, like C# and Scala,…

> C++'s vtable is also late binding, since you don't know which implementation you're calling until runtime. And there's no such thing as "extremely late binding".

C++'s vtables are determined at compile time. The specific implementation executed at a given moment may not be possible to deduce statically, but the set of possible methods is statically determined for every call site: It consists of the set of overridden implementations of the method with that name in the class hierarchy from the named type and downwards.

No such restriction exists in Ruby or Smalltalk or most other truly dynamic languages. E.g. for many Ruby ORM's the methods that will exist on a given object representing a table will not be known until you have connected to the database and read the database schema from it, and at the same time I can construct the message I send to the object dynamically at runtime.

Furthermore the set of messages a given object will handle, or which code will handle it can change from one invocation to the next. E.g. memoization of computation in Ruby could look sort-of like this:

    class Memo
      def method_missing op
         result = ... execute expensive operation here ...
         define_singleton_method(op) { return result }
      end
    end
After the first calculation of a given operation, instead of hitting method_missing, it just finds a newly created method returning the result.

"Extreme late binding" is used exactly because people think things like vtables represent late-binding, but the ability to dynamically construct and modify classes and methods at runtime represents substantially later binding.

E.g. there's no reason why all the code needs to be loaded before it is needed, and methods constructed at that time And incidentally this is not about vtables or not vtables - they are an implementation detail. Prof. Michael Franz paper on Protocol Extension [1] provided a very simple mechanism for Oberon that translates nicely to vtables by dynamically augmenting them as code is loaded at runtime. For my (very much incomplete) Ruby compiler, I use almost the same approach to create vtables for Ruby classes that are dynamically updated by propagating the changes downwards until it reaches a point where the vtable slot is occupied by a different pointer than the one I'm replacing (indicating the original method has been overridden). Extending the vtables at runtime (as opposed to adding extra pointers) would add a bit of hassle, but is also not hard.

The point being that this is about language semantics in terms of whether or not the languages allows changing the binding at runtime, not about the specific method used to implement the method lookups semantics of each language - you can implement Ruby semantics with vtables, and C++ semantics by a dictionary lookup. That's not the part that makes the difference (well, it affects performance)

> That's not true, you can always have a "send_message(string id)". Few people do it because you lose static type safety. And some languages, like C# and Scala, have dynamic types that allows for the "method_missing" protocol and such features are very unpopular.

If you're working in a language with static typing you've already bought into a specific model; it's totally unsurprising that people who have rejected dynamic typing their language choice will reject features of their statically typed language that does dynamic typing. I don't think that says anything particularly valuable about how useful it is. Only that it is generally a poor fit for those types of languages.

[1] Protocol Extension: A Technique for Structuring Large Extensible Software Systems, ETH Technical Report (1994) http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.42....

Re: Why OO Sucks by Joe Armstrong (2000)

#295
post #72

Earlier quoted context omitted.

Admittedly I'm somewhat of a FP fanboy, but I seriously cannot disagree with you more on this. Functional Programming (and Logic Programming) are better than other paradigms because, unlike Java (or C++, or C#...) there is an emphasis on correctness , and the people working on FP compilers (like Haskell and Idris) are utilizing mathematics to do this. No idea on your opinion on mathematics, but to me Math/Logic reign…

none of my coworkers use it This sounds like the root of your problem. If you want to do FP, and none of your coworkers want to do FP, then your problem isn't really the language. If you're in a Java shop, maybe start by evangelizing FP rather than a totally different language/platform? It's possible to do FP in Java, and (IMO) it ends up pretty reasonable. But it's not the default habit for J Random Java Programmer,…

Sure, but as John Carmack has said, if the compiler allows something, it will end up in the codebase once it gets sufficiently large.

I work for a brand-name big company (I won't mention it here but I'll tell you if you email me) that hires incredibly talented engineers that are a lot smarter than me. The codebase I work on is around ~20 million lines of Java, and I've seen stuff in there that is so incredibly gross that a compsci professor would write "see me after class" if you submitted it.

Example: I once saw a piece of code doing this:

    do {
        // doing stuff
    } while (false)
It took me about 10 minutes of digging into the code to realize that the person who wrote this was doing this so that they could add a `break` in there as sort of a makeshift `goto` so they could early-exit and skip all the rest of the stuff in the block. Needless to say, I was horrified.

Why is it that incredibly talented engineers are writing awful code like that? It's certainly not incompetence; what almost certainly happened was that there was some kind of time-crunch, and the dev (understandably) felt the need to cheat. This is a direct consequence of the compiler allowing a bad design.

Re: Why OO Sucks by Joe Armstrong (2000)

#296
post #72

Earlier quoted context omitted.

Admittedly I'm somewhat of a FP fanboy, but I seriously cannot disagree with you more on this. Functional Programming (and Logic Programming) are better than other paradigms because, unlike Java (or C++, or C#...) there is an emphasis on correctness , and the people working on FP compilers (like Haskell and Idris) are utilizing mathematics to do this. No idea on your opinion on mathematics, but to me Math/Logic reign…

OOP has evolved. If you want to get a clearer idea of where it's at, look at Kotlin instead of a twenty-five year old language.

Sure, Scala has some neat features too (though I'm not 100% sold on the language).

That said, and I addressed this specifically, when I say "OOP" in the software world, people typically think of Java, C++, or C#, and those are what I'm addressing specifically.

I suppose in the most technical sense of the word, you could argue that Erlang is OOP at some level, and Erlang is awesome, so if we want to play with definitions then sure, I'll concede that OOP is good, but until the industry as a whole agrees on these terms, and doesn't treat OOP as a synonym for "Java/C++/C#", I'm still going to say that I hate OOP.

Re: Why OO Sucks by Joe Armstrong (2000)

#297

Earlier quoted context omitted.

Isn't a method call a message, and the return value a message back? Or is it that "true OO" must be asynchronous?

I think the spirit of OO, an object has agency over how the message is interpreted in order for it to be considered a message. If the caller has already determined for the object that it is going to call a method then the object has lost that agency. In a 'true OO' language an object may choose to invoke a method that corresponds to the details within the message, but that is not for the caller to decide. Consider th…

vtables is an implementation detail. To compile Ruby with vtables, consider this:

    class A
      def foo; end
    end
    
    class B 
Now you make a vtable for class A that looks conceptually something like this:

    slot for foo = address_of(A#foo)
    slot for bar = method_missing_thunk(:bar)
And a vtable for class B that looks like this:

    slot for foo = address_of(B#foo)
    slot for bar = address_of(B#bar)
The point being that you can see every name used in a method call statically during parsing, and can add entries like `method_missing_thunk(:bar)` to the vtable, that just pushes the corresponding symbol onto the stack and calls a method_missing handler that tries to send method_missing to the objects.

You still need to handle #send, but you can do that by keeping a mapping of symbols => vtable offset. Any symbol that is not found should trigger method_missing; that handles any dynamically constructed names, and also allows for dynamically constructed methods with names that have not been seen as normal method calls.

When I started experimenting with my Ruby compiler, I worried that this would waste too much space, since Ruby's class hierarchy is globally rooted and so without complicated extra analysis to chop it apart every vtable ends up containing slots for every method name seen in the entire program, but in practice it seems like you need to get to systems with really huge amounts of classes before it becomes a real problem, as so many method names gets reused. Even then you can just cap the number of names you put in the vtables, and fall back to the more expensive dispatch mechanism for methods you think will be called less frequently.

(redefining methods works by propagating the new pointer downwards until you find one that is overridden - you can tell it's overridden because it's different than the pointer at the site where you started propagating the redefined method downwards; so this trades off cost of method calls with potentially more expensive method re-definition)

Re: Why OO Sucks by Joe Armstrong (2000)

#298

Earlier quoted context omitted.

I don't believe he claims to, no. He coined the term “object,” but what he meant by a computational object was different than what it came to mean: a data structure with associated operations upon it. Kay meant a parallel thread of execution which was generally sitting in a waiting state—one could make a very strong analogy between Smalltalk's vision of “objects” and what we call today “microservices,” albeit all liv…

I didn't coin the term "object" -- and I shouldn't have used it in 1966 when I did coin the term "object-oriented programming" flippantly in response to the question "what are you working on?". This is partly because the term at the time meant a patch of storage with multiple data fields -- like a punched card image in storage or a Sketchpad data-structure. But my idea was about "things" that were like time-sharing p…

I think the inspiration from Simula I is something a lot of folks either don't know about, or maybe they know about it but don't recognize its significance. Objects with encapsulated state that respond to well-defined messages are a useful level of abstraction for writing simulations of the sort Simula was built for. They're just not automatically a particularly wieldy abstraction for systems that aren't specifically about simulation. Some (most?) of that is about the skill of the programmer, imo, not some inherent flaw in the abstraction itself.

P.S.: Thank you for all your contributions to our profession, and for your measured response to these kinds of discussions.

Re: Why OO Sucks by Joe Armstrong (2000)

#299
post #145

Earlier quoted context omitted.

You could also make a class of global functions and use that, but I think the point still stands: it forces square pegs into round holes, so to speak.

> You could also make a class of global functions and use that I'm not sure I understand your issue with doing this. You need to put your global (i.e. public static) functions in classes not because Java is forcing OO practices into everything, but because classes effectively serve as Java's translation units. I think they serve this purpose pretty well in practice.

Classes being Java's only translation units are one of the downsides that I'm mentioning. Really my objection is more that it doesn't allow use of the right tool for the job (which is not always an object).

Re: Why OO Sucks by Joe Armstrong (2000)

#300

It really should be noted that years later Joe changed his mind about OO and came to the realization that perhaps Erlang is the only object-oriented language :) From a 2010 interview: ..."I wrote a an article, a blog thing, years ago - Why object oriented programming is silly. I mainly wanted to provoke people with it. They had a quite interesting response to that and I managed to annoy a lot of people, which was par…

That speaks to one of the things that bothers me about OOP's intellectual traditions: there are two different ideas of what "object" can mean, and most object-oriented languages and practices deeply conflate the two.

On the one hand, "object" can mean a unification of data structures with the procedures that act on them. In this view, the ideal is for everything to be an "object", and for all the procedures to actually be methods of some class. This is the place from which we get both the motivation for Java's ban on functions that don't belong to classes, and the criticism of Java as not being truly OO because not every type is an object. In this view, Erlang is not OO, since, at the root, functions are separate from datatypes.

On the other hand, "object" can describe a certain approach to modularity, where the modules are relatively isolated entities that are supposed to behave like black boxes that can only communicate by passing some sort of message back and forth. This ends up being the motivation for Java's practice of making all fields private, and only communicating with them through method calls. In this view, Erlang is extremely OO, for all the reasons described in parent.

I haven't done an exhaustive analysis or anything, but I'm beginning to suspect that most the woes that critics commonly describe about OO come from the conflation of these two distinct ideas.

Post reply on HN