avivcarmi.com

Generic-Disposable, to programming in The Tragic Death of Inheritance

Considering most of the lines of code in the world are written in java, C#, C++ etc it's pretty hilarious to claim that OOP and inheritance are dead.

As for go if you want to see what a large go codebase looks like go look at the kubernetes source code one day. Get back to me when you are done recovering from non stop puking.

wave_walnut, to programming in The Tragic Death of Inheritance
@wave_walnut@kbin.social avatar

We have been using OOP for a long time and have evolved our thinking through experience. We need to redefine a new paradigm that retains the good parts of OOP and removes the bad parts.

ZILtoid1991, to programming in The Tragic Death of Inheritance
@ZILtoid1991@kbin.social avatar

These "OOP is bad, here's why" type of articles often can be simplified to the pattern of "here's a terrible example of OOP, and here's a very good functional solution of the same problem".

On small scale, OOP just makes things way more complicated than it should be. On larger scale however, it works quite well, especially if you know where to break the rules.

Something doesn't need inheritance? Don't use it! I even use structs in D, which often speed up things by a lot, especially since they're not ref by default.

One big issue I've seen to come up again and again is the programmer not knowing how to handle functions, that need to be called many times. By conventional OOP wisdom it's done something like this:

class Foo {
    void doTheThing(Param p) {
        //doing the thing
    }
}
[...]
for (int i ; i < timesToDo ; i++) {
    foo.doTheThing(param);
}

However, we can move the iteration into the function of the class, so we will still have the power of class interchangeability:

class Foo {
    void doTheThing(int timesToDo, Param p) {
        for (int i ; i < timesToDo ; i++) {
            //doing the thing
        }
    }
}
[...]
foo.doTheThing(timesToDo, param);

Inheritance can replace complex condition statements. The class Foo in my example could be a basis for a thing, that has its own internal state, which is pretty common in game development. However most people are not being taught game development, but instead things that assumed to make money, which include the hottest new trend. When I was beginning to learn programing in college, I was told that we can say goodbye to .exe files, to say goodbye to installing programs to your PC, because everything is going to be web based, thanks to... Flash??? And Java applets??? Funny, it turned out to be JavaScript to be the winner, and now we have applications on our computers that are just glorified Chromium browsers running what are essentially interactive web pages, which got so widespread there are now coders not only afraid of all pointers, but also type declarations.

In my honest opinion:

  1. OOP is okay. It's not the catch-all solution as it was advertised back in the days, but neither if FP, aspect-oriented programming (was this even adapted?), etc. When structured programming came out and obliterated those awful goto statements, it was revolutionary. However, we might never replicate its impact yet again in our lifetime. Maybe it'll never be replicated ever again. People are already failing to find the next iPhone, which are just nicer looking PDAs.
  2. I've seen some some FP jank too. So far my favorite was a person, who managed to solve the use of atoms, by creating a struct they passed to each function, essentially creating a code that is as FP as it gets.
  3. A lot of attempt at avoiding OOP often end up with an attempt of reinventing it without using the class statement.
  4. Monoparadigmism, as I call it, is harmful. It makes its user to fall into the "when your only tool is a hammer" fallacy, and acting accordingly. It would be nice if we could have a single hammer that fixes everything, but that's not the case. That's why I love D's multi-paradigm solution. You need classes? There's a very friendly class system. You would like the same without being a reference value and the inheritance? You can just use structs. You need to ensure your data isn't changing? Just add const everywhere. And so on, and so on, and so on.
subzerosk,

Yeah. I read a lot less about large FP codebases than about large OOP codebases. Wonder why. /s

Some things just can't be properly seen and evaluated in a tiny made-up example that fits in a blog post.

Plus, you have large teams with devs of different skills. Will they all be able to use the wonderful functional idioms that solve all problems and make everything great? Looks like more devs are able to use OOP, warts and all, to create some workable projects. Even if not supremely elegant.

tetris11, to programming in The Tragic Death of Inheritance

I liked the idea of inheritance when you need to define a single thing and spawn it multiple times, but each class required exceptions, too many overrides to count, and usually I would spawn a thing either once or twice in my code, or 15000 times - neither scenario being optimal to having that many objects floating independently about. Sometimes an assoc. array is all you need.

snaggen, to programming in The Tragic Death of Inheritance
@snaggen@programming.dev avatar

The core problem I see with Inheritance is that the abstractions tend to fall apart and no longer be true. Lets use the Animal example. It is easy, when you have Animal -> Cat and Animal -> Dog. But as soon as we become more specific like Animal -> Mammal -> Cat, Animal -> Fish -> Hammerhead Shark, Animal -> Bird -> Bald eagle, we risk of getting in trouble. Because now for all purposes we assume things about the Fish, Birds and Mammals, like fish is in the sea and mammals are live on land. We know that this is not strictly true, but for everything we need it works. Later we need to handle a dolphin… should that be a fish, or do we need to restructure the whole program. If we treat it like a fish, then we might be even deeper in trouble later if we would need to handle birth. And even if we restructure our program to be correct to handle birth, we might stil forget that some mammals lay eggs like the Platypus, so then things break again if we need to handle that. We tend to see Inheritance as a rigid fact based structure, but the core problem is that it is just a bunch of assumptions we dictate in a very rigid way that is hard to change.

Composition have no problem with specifying the platypus as a mammal that lays eggs and have a beak.

mrsgreenpotato,

What’s a good alternative to inheritance in your Animals example?

snaggen,
@snaggen@programming.dev avatar

If you look at Rust for example, then you specify the Traits instead. So, you could define a trait that defines the properties for birth, another to define if the animal have a beak, and another one to define the number and type of legs. The each animal implement these traits, which then properly can define a duck, cat and a platypus.

mrsgreenpotato,

Thanks for the explanation! I haven’t worked with Rust before, would these traits be an equivalent of C# interfaces?

snaggen,
@snaggen@programming.dev avatar

Traits are similar to an interface, but with some differences. Here is a comparison with Java interfaces stackoverflow.com/a/69485860

ignirtoq, to programming in The Tragic Death of Inheritance

I think inheritance served as a good stepping stone to features like traits in Rust. I spent most of my early career in C and C++, and given just those 2, I would pick C++ for classes alone, even though that's nominally "picking inheritance." Because with C++ classes you can define interfaces and compose those objects better than you can with just functions and structures in C (no callback functions and void pointers, thank you).

So it's about the ergonomics of the language, and I think we as developers are collectively growing and exploring, figuring out what works and what doesn't, and with Rust and Go we're trying out those traits and interfaces we figured out in object oriented languages without dragging along classical inheritance. Given another 5, 10, 20 years, I'm sure we will have figured out what doesn't work in Rust and Go and see new languages dropping those concepts in favor of newer, even more ergonomic ones.

jim, to programming in The Tragic Death of Inheritance
@jim@programming.dev avatar

Most of us have bad memories of over-complex hierarchies we regret seeing, but this is probably due to the dominance of OOP in recent decades.

This sentence here is why inheritance gets a bad reputation, rightly or wrongly. Inheritance sounds intuitive when you’re inheriting Vehicle in your Bicycle class, but it falls apart when dealing with more abstract ideas. Thus, it’s not immediately clear when and why you should use inheritance, and it soon becomes a tangled mess.

Thus, OO programs can easily fall into a trap of organizing code into false hierarchies. And those hierarchies may not make sense from developer to developer who is reading the code.

I’m not a fan of OO programming, but I do think it can occasionally be a useful tool.

  • All
  • Subscribed
  • Moderated
  • Favorites
  • random
  • uselessserver093
  • Food
  • aaaaaaacccccccce
  • test
  • CafeMeta
  • testmag
  • MUD
  • RhythmGameZone
  • RSS
  • dabs
  • KamenRider
  • Ask_kbincafe
  • TheResearchGuardian
  • KbinCafe
  • Socialism
  • oklahoma
  • SuperSentai
  • feritale
  • All magazines