15 ms·
I changed my mine on this. I did OOP since the mid-1990s when I learned it in high school up until about 10 years ago. I find OOP works best when you have a s
by bhouston 2y ago
I changed my mine on this. I did OOP since the mid-1990s when I learned it in high school up until about 10 years ago. I find OOP works best when you have a single coder who can store the model of the system in this mind and work out how to design the base and abstract classes well. And they also have freedom to refactor THE WHOLE CODEBASE when they get it wrong (probably multiple times.) Then you can make these webs of elegant ontologies work.
But in real life, when there is a team, you run into the fragile base class [1] constantly and changing that base class causes horrible issues across your code base.
I have found that OOP with inheritance is actually a form of tight coupling and that it is best to not use class hierarchies.
I agree with encapsulation and modularity and well defined interfaces (typed function signatures are amazing.) I just completely disagree with inheritance in all forms.
There are no benefits to it (besides feeling smart because you've made an elegant but ultimately brittle ontology of objects and methods), just a ton of downsides.
[1] https://en.wikipedia.org/wiki/Fragile_base_class#:~:text=The%20fragile%20base%20class%20problem,the%20derived%20classes%20to%20malfunction https://en.wikipedia.org/wiki/Fragile_base_class#:~:text=The....
- piva00 2y agoSimilar thinking, I've been through much pain from a class hierarchy degrading into an unusable mess, also done a lot of rework refactoring those and it doesn't pay off. Instead of inheritance I much rather prefer the composition approach, not extending classes but defining interfaces for the API, using other classes in the composition of an object rather than relying on overrides/implementations from a base class. It's much clearer to reason about (no more 3-4 layers of indirection), easier to refactor as well.
- 000ooo000 2y ago>I have found that OOP with inheritance is actually a form of tight coupling and that it is best to not use class hierarchies [..] I just completely disagree with inheritance in all forms This is pretty common advice (at least IME), usually distilled into the form "prefer composition to inheritance".
- bhouston 2y ago> This is pretty common advice (at least IME), usually distilled into the form "prefer composition to inheritance". I think this is why in the current JavaScript era, it is rare to find a popular library that makes significant use of inheritance (as opposed to just supporting interfaces) even though it is supported in the language. ThreeJS is one of those exceptions, but they are few and far between.
- arresin 2y agoExactly my thoughts. When I started really getting functional programming it was a breath of fresh air. For me the test is not just how fast someone else can pick up the codebase but how fast I can remember how it all works in n years.
- ninetyninenine 2y ago> I have found that OOP with inheritance is actually a form of tight coupling and that it is best to not use class hierarchies. Tight coupling is the basis of oop. A method is tied to an instance. Methods cannot be composed with other methods or functions without instantiating state. Methods cannot be moved into other scope. The literal definition of an object is a tightly bound set of methods that cannot ever be used without instantiating state.
- the_af 2y agoI don't think a method being tied to an instance is the best case for calling it "tight coupling". OOP can be used to design relatively uncoupled systems. One of the lessons learned in all these decades is what the grandparent post alludes to, which is distilled into "prefer composition over inheritance". Implementation inheritance (as opposed to interface inheritance) indeed introduces coupling and is therefore discouraged in current advice.
- gorjusborg 2y ago> OOP can be used to design relatively uncoupled systems. Never go full-Object-oriented programming. In this case I think it is valuable to make a distinction between OOP which is a style of programming, and object-oriented languages, which are just a language designed with that style in mind. I have seen issues in codebases where developers have used OOP as style to aspire to, using it in an academic sense. They tend to try to use inheritance frequently, have deep inheritance trees, and suffer from hidden coupling through these. On the other hand, those who use object oriented languages in a mostly functional style (side-effect free functions, effective immutability, and almost no use of inheritance) tend to be much healthier in the long term. So it's fine to use OO languages, but never go full OO programming.
- the_af 2y ago> Never go full-Object-oriented programming. Agreed, but that wasn't what I was saying or replying to, was it? I was arguing that method implementation tied to an instance isn't the type of thing people mean when they refer to tight coupling. Coupling is related to breakage/maintenance; when you touch this thing here, if it's tightly coupled with some other component, it will also require (sometimes unexpected) changes in that other component. Whether one should or shouldn't go full OO is an orthogonal consideration.
- moffkalast 2y agoMy thoughts as well. Inheritance forces you into spaghettification sooner or later if you didn't consider everything you'll ever need from the start to the end of the universe. Even if you're working on it by yourself the refactors become frequent and take too much time for little gain. Self contained encapsulated parts with an eventbus for entirely decoupled data propagation are much easier to manage and edit. Just duplicate a bit more than you think would be best to reuse, disk space is cheap and if you get that part wrong you're screwed and will need another rewrite. And it's probably more performant too with newer hardware since you can usually just spin out any self contained part as its own thread if need be, often with almost zero changes.
- bluGill 2y ago>I have found that OOP with inheritance is actually a form of tight coupling You are not the only one. Prefer composition to inheritance is a saying for a reason. Inheritance is powerful and useful for small problems, but as you say it introduces tight coupling and so should only be used where that is intended. Tight coupling isn't always bad, but it is bad often enough to avoid it.
- ajuc 2y ago> I find OOP works best when you have a single coder who can store the model of the system in this mind and work how out to design the base and abstract classes well. When all the states of the program and all the transitions between them fit into one programmer's head - every programming paradigm works well.
- bhouston 2y agoGood observation. That makes my statement is an even worse condemnation of OOP that I thought.
- ravenstine 2y agoI totally agree that class hierarchies are mostly a trap, especially when there's more than one developer on a project. What I don't understand is why many programmers still use classes even when they plan on avoiding inheritance. I've seen this sort of thing on the past few major projects I've been involved with; initial creators heavily relied on inheritance, future developers realize that was a mistake, then said future developers continue using the class construct of whatever given language. At that point, why not just use functions and regular objects? Without inheritance, classes tend to have these other rules and complications that don't seem to really add anything when there is no hierarchy.
- bhouston 2y ago> At that point, why not just use functions and regular objects? Without inheritance, classes tend to have these other rules and complications that don't seem to really add anything when there is no hierarchy. I have done this myself. In TypeScript I would write a class that supports an interface. There is no hierarchy, but writing as a class gives it structure, a clear name, you know how to instantiate it, what it supports, private methods, private state, static functions, etc. So I find that classes still do great encapsulation for mutable objects.
- AnimalMuppet 2y agoOO was created for a reason. Before OO, you had these data structures, and they got passed around between functions. Well-designed data structures were not just a random collection of items - they had a relationship between the elements. And you kept finding structures that were in an invalid state - the relationship among the elements had been broken. Well, who did that? You couldn't tell. It could have been any function anywhere in the code that took the structure. With OO, you could have a very small set of functions that could change the structure. If the constraints got broken, you had a very small footprint to look at to see how it could have happened. That was the OO advantage. And this advantage did not go away with multiple programmers. In fact, it increased. If you had a class that you "owned", some other new (or incompetent) programmer could not break your code without changing that class's code. You didn't have to rely on everyone else always doing the right thing with your structure. Note that this advantage is orthogonal to inheritance vs. non-inheritance.
- globular-toast 2y agoA useful rule is not to extend a class you don't own. This is usually taken to mean don't extend a class from a third party library. But it should also mean classes that are shared by multiple developers. In that case, compose, don't inherit.
- DeathArrow 2y ago> But in real life, when there is a team, you run into the fragile base class [1] constantly and changing that base class causes horrible issues across your code base. And then you start writing unit tests for everything and wait 10 hours for building and deployment, which is a good thing because your employer will need more people to do the work. Or you can't fix a bug without creating other 10 new bugs, which is a good thing because your employer will need you to solve that 10 new bugs. OOP keeps people employed. :)