top | item 45943636

(no title)

OrderlyTiamat | 3 months ago

> It can easily become a pinball of calls around the hierarchy.

This is why hierarchies should have limited depth. I'd argue some amount of "co-recursion" is to be expected: after all the point of the child class is to reuse logic of the parent but to overwrite some logic.

But if the lineage goes too deep, it becomes hard to follow.

> every time you modify a class, you must review the inner implementation of all other classes in the hierarchy, and call paths to ensure your change is safe.

I'd say this is a fact of life for all pieces of code which are reused more than once. This is another reason why low coupling high cohesion is so important: if the parent method does one thing and does it well, when it needs to be changed, it probably needs to be changed for all child classes. If not, then the question arises why they're all using that same piece of code, and if this refactor shouldn't include breaking that apart into separate methods.

This problem also becomes less pressing if the test pyramid is followed properly, because that parent method should be tested in the integration tests too.

discuss

order

ferd|3 months ago

> I'd argue some amount of "co-recursion" is to be expected: after all the point of the child class is to reuse logic of the parent

That's the point: You can reuse code without paying that price of inheritance. You DON'T have to expect co-recursion or shared state just for "code-reuse".

And, I think, is the key point: Behavior inheritance is NOT a good technique for code-reuse... Type-inheritance, however, IS good for abstraction, for defining boundaries, to enable polymorphism.

> I'd say this is a fact of life for all pieces of code which are reused more than once

But you want to minimize that complexity. If you call a pure function, you know it only depends on its arguments... done. If you can a method on a mutable object, you have to read its implementation line-by-line, you have to navigate a web of possibly polymorphic calls which may even modify shared state.

> This is another reason why low coupling high cohesion is so important

exactly. Now, I would phrase it the other way around though: "... low coupling high cohesion is so important..." that's the reason why using inheritance of implementation for code-reuse is often a bad idea.

OrderlyTiamat|3 months ago

Great points, especially on state management.

I actually can't imagine for the life of me why I'm defending OOP implementation hierarchies here- I guess I got so used to them at work, I've changed my strategy from opposing them to "it's okay as long as you use them sparingly". I have found that argument to do a lot better with my colleagues...

marcosdumay|3 months ago

> You can reuse code without paying that price of inheritance.

The same pinball of method calls happens at almost exactly the same way with composition.

You save some idiosyncrasies around the meaning of the object pointer, and that's all.