Live data from Hacker News

Why OO Sucks by Joe Armstrong (2000)

cs.otago.ac.nz

261–270 of 396 posts

Re: Why OO Sucks by Joe Armstrong (2000)

#261

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…

Oh wow.

I was really not expecting you to join this conversation and I am very thankful to have crossed paths with you, even so briefly. Sorry for getting you wrong about the “objects” vs. “OOP” thing.

I have thought you could maybe call it “node-oriented” or “thread-oriented” but after reading this comment I think “ecosystem-oriented” might be more faithful a term?

Re: Why OO Sucks by Joe Armstrong (2000)

#262
post #94

Earlier quoted context omitted.

> How about having to create six different files Took me a few reads but it's better stated "six different classes". At first I was confused about why you rely on `java.io.File` for business logic. So, if I'm stuck on JVM, what's my FP alternative that compiles and runs comparatively? Clojure? Scala?

Scala. Particularly Scala 3. Because it is principled but also very pragmatic.

Scala failed because it's the opposite of pragmatic. If you're looking for pragmatic, take a look at Kotlin.

As for Scala 3, it's still years away, if it ever comes out. And when it does, there's little reason to think its goals will be different from what Scala 2 was (an academic language) since it's the same team as Scala 2 writing it.

Re: Why OO Sucks by Joe Armstrong (2000)

#264
post #81
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.

I think OO can work because in many problems we only focus on one thing at a time. If multiple objects with equal complexity/importance are involved, OO can get sticky (e.g. which object should invoke a method, etc). I think Joe's article is intentionally provocative to make a point, but I'd like to see more discussions about when and why OO doesn't work well sometimes and what the course of actions we should take.

I've upvoted you because you spotlighted a very important issue. In OOP we are supposed to think of a program as little pseudo-isolated programs that somehow work together to fulfill the technical requirements.

This model works where it actually represents the real world: Mostly, in distributed systems.

In other areas, it just leads to overengineered piecemeal crap that is incredibly hard to understand. Where you can get control over what happens, you absolutely should get it. Don't act like your program was a thousand little independent components that have their own mind and lifes. Because it isn't like that, and if it was, there was no way you could actually get in control of these to make them produce a very specific outcome.

So the only reason why many OOP programs sort-of work is because programmers never actually respect the abstractions that they set up by defining so many classes and methods. To get the program to work, one needs to know very precisely what each class does in each cases. In the end OOP is just a terrible farce since there is no rhyme and reason for all these classes. It's needless bureaucracy, and prevents us from structuring programs in a more efficient and maintainable way.

Re: Why OO Sucks by Joe Armstrong (2000)

#265
post #155
post #146

Earlier quoted context omitted.

> Objects can have a private state. This is a problem with mutability, not oriented object programing. You can have non mutable OOP. Wouldn't this violate the "encapsulation" pillar of OOP? As far as I know, it's always taught with encapsulation, inheritance, polymorphism being its three pillars. > How has OOP created a software industry that would not have existed if functional programing had "won the fight"? I'm no…

> Wouldn't this violate the "encapsulation" pillar of OOP? As far as I know, it's always taught with encapsulation, inheritance, polymorphism being its three pillars. Encapsulation is "if you have a state, you should encapsulate it". It does not ask you to have a state (even less a mutable one). I quite often use object to represent a logical piece of code, without any attributes. > I'm not sure functional programmin…

The question isn't if OOP or FP will win, but what mix of both is best. A lot of old OOP languages have added features that move them more towards FP. Out of the top of my head C# got E.g. extension methods, lambdas and many ways to be less mutable or pass multiple values around. The bit of programming history i was allowed to experience most definitively became more functional.

Re: Why OO Sucks by Joe Armstrong (2000)

#266
post #95

Earlier quoted context omitted.

I don’t think I’ve ever seen a useful “Getter” abstraction...

It's frustrating to read this thread and your comment kind of crystallized this for me so I'll respond to you. Using an array without having to (manually) calculate the size of the objects contained within is like the major triumph of OO. This is a getter that you almost certainly use constantly. Please try to consider your statements and potential counter factuals before spraying nonsense into the void

> Please try to consider your statements and potential counter factuals before spraying nonsense into the void

My claim was that getter abstractions as described by the GP (abstracting over the “accessed from memory” implementation detail) are not useful. Why do you imagine that your array length example is a reasonable rebuttal?

Re: Why OO Sucks by Joe Armstrong (2000)

#267

Earlier quoted context omitted.

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…

Is it unreasonable to think of the method as a semantic "port" to which messages (arguments) are passed? And languages that allow programmers to bypass OO with jmp instructions seem multiparadigm rather than not-OO...

> semantic "port"

Not unreasonable at all! In fact the term used in objective C and Ruby is “selector”. Beneath the synchronous veneer anyway.

Re: Why OO Sucks by Joe Armstrong (2000)

#268

Earlier quoted context omitted.

Nobody is saying don’t have any abstractions, just that your program hiding state in layers of objects is often counterproductive.

> program hiding state in layers of objects is often counterproductive Do you think it was counterproductive to hide OS-specific file handles, CRT level of caching, and many other things CRT does behind these opaque FILE* object pointers? Such hiding allowed to have very similar and quite easy to use across all platforms. The implementation of these fopen and fwrite functions relies on kernel calls like open/write on…

> Do you think it was counterproductive to hide OS-specific file handles, CRT level of caching, and many other things CRT does behind these opaque FILE* object pointers?

To answer that question for parent, no, he obviously doesn't think so. And yes, streams are basically OOP (they are implemented using "method dispatch"). Streams are one of the few successful abstractions out there.

And when I say "successful" I mostly mean "necessary". Because they're leaky. Consider fseek(3), ftell(3), fileno(3), fflush(3), fclose(3), fsync(2), posix_fadvise(2), isatty(2), fcntl(2), ioctl(2) and many more. All operations that are not supported for all streams, but necessary for some (like file system files, network connections, terminals devices...). Essentially when you use any of these you concede to break the abstraction.

It's incredibly hard to handle these streams correctly, and the vast majority of programs are faulty in that they don't handle most error conditions correctly. In some cases, it isn't even possible to handle errors through the API! See close(2)

So again, not saying we shouldn't have a stream abstraction. But abstractions come at a huge price, and therefore it's incredibly misguided to make every program a layering of thousands of pseudo-isolated objects that bring their own bug-prone abstractions and idiosyncrasies.

Re: Why OO Sucks by Joe Armstrong (2000)

#269
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,…

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

That is the difference. If every class in C++ had only one method - send_message and each object is an independent thread, you will get how Erlang works. That is how you would do the actor model in C++.

Inheritance, Polymorphism is emphasised in Java, C++ and C#, whereas Functional programmers emphasise function objects / lambdas / Command Pattern where you just have one method - calling the function. Infact having just method you no longer need Polymorphism / Interfaces.

Re: Why OO Sucks by Joe Armstrong (2000)

#270

> The “hide the state from the programmer” option chosen by OOPLs is the worst possible choice When you code C and write something as simple as fwrite( "Hello world", 1, 11, stream ); that line of code changes state of the file stream object in CRT, state of file caches in OS, state of B-tree nodes in file system driver, state of disk firmware, state of NAND flash chips… It’s not just OS and drivers. Any sufficiently…

Nobody is saying don’t have any abstractions, just that your program hiding state in layers of objects is often counterproductive.

Another example why hiding state can be a good thing. Consider following code:

    void* ptr = malloc( 32 );
No OOP is involved here, yet the malloc function operates on a critically important piece of mutable global state. The state is quite complex due to numerous reasons: performance, fragmentation, multithreading & deadlocks, alignment… Just look at ptmalloc (linux) or jemalloc (BSD). I think it’s undocumented on Windows but I’m sure it’s at least as complex, search for “low fragmentation heap” which is the default one since Vista.

I don’t think hiding that state in layers of abstractions is counterproductive, I think it was good, due to the following reasons.

1. In 99% cases makes it easier to write code. Heap state is very complex in practice, and just like file IO, it spawns across user mode state of your process and OS kernel state. Hiding the state all together allows programmers to reason in terms of very simple APIs, it’s just 2 functions malloc/free with very clear purpose each.

2. Hiding that state makes bugs in your code less likely to corrupt it. If you instead have something like void* malloc( size_t bytesCount, struct HeapState *processHeap ) it becomes easier to accidentally corrupt that state.

3. Hiding that state decouples consuming code from implementation. On Linux, that state is hidden deep inside libc library. You can replace the complete implementation of that state, or even eliminate it if you want so, the consuming code will run fine as long as malloc/free API stays stable. Quite often, code that uses explicit state becomes dependent on the particular implementation of that state. Much less likely to happen when the state is hidden behind some API, OOP or not doesn’t matter.

Post reply on HN