Hacker News new | ask | show | jobs
by kabdib 3400 days ago
Given the awfulness of so many OOP-based frameworks that I encountered in the 90s, I began to seriously consider that OOP wasn't a better paradigm for most things and that instead it was worse, and simply caused people to rewrite code to the point that it overcame the procrustean bed of inheritance and whatever other tools the language of choice was providing.
2 comments

It is interesting that Go and Rust eschewed OOP inheritance for simple encapsulation. Information hiding, not implementation inheritance, turned out to be the big practical benefit of OOP. Inheritance leads to fragile code because it allows unseen dependencies on private implementation details in far-flung classes and files.

Many C++ game engines also moved away from huge class hierarchies of game objects to property-based game objects that were collections of behavior handlers.

There are many calls for, and proposals to include, some form of inheritance in Rust. Among other things, people have found that Rust is poorly suited to modeling HTML/XML hierarchies, retained mode GUIs, industrial simulations, code specialization, and some forms of video games. Inheritance is a missed feature.

What is clear to me is that Rust does incredibly well without it, but wouldn't be hurt by having it. Most of the egregious sins of OOP are mitigated by having far better abstractions available in Rust. ML-style modules, ADTs with pattern matching, type classes, first class functions, etc. Much like scala, if you give them capable FP, OOP stops being abused and starts being used appropriately.

Aggregations and interfaces cover 99%of what you need. Implementation inheritance and virtual variation points create too tight coupling to be workable for evolving systems.
Maybe 99% of what you need, but more like 70% of what I need. I'm not sure what you mean by aggregations, but I design industrial simulations relatively frequently and I've seen the suggestions for replacing inheritance with composed typeclasses and they are not even close to a true alternative. Rust's current troubles with GUI development would suggest the same pattern there too.
Can you elaborate on that? What's an industrial simulation (compared to a "regular" simulation) and why do you like to solve it with inheritance?
An industrial simulation, in my context, is modeling the stateful flow of things through industrial processes. It typically involves millions of instances of thousands of types. There are typically much fewer very well defined processes, most of which would be trivial to implement with a simple impl trait with default methods. But some require stateful members in order to implement a default behavior, but Rust traits do not have fields/members, just functions.

Rust traits and Scala traits (or abstract classes) are more or less equivalent with this one exception. I was just pointed to a proposal that would allow for this in Rust, but it is not yet implemented [0]. Essentially, you would be able to define type members, and then "link" them to a member of the struct/enum that is being "impl"-ed. While ergonomically not quite the same as scala, it is effectively the same as inheriting an abstract class with a constructor parameter.

[0] https://github.com/rust-lang/rfcs/pull/1546

It's the same story in Java - inheritance used to be the first sledgehammer you reached for whenever you saw a nut, but these days it's barely used. Effective Java, the definitive text on the proper way to write Java, tells you to avoid inheritance [1], and that was published in 2008.

[1] https://books.google.co.uk/books?id=ka2VUBqHiWkC&lpg=PA81&ot...

My personal suspicion is that the problem there wasn't OOP, it was frameworks.
… and dogma. There was a lot of blather about hour Everyone Serious needed this complex structure and a lot of people superstitiously followed it without asking whether e.g. advice from a 2k engineer megaproject in a different industry was applicable to their 3 person in-house app.

The modern counterpart is probably scalability — I see a lot of parallels in all of the Google/Facebook-envy applied to “big data” problems which can fit on an iPad.

I think OOP will always run into the problem that it requires a taxonomical theory about your problem, which never holds up in reality. (This is just another way of saying, inheritance has to be a forest/bundle of disjoint trees. Yes, there's multiple inheritance, but I'm pretty sure acknowledging that is a mortal sin among OO types.) Haskell is slightly better, since typeclasses are less topologically constrained, but I suspect requiring ANY categorical theory about your problem is going to create mischief in the long run.
The problem is people not using abstract taxonomies.

If people keep trying to force code organization around the business jargon, they will keep getting the same awful result. It does not matter if they are writing OOP, Abstract Data Types, FP, or direct bits manipulation with assembly.

But then you end up growing your taxonomy ad-hoc. Also, Python does multiple inheritance sanely, and so does Eiffel.
Python might do nearly as well as any language could do with multiple inheritance, but "sanely" is relative, like finding the sanest way to drive two cars at once.
Multiple inheritance is perfectly sane, what isn't (or at least is less) sane is implicit invocation of methods defined in interfaces (and inheritance from a parent class is, among other things, taking an interface with a default implementation.)

Unfortunately, explicit interfaces were a very late idea (at least in terms of implementation in a major language, not sure if the idea was around earlier) in OOP implementation, and wasn't on v1 of any major language as a core approach, so we've got a bunch of languages where we accept multiple inheritance being messy or we don't have MI at all to avoid it being messy.

But if you had exclusively explicit access to interface (including inherited) methods, MI would be clean.

Yeah, pretty much everyone and his brother had a framework:

- Apple, MacApp

- Microsoft: MFC, and others

- Borland: I forget what they called their stuff

- Anyone remember Taligent? Apple, HP and IBM, all getting together in a money-burning party...

- NeXT / Apple revival: NextStep / OpenStep, etc.

- Any number of minor players, including folks with Honest to Goodness Smalltalk implementations (none of which have survived to this day, I believe)

- Java stuff that I have mercifully forgotten

... they were nearly all crazy, and nothing was portable. So much for the promise of OOP :-)