How does a paradigm like that survive? I might be a fan of functional, but I'm not even saying go that way- stay procedural! Learn your abstractions over time and only build them when necessary.
How does a paradigm like that survive? I might be a fan of functional, but I'm not even saying go that way- stay procedural! Learn your abstractions over time and only build them when necessary.
suggest how this may be fixed
> and requires a list of caveats so large that it effectively draws down to "only use it in these specific places"?
I don't recognise this, can you explain please
Only allow composition. Allow composition techniques to add state, detect the presence of other composition types, etc.
Also, while one can do composition about as easily as inheritance, it still has its warts in languages like C++. If you want to unit test code, it's recommended to use dependency inversion instead of regular composition - there are other good reasons to do DI as well. But when you start coding the same stuff in non-OO paradigms, you realize that it's just much easier - stuff like DI was popularized to get around the flaws of the OO implementation in those languages. The same goes for most OO design patterns.