Hacker News new | ask | show | jobs
by userbinator 4359 days ago
While it's possible to overuse inheritance, I don't think replacing it with composition is all that much better, and in addition all those forwarding methods that do nothing more than call another (could they even be optimised out?) are a great example of code that would need to be written, consuming resources like programmer time, but otherwise serves no true useful purpose to the functionality of the software. The complexity only changes form, so instead of tracing the flow through an inheritance hierarchy you're just doing it through chains of forwarding methods. It's for this same reason I don't believe so much his argument for readability and short classes - breaking everything up does not make things simpler, it makes the complexity spread out over a larger area; while it may be true that it is easier to understand an individual piece, it becomes more difficult to understand the system as a whole. This is especially important when debugging, where "can't see the forest for the trees" is a big hindrance.

I think his example of flexibility is the strongest argument for composition, because in that case the forwarding methods are not a waste - they would need to do (useful) work to determine which of the multiple composited objects they would need to work with.

Being mostly a C programmer who does OO-things, I use inheritance when it's obvious that most of the "methods" will be passthroughs to the "superclass", and composition when there is something more that needs to be done. Also, as I am not constrained by the OO model/conventions of the language, it's more flexible in that I can do things like "inherit" multiple times and even change that at runtime, so there is really no strict separation between composition and inheritance; to me, it's just "which function do I set this to point to."

2 comments

That's a fair point, although long chains of forwarded methods could be indicative of poor design - writing inheritance via composition in much the same way that one may write Lisp via Java. Granted, it's very easy to say that this is a bad idea, but that's part of the art of good OO design. :-)

I ran into this at work recently when refactoring an inheritance hierarchy. My initial instincts led me towards many forwarding calls, but after taking some time to reflect on the problem further, I found that many were no longer needed given the smaller scope of each class.

> The complexity only changes form, so instead of tracing the flow through an inheritance hierarchy you're just doing it through chains of forwarding methods. It's for this same reason I don't believe so much his argument for readability and short classes - breaking everything up does not make things simpler, it makes the complexity spread out over a larger area; while it may be true that it is easier to understand an individual piece, it becomes more difficult to understand the system as a whole.

Preach it! Whilst immense monolithic classes are bad, smashing a system up into a million tiny bits is just as much of a barrier to understanding. It is baffling to me that this is not immediately obvious to everyone.

See also the microservices movement!