Remix.run Logo
ferd 7 hours ago

An important point not mentioned by the article is that of "co-recursion" with inheritance (of implementation).

That is: an instance of a subclass calls a method defined on a parent class, which in turn may call a method that's been overridden by the subclass (or even another sub-subclass in the hierarchy) and that one in turn may call another parent method, and so on. It can easily become a pinball of calls around the hierarchy.

Add to that the fact that "objects" have state, and each class in the hierarchy may add more state, and modify state declared on parents. Perfect combinatory explosion of state and control-flow complexity.

I've seen this scenario way too many times in projects, and worse thing is: many developers think it's fine... and are even proud of navigating such a mess. Heck, many popular "frameworks" encourage this.

Basically: 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. That's a horrendous way to write software, against the most basic principles of modularity and low coupling.

kccqzy 7 hours ago | parent | next [-]

This is only the case when the language does not distinguish between methods that can be overridden versus those that cannot. C++ gives you the keyword "virtual" to put in front of each member function that you want to opt into this behavior, and in my experience people tend to give it some thought on which should be virtual. So I rarely have this issue in C++. But in languages like Python where everything is overridable, the issue you mention is very real.

ferd 7 hours ago | parent | next [-]

Good point. In Java and many other languages you can opt out instead... which might make a big difference. Is it more of a "cultural" thing?... again, many frameworks encourage it by design, and so do many courses/tutorials... so those devs would be happy to put "virtual" everywhere in C++

lepicz 4 hours ago | parent [-]

heh, i have seen programmers using virtual everywhere, because they were lazy to use declspec(dll_export) on windows system :)

trallnag 32 minutes ago | parent | prev [-]

While in Python everything is overridable, does this show up in practice outside of (testing) frameworks? I feel like this is way more common in Java. My experience in Python is limited to small micro service like backends and data science apps.

OrderlyTiamat an hour ago | parent | prev | next [-]

> 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.

DeathArrow 2 hours ago | parent | prev | next [-]

I 100% agree. And even though I use C# which is kind of OOP heavy, I use inheritance and encapsulation as least as possible. I try to use o more functional worklflow, with data separated from functions/methods. I keep data in immutable Records and use methods/functions to transform it, trying to isolate side effects and minimize keeping state.

It's a much pleasurable and easier way to work, for me at least.

Trying to follow the flow through gazillion of objects with state changing everywhere is a nightmare and I rather not return to that.

reactordev 6 hours ago | parent | prev [-]

Sounds like someone didn’t follow the SOLID principles