|
Language Design:
Let's start with the admission that there's a lot of cargo culting in language design. Evidence is hard to come by and the best evidence is other languages that succeed with different choices. I remember the flame wars about how multiple inheritance would cause a language to fall apart. When will languages adopt the idea that encapsulation is not sacrosant, as the theoretical issue about the backdooring like _method in python or package level public in Go^ is, someone might abuse it? Howabout make testing a first class concept and lump it in there or just use the shortcuts that have been working. What is inheritance?
Inheritance (for any given language) is a language supported type of class composition (https://youtu.be/eEBOvqMfPoI?t=2874), as a closure. A class is a function and once you understand this, it opens up possibilities in how you design and test. This has nothing to do with performance, which is a nonsequitor. Is Rust less performant than Java because of how it does composition? No. Perhaps there's something in the JVM that makes mixins difficult to optimize for, but that would require some evidence (there's no general branch prediction in the JVM, last I checked) and is, ultimately, at the feet of the JVM implementation. Have a look at Go and Rust. Naturally, because a specific kind of inheritance is a language feature, it gets overused and a language, (like Java) for backward compatibility's sake, overuses it in designing new features. Looking at other languages like Javascript, Lua, Erlang, PHP, Ruby, Rust, etc. saner heads have prevailed and even Java has resorted to using "Aspects" ...which are runtime traits for additional types of composition^^. Regarding the rest of the article...
His arguments for using final include: 1. Someone may forget to use super() and that's bad because what I want to happen trumps what they want to happen. 2. People can't subclass my class across package boundaries, because I don't know why handwaved JPMS (then covered in Should Inheritance Across Package Boundaries Ever be Used?).
His reasoning is not compelling, in the least. I can say, without hesitation, that 'final' is harmful. Adding final to a class is such a violation of the concept of reusable software, I'm surprised the FSF doesn't boycott languages. In C++ there are performance benefits. In Java it's just to put up a roadblock. This was never a good idea and makes testing impossible in some cases (where final classes are injected into final classes). This is purely because of Java's design as a language, not because of some demonstrably helpful concept, implemented poorly^^. ^If you are a language designer, always allow backdooring of accessors for testing, at the very least. This conviction that they must always apply to protect developers from each other is misplaced and has hurt the reliability of software, badly. ^^Spring has a form tacked-on composition, which is both ugly from a conceptual standpoint and problematic from a testing standpoint. Java always seems 20+ years behind. |
You are going to get a lot of false positives using success as a metric for good language design.
I cannot think of a single popular language, other than Python, in the last 40 years that did not have huge companies with sizable marketing budgets behind them.
Programming languages do not succeed based on merit. They may fail based on lack of it.