You can push things into the type system only so far before you drop off a cost/benefit ratio cliff, unfortunately. Fundamentally, even in FP languages that expose side effects in the type system, you can still easily make APIs with undocumented semantics and in which users will break as the underlying component evolves. In fact Haskell is quite notorious for an ecosystem that seems to believe Haskell's type system obviates the need for good documentation, an illusion the Java world fortunately never labored under.
I think in recent years there's been an uptick in clever sounding attacks on common PL features like inheritance and exceptions, many of which look suspiciously like motivated reasoning. At the very least the arguments are extremely weak. This article ends by saying:
"Personally, for code reuse and extensibility, I prefer composition and modules."
But these are orthogonal. Languages like Kotlin have built-in support for inheritance, modules and composition. It's not an either/or approach, and there are lots of high quality, highly successful codebases that use inheritance extensively which would be pretty unimaginable without it. I use libraries that use inheritance every day and it's very rarely a problem: only in cases where someone made a bad API with it, and you can get bad APIs that rely on composition or badly modularised APIs too. I don't feel like one problem is more common than another.
I think in recent years there's been an uptick in clever sounding attacks on common PL features like inheritance and exceptions, many of which look suspiciously like motivated reasoning. At the very least the arguments are extremely weak. This article ends by saying:
"Personally, for code reuse and extensibility, I prefer composition and modules."
But these are orthogonal. Languages like Kotlin have built-in support for inheritance, modules and composition. It's not an either/or approach, and there are lots of high quality, highly successful codebases that use inheritance extensively which would be pretty unimaginable without it. I use libraries that use inheritance every day and it's very rarely a problem: only in cases where someone made a bad API with it, and you can get bad APIs that rely on composition or badly modularised APIs too. I don't feel like one problem is more common than another.