The empirical evidence that types affect productivity and correctness
danluu.com
danluu.com
It's refreshing to see posts like this and http://blog.metaobject.com/2014/06/the-safyness-of-static-ty... pointing out that we don't have strong evidence on this and keeping an open mind. A trend? One can hope.
Other than that, I'd say skip the over dramatized dogma and just pick the tool that suits your problem space best.
Said another way, the experimenters picked a task which some of the languages were designed for. Which sounds rather like the point you're trying to make, too. Did you confuse the quoted abstract with this author's comment?
Unfortunately, most languages are now heavily shaped by the typechecker. That is, not many languages can flip the typechecker on or off with a switch - or have parallel typechecked and not implementations.
That was one golden chance to get people familiar with the language to try both variations.
And the effect of that? Slightly in favor of typechecked (he typed smugly). But that's not really enough. It's not clear there's even a 5% bump in productivity.
I like compile time typechecking. I like static guarantees. But there's just not enough evidence to say typechecking is a must-have. And really, I'm not sure it's possible to construct an environment to test that.
It would actually be interesting to see a study done comparing the two, but the sometimes shaky documentation of the latter might even throw the results.
TypeScript type annotations are optional, and its semantics are by design exactly those of Javascript.
Anything that adds an extra step to the workflow can diminish the benefit of types, so if you were to do a TypeScript vs JavaScript comparison, you'd have to decide whether you wanted the comparison to include the extra time that TypeScript adds into your iteration flow or make a fake build step for vanilla javascript that slows things down. Maybe es6 transpiled to es5 vs TypeScript would be fair.
[0] http://www.mypy-lang.org/ [1] https://mail.python.org/pipermail/python-ideas/2014-August/0...
One question would be "does it compound?" A "5%" advantage (leaving aside how we could even define something that precisely) that compounds every 1000 lines is hard to detect in any reasonable study but could have an astounding effect by the time you've written a 50,000 line application. Even a 1% advantage compounds quickly to significant differences at scale, yet in the small will be virtually impossible to detect as it will be more than swamped by the noise floor.
Part of the problem with these studies is that yes, programmer skill probably does dominate at the smaller end of the scale. I've come to really not like dynamic typing for the sort of work I do, but I still can and do crank out 500-line Perl scripts at times, because if that really is all I need, static vs. dynamic typing aren't the question. It's about how comfortable I am, how comfortable my coworkers are, what kind of library support I need, and a lot of other considerations long before I worry about typing. By contrast, putting together a multi-dozen-thousand line codebase leads me to entirely different considerations in my language choice.
My summary of the summaries is that we still have virtually no hard evidence to go on that has any utility or relevance to real-world software engineering. At best we have some suggestions about how we might teach students how to do their tiny school assignments and a couple of interesting-but-inconclusive case studies on code of real size.
InfraRuby (at http://infraruby.com/live), compatible with Ruby interpreters, is typechecked.
Looking at code on Github is promising. Several people have done that, trying to analyze changes. Of course, you only see the changes that get pushed to the server, so you're only seeing post-test results.
We seem to be converging on a consensus on typing. Within a module, automatic type inference makes life easier and programs less wordy. The newer hard-compiled languages, Go and Rust, have that. Even C++ has that now, with "auto". Program-wide type inference is hard and less helpful. Program-wide inference also means the caller's types drive the callee, which is a mismatch to the concept of libraries. So that hasn't caught on.
Expressing size remains an issue. Is size part of a type? C and C++ struggle with this and lose. Go and Rust make a distinction between arrays and slices, which seems to be working.
Type attributes are still up in the air. Read-only/immutable is common. By value or by ref is sometimes explicit and sometimes implicit. Whether something can be nil is not common, but has been tried. Rust has the "borrow" concept, which is promising but doesn't much mileage on it yet.
There's been real progress in recent years. Until recently, type systems in mainstream languages looked like either C or Pascal. Now they're getting better.
One quick note:
> Other than cherry picking studies to confirm an long-held position, the most common response I’ve heard to these sorts of studies is that the effect isn’t quantifiable by a controlled experiment. However, I’ve yet to hear a specific reason that doesn’t also apply to any other field that empirically measures human behavior.
In practice, I'm not actually aware of any good studies on 'tools productivity' in any other fields. (And it's not for lack of strong opinions -- grab a professional photographer sometime and ask them about Canon vs. Nikon.) I think it really is fundamentally difficult to measure things like this: getting the most out of a tool can take years, and ecosystem factors can outweigh even a large difference in 'inherent quality'.
If we care about using nice languages, it seems like the best thing we can do is try and lower the impact of these external factors. I think the situation here is actually pretty promising -- projects like LLVM take a lot of the heavy lifting out of implementing a performant compiler, and the JVM and CLR are becoming more and more hospitable to diverse language implementations. There will always be a cost to choosing an unpopular language -- but the smaller that cost is, the easier it will be for better technologies to win out in practice.
[0]: https://docs.oracle.com/javase/7/docs/technotes/guides/vm/mu...
If the long list of evidence is too long for you, then it's totally worth clicking the "click here" link to jump to the author's summary at the end. The summary is readable and useful by itself -- and it is what you're looking for if you really just wanted him to summarize the research for you instead of telling you about all the relevant studies, one by one.
But it's available here:
http://page.mi.fu-berlin.de/prechelt/Biblio/tcheck_tse98.pdf
Google has lots of code in C++, Java, Python and Javascript, and their employees all have passed very rigorous assessments before hiring, so language comparisons should be less skewed by individual skill variance.
I would be surprised if they didn't already perform these sorts of analysis internally.
And even though I'm a static-typing proponent, I will concede that developer productivity is likely to correlate a lot more with the state of your existing systems.
Personal testimonials:
Objective-C is an uncouth mishmash of strong, weak, dynamic, static, and duck typing, with different rules applying to different corners of the language. In theory this should be a train wreck. In practice I found it to be one of the most productive languages I've ever worked on - provided I was very principled in how I built my code. Whenever I let myself slip into hack mode, the result was indeed a train wreck.
F# has a mostly-fantastic type system that still manages to fall apart in a couple of key areas: First, its type inference mechanism doesn't have any clue what to do with calls to non-curried ("C#-style") methods, so any code that interacts with the .NET API ends up littered with type annotations or convenience functions whose only purpose is to wrap a .NET API call up in a curried function that the type inferencer can understand. Second, no type classes. This is particularly painful because .NET's original designers didn't have the foresight to create a base abstraction that numeric types can conform to.
That said, for me, it's about flow. (The IDE flamewar gets into the same territory. I just don't like the flow-breaker that is having to use the mouse, when coding.) Writing unit tests can be a flow-breaker. On the other hand, ripping through source code to chase down a NullPointerException (or similar error, like a "List.head []") is annoying at best and extremely disruptive when the error/failure distance is high, as it often can be in dynamic languages. I find, on average, that development is more flowful in statically-typed languages, and even if the development top speed is slower, I think that's made up by the low frequency of flow breakage.
That said, Java's version of "static typing" is abysmal and, in a typical corporate shop, you're never going to get into flow in the first place so it doesn't much matter.
I've written sloppy Haskell...
You don't see sloppy Haskell because no one is being forced to write Haskell at work. They're only using it because they want to.
The way I see it, it's not so much about discipline or type systems, it's more about freedom and choice.