this post was submitted on 03 Jul 2023
103 points (96.4% liked)

Programming

17303 readers
83 users here now

Welcome to the main community in programming.dev! Feel free to post anything relating to programming here!

Cross posting is strongly encouraged in the instance. If you feel your post or another person's post makes sense in another community cross post into it.

Hope you enjoy the instance!

Rules

Rules

  • Follow the programming.dev instance rules
  • Keep content related to programming in some way
  • If you're posting long videos try to add in some form of tldr for those who don't want to watch videos

Wormhole

Follow the wormhole through a path of communities [email protected]



founded 1 year ago
MODERATORS
you are viewing a single comment's thread
view the rest of the comments
[–] jim 21 points 1 year ago (3 children)

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.

[–] [email protected] 10 points 1 year ago (1 children)

I think part of the problem isn’t just bad hierarchies, it is that they are so hard to fix.

Bad OOP code gets its fingers everywhere, and tearing out a bad hierarchy can be downright impossible.

[–] jim 1 points 1 year ago

Yeah that's a good point. It's telling that inheritance is by design difficult to change unless you follow very specific rules of good OO design patterns.

I guess it's easy to write bad code in any programming paradkgm but inheritance makes it easy to screw up.

[–] nous 6 points 1 year ago

Lots of people equate OOP with inheritance, and I think that does a disservice to OOP code style in general. The original definitions of OOP had nothing to do with inheritance at all and this relationship was only popularized by a few languages (which others then copied due to aggressive marketing).

IMO the more important parts of OOP that are still useful are encapsulation and message passing which can be done in languages without inheritance.

I would caution against throwing out a paradigm before of one aspect of of that languages added onto it after the fact.

[–] [email protected] 4 points 1 year ago* (last edited 1 year ago)

There are some infamous cases of OOP abuse in the 7 digit LOC embedded system codebase I work in. I have known several developers that created these sorts of overly-engineered inheritance hierarchies seemingly just for their own sake. It's awful, and it's even worse when the original author leaves the company and leaves these sorts of unmaintainable blocs in our applications.

But I think there are definitely places where OOP is not only beneficial but just the correct solution for a part of the application. GUI for instance--all the various widget types and how they plug in to the UI system to handle mouse events and get drawn in the correct Z-order--it's very intuitive. Of course you will find a subclass of a subclass of a subclass of Button every once in a while, and in these cases I do look for opportunities to use composition over inheritance.

By the way - can we talk about the author's weird definition of composition? I've always defined composition as a class with a "has-a" relationship with other classes. But this author still defines it as classes with a "is-a" relationship to other classes, or in this case a single "generation" of inheritance. That seems bizarre to me, especially when they give this example:

In composition, this is a simple task: go to Dog class, add getTreat call in between eating and pooping. Done. 💪

And yet, their example of a Dog class following composition literally inherits from the Animal interface and does not have a point in which Dog can, internally, insert this getTreat() call:

class Dog implements Animal { doStuff() { consumeEnergy() println("woof") rest() } }

Lol... anyway, I like the sentiment of the article but I lean much farther toward just picking the correct tool for the job. Inheritance can still be the right solution in many cases and blaming a paradigm for code readability problems doesn't seem as apt as, say, realizing that even in codebases where every commit has to be reviewed, at the end of the day you still have to ship product and there is never time to keep all code in perfect order, especially in large legacy systems*.

  • note this may not apply to some open source projects or other projects where True Idealism can be/is exercised