Study of 49 programmers: static type system had no effect on development time
cs.washington.edu
cs.washington.edu
I once read an article about a technique Intel had developed for improving cooling of processors by changing the shape of the fan. I related this to some of my co-workers. One of them proceeded to tell me that this can't possibly work, backing up his argument with "reasoning" based on off-the-cuff remarks about the way air and physics "must" work. The fact that Intel had actually done this seemed to have no effect on his eagerness to continue the "debate" about this scientific fact.
I have a hard time believing that I get no benefit from using Haskell over Smalltalk, but if a body of science were to appear that cast doubt on that belief, the appropriate thing to do is change the belief, not stand around debating from imagined first principles why all the science is wrong and can't be so. Shut up, design an experiment and go prove it!
Perhaps there's little of this kind of actual science in our computer science because it would mean asking hard questions and accepting difficult truths. "The prisoner falls in love with his chains."
Also, I suspect there are a couple of reasons such studies are uncommon in computer science. For one, CS isn't really a science; programmers and computer scientists are not trained in the scientific method or experimentation (beyond their general education); almost no CS papers I've read have contained empirical studies. If anything, they are closer to math papers than science papers!
Additionally, this sort of study is basically sociology. (Or something similar.) These sorts of fields are considered a little shady by hard scientists, and CS people tend to empathize more with the latter. I think this explains the immediate attack on methodology.
All that said, having more studies done about these questions would be great. I'm just not sure who's the best to do them. Maybe HCI researchers? I can't help thinking that the really intense PL people I know wouldn't be very interested in doing this.
You aren't reading the right papers then. At least in Software Engineering, you can't get into the main conferences (ICSE and FSE) without a pretty significant empirical study.
More to the point, the distinction of what is and isn't computer science has become even more blurry in the research community because research in itself has become more inter-disciplinary. There seems to be little to gain from attempting to "bucket" research into distinct taxonomies.
The only problem is, people have been doing these experiments for 30 years, and do you know what the net effect it's had on the world of programmers: none at all. Saying "no no, this time really listen to this study" seems to be having no effect.
There are a lot of causes for this, not least of all the things you mention (nobody cares about science, people like or dislike based on non-scientific evidence).
But it's also because people know that all these studies are flawed. As much as I hate to be the "nitpicker" who takes apart studies, EVERY SINGLE STUDY on programming doesn't even come close to real-life scenarios. In fact, one of the few studies that people actually believe is the "some programmers are 10x better" study, and that was actually fairly well conducted - many students were given identical tasks, and a fairly large amount of time to do them.
But take a look at the Dynamic vs. Static argument. For years, the Dynamic-fans have been saying "Quicker to program, so it's better", while the Static-fans have been saying "Quicker to program, but harder to maintain, hard to use with large teams". So now we have a study that doesn't even come close to addressing most of the issues that have been argued for years! Of course this isn't going to convince anyone.
Can you by chance point me to this paper? I'd like to add it to my paper collection, since most of the studies I've seen concerning programmer variability use members of the workforce. I'm not aware of the one involving students, but such replication studies are easy to miss.
Thanks!
That is the specific study I am searching for to add to my list of papers. Did you give me this link because you were referring to Humphrey (A Discipline for Software Engineering), or something else? I can track down Humphrey, but it will take me a few days, since it's a physical book.
Perhaps the previous author was thinking of the Prechelt "An Empirical Comparison of .." paper? http://page.mi.fu-berlin.de/prechelt/Biblio/jccpprtTR.pdf . Section 5.7 has "work times" for Java and C/C++ programmers using well-observed times. However, that is not for a "fairly large amount of time."
Laurent Bossavit does a masterful job of researching the origins of this myth (and others) in his new book The Leprechauns of Software Engineering, available on LeanPub [1].
However, I don't want to go down the rabbit hole and argue social vs natural sciences.
I find it dumbfounding that in this day and age, people can still create rather arbitrary social experiments with only 49 people and then think they can draw grandiose conclusions from their "data".
Software development is so complicated that there is always an endless supply of objections to fire at any study at odds with one's beliefs. And that is exactly how all these discussions go. All we're doing is repeating shibboleths.
The most interesting studies would be ones that changed somebody's beliefs. That doesn't happen very often in our field. Does it ever?
In fact, everyone here should flip this around and ask: can you design a practical experiment to compare productivity of dynamic vs. static languages? Will others find it convincing? Probably not. PL advocates are no different than religious missionaries. They have no objective proof of any of their claims. And both will murder the natives if they don't convert.
edit: Fowler's view here http://martinfowler.com/bliki/CannotMeasureProductivity.html
int foo(int *p) {
return *p + 17; //well, probably something more complicated.
}
if p is NULL, this code doesn't work. In a language with a more expressive type system, we would write: foo :: Maybe Int -> Maybe Int
foo p = case p of
Just x -> Just (x + 17)
Nothing -> Nothing
(Note: there are more succinct ways to write this example in Haskell, but I'm trying to illustrate the code.)In this case, we have demonstrably covered every case. That's what an expressive type system gets you: you can completely preclude certain classes of bugs like null pointer dereferences by having a sufficiently expressive type system. It's the same in more relevant PL research: people are attempting to formalize systems so that whole classes of bugs can be removed at compile time. It's not about user case studies or anything like that: those can come later, when features look like they'd be useful to integrate into languages.
It looks like the featured article gives a case study about a pretty bad type system. A sufficiently expressive type system doesn't get in the way--it aids the programmer, not hinders her. Heck, in Haskell and ML, you don't even have write down types--the compiler will infer them for you. (It is Haskell practice to type-annotate toplevel functions anyway).
[0] When I say type system, I mean a static type system. For the purposes of this discussion, dynamically typed programs are statically typed, just with not-very-useful types.
Remember all the research done on typestates? The motivation section of those papers was usually a few paragraphs of total BS. AFAIK, there was no real data nor experiment that demonstrated this was a real problem for professional programmers.
FYI: I like static type systems and used Haskell et. al. But no one has demonstrated that it is better than even Visual Basic!
For example, controlling variables has to be done by constructing artificial systems from the ground up. You can't just pull two commercial products off the shelf and then pretend you're examining the impact of only one of the hundered different things that differs between the two.
Similarly, if we wanted to compare the impact of dynamic vs. static typing, we'd have to make sure that that is the only variable. Which means you basically have to construct a new programming language from the ground up, so that you can easily create new dialects of it that differ in only one very specific characteristic.
I suppose I should have nodded to that. Got me there.
The number of programmers is too small and skills not representative (49 undergrad programmers). The problem (writing a simple scanner / parser) isn't one that will really benefit from a decent type system. All you need need are ints, strings, and arrays and you're good to go.
I agree in the sense that we see so many cases in the other direction - reasoning full of holes being trusted over empirics. The interesting thing is in any given situation, how much trust to give to the different tools that we have to evaluate a claim.
There is an ongoing experiment wrt the usability of programming languages, libraries, frameworks, concepts, ... It's called the market.
I'd like to see them hand a pre-written codebase of say, 10,000 lines to a bunch of students, and ask them to make large changes/new features to the codebase.
Dynamic languages are very good for prototyping or small scale projects.
But they fail to address the context of programming large scale applications with teams distributed across multiple sites.
- Multi-site development at least in 3 countries; - Sometimes up to 100+ developers - CI systems - Source code of several MB of source code - Enterprise like infrastructures for Fortune 500 companies - Different skill sets from the "just out of the university" to the "top developer"
Maybe YouTube beats this, but Google only has Phd guys able to crack out crazy algorithms/data structures in minutes. Not typical in most software houses.
Also, as for large and complex projects done by distributed teams, I don't have to point much further than Django or Plone to prove dynamic typing works well in that context.
Heck, the examples you give aren't even anecdotes. They're just name-dropping. One would have to be pretty familiar with the codebases in question and the history of their development in order to be able to give a clear assessment of what, if any, impact dynamic typing might have had on them.
There was a time I was familiar with both codebases (I have some catching up to do) and that's why I mentioned them. Both projects carry heavy heritage and are experiencing huge pressures to evolve and both are doing very well (from what I hear on the dev lists).
That doesn't imply that they are being successfully maintained because they are written in dynamic languages, or despite being written in dynamic languages. And of course there's also the possibility that static vs. dynamic is a wash and doesn't really have an impact at all. Or that the potential impact of going with static or dynamic is heavily influenced by other factors - does the static language have type inference, does the dynamic language support duck typing, stuff like that.
Long story short, correlation does not, in and of itself, imply causation.
- Big consultancy company working with lots for Fortune 500 company groups;
- At least 3 development sites active at any time;
- Some projects can have 100+ active developers across sites;
- Several MB of written source code, plus many modules generated via specific DSLs or code generation tools
- The typical enterprise architectures
- Lots of crappy developers in some of the teams
The implications of static typing helps keeping the possible damages under control.
Everywhere people talk about 'large' teams maintaining a large codebase in this thread, substitute 'mediocre' teams stuck with a poor bloated codebase that is the vehicle for their ambitions. It's just not worth anybody's time to understand its unique needs in detail, especially since any improvement you make today risks being messed up tomorrow.
My lisp interpreter above allows me to tear out a lisp function and replace it with a C function, while leaving the unit tests untouched.
Most enterprise projects with modules developed in offshore, suffer from crappy developers that barely know one single programming language.
Forcing them to write lots of unit tests as required by dynamic languages development leads to nothing.
The only way to minimize broken systems is to use languages that force them to stay on course.
Absolutely.
And also: static typing benefits is not about "development time" but about maintenance, adding stuff, refactoring etc.
If anything, dynamic typing would be expected to lead to faster development time, which is also why it's used in most prototyping.
Lastly: small sample. Did enough of them use an editor/IDE that could take advantage of a static type system?
Did enough of them use an editor/IDE that could
take advantage of a static type system?
Just because the language is static, that doesn't mean it benefits from an IDE.For instance, Scala has fairly good integration on top of Eclipse and IntelliJ IDEA, however every time I try doing some work in Scala, I end up cursing and screaming, because these Scala IDE plugins are slow, incomplete and unstable and get in my way. And I can't blame their authors, because Scala is a difficult language to deal with.
Another example would be C++, which has been around for a very long time and is one of the most popular programming languages ever. And yet even Visual Studio has problems with its refactoring/IntelliSense support.
And then there are the Smalltalk environments, still around, still kicking ass.
Here's the thing ... there are static languages, and then there are languages designed for usage within an IDE ;-) Java, C# and Smalltalk are like that, while Scala, Haskell and C++ aren't.
static typing would more benefit:
* large groups of programmers
* large codebases
* maintenance (which is usually taking more resources then the initial development of a large code base)
aditionally i've come to believe that not all static typing is created equal. most allow `null` to be returned instead of adhering to the type, then some have exceptions and not many languages type side effects (like IO). i'm basically saying that C/C++/Java/C#'s kind of typing is not Haskell's kind of typing, and that the potential gains from Haskell's type system are much bigger on the long run (while it also comes with a steeper learning curve).
Of course, this study is fairly limited and drawing conclusions from it is probably premature. I would not base any policy decisions on it alone.
But, if static typing does not slow you down, it seems worth using even if benefits to maintainability are slight. And if they're nonexistent, using a statically typed language over a dynamically typed one still doesn't hurt you.
Besides, I think static typing is awesome. And I'm a college student--you can trust me! That should be all the validation you need :).
The paper clearly states that static typing slowed development time down.
Maybe the abstract is lying, but that seems to agree with my original premise. That is, the type system had no effect on development time.
Now, the paper makes no comment either way--all it says is that the type system did not have an effect on development speed. My argument is that not having an effect is actually a point in static typing's favor: the main advantage of dynamic typing is supposed to be faster development, after all.
To quote:
We measured two different points in the development: first, the development time until a minimal scanner has been implemented, and second the quality of the resulting software measured by the number of successful test cases fulfilled by the parser. In none of these measured points the use of a static type system turned out to have a successful impact. In the first case, the use of a statically typed programming language had a significant negative impact, in the latter one, no significant difference could be measured.
Now, judging from their test setup, and also from the very low number of testers, I find it very hard to agree with what it seems to be you're taking away from this article. Static typing has more benefit in large code-bases, with multiple programmers, and for avoiding hard to find bugs related to dynamic typing. This doesn't seem to be well reflected by the setup they had.
Also, don't think you should repeat the same comments throughout the HN articles, you are not replying to individuals, but to general readers.
In the first case, the use of a statically typed programming language had a significant negative impact
Considering the size of the sample, I'd guess the difference is rather large to considered significant. By looking at the numbers quickly, it seems to be around 25%. I'm a bit shocked, in fact, because in my own experience, the difference is much larger, but this experiment controls for language and my experience doesn't.
I suspect you are not understanding my point, or what I said about the meaning of the use of the word "significance" when used in statistics.
edit: Say you flip a loaded coin that is 50.1% likely to be heads. Now you want to test whether this is loaded, and flip the coin a certain number of times and count the outcomes. If the number of times you flip the coin is too low, you won't be able to say the coin is 'significantly loaded'. It might be either way, you don't have enough data. If you flip it enough times, you will be able to say something about it -- i.e. that either it significantly is, or significantly isn't loaded.
However, in vernacular English, you would still say that the difference isn't very significant. Who cares if it is 50% or 50.1%.
5.17 hours (dynamical typing) 7.71 hours (static typing)
And that the difference in statistically significant (p=0.04, Mann-Whitney U-test). Whether 5 vs. 8 hours is significant in the natural language sense, everyone can decide for themselves.
Also, it's worth to notice they controlled for language - they used the same language in two flavors - to isolate the typing system difference. It's not a Lisp vs. C thing.
* The whole api consisted of 14 classes, which makes the conclusion that static typing doesn't help with API discoverability somewhat moot.
* We are not talking about Haskell, Scala or even Java/C++ flavor of static typing. The statically typed language offers no generics, no support for encapsulation, no type inference etc.
* IDE support seems to be absolutely minimal.
A methodical problem is that they seem to skip over the abysmal success rate: Only one(!) guy or gal was able to get 100%, more than halve of them was unable to implement a meaningful parser at all. To be honest, it looks a little bit like the subjects were overwhelmed by the unfamiliar syntax and/or most of them where really inexperienced (the paper says that none of them ever implemented a scanner or parser).
"The introduced study is a relatively large study with 49 subjects and required for each subject approximately 27 hours pure development time. Including the teaching time for each subject, between 43 and 45 hours working time was required per subject."
If I were working on a software project where I expected 30 hours of development work, I'm not sure static vs dynamic typing would matter at all. I'd pick the language that would get the job done in 30 hours.
I'm surprised this was accepted in a peer-reviewed conference. I'd give this study more credence if this involved the same number of subjects working on or inheriting a much larger, longer-lived code base. Though, based on the subtitle of the paper, it sounds like the author could be convinced otherwise.
My feeling about this has always been that dynamically typed languages will save time on initial implementation and small projects, and statically typed languages will win on large projects and things that require more maintenance. They acknowledge this, and didn't find anything to contradict it.
Their own graphs seem to show that effect too. In some areas, dynamically and statically typed languages were equal, while in others dynamically typed languages had lower times. I don't actually see where the conclusion that a "static type system had no effect on development time" came from, it appears that it had an overall (if not very large) negative effect. Just like I would expect for a small (27 hours) project.
I didn't crunch the numbers though, maybe I'm just eyeballing it wrong. (again, I can't seem to copy-paste out of it, and I don't feel like reentering all of them)
I just started diving into Ruby. I'm about a month into it, after having spent over a decade doing Java and other static languages. The productivity boost for new development in Ruby is very real; I converted a 10K LoC java program to < 1K LoC Ruby in about a week, despite not knowing the language well at all. It almost feels like a "runner's high" to be so incredibly productive. But there are several things that I find frustrating about dynamic typing.
In dynamic languages it's very hard to navigate existing code and libraries. In Java, you can click on a variable and instantly navigate to its declaration and class definition. In a well-configured environment (say Intellij + Maven) you can even click on imported libraries and drill right down into their source, even the JRE. It's totally natural to know exactly what a method takes as arguments, and what it returns.
In Ruby it always feels like a mystery. When you ask the IDE to jump into a library, it pops up a dialog of 20 choices and makes you guess which one to open. It feels like the old days of running find/grep over the source tree. And if you somehow manage to guess correctly and find the code you're looking for, you often have to read the comments (if they exist) to figure out what it expects/returns. I'm sure a lot of this is due to my inexperience, but code navigation is really painful in a dynamic environment. I can only imagine how hard it would be in a non-trivial project after a couple of years with a few different devs.
Of course refactoring is way better in a static environment. Even if you throw out the IDE, you can more or less instantly find where a piece of code is used by simply renaming it and recompiling to see what breaks. In Ruby you have to rely on tests for that kind of thing, instead of getting it for free from the compiler.
Don't get me wrong- I'm excited about Ruby, and I think dynamic languages will play a major role in the rest of my career. I just wish that code navigation could be better.
It's important not to conflate the benefits of Ruby here with benefits of dynamic typing.
Haskell is statically typed but can be as concise as Ruby (sometimes more concise, sometimes less).
It's ok at refactoring but it breaks down all the time for me, renaming unrelated variables or missing cases. I don't believe it can handle kwargs for example (no computer in front of me, feel free to prove me wrong)
Or with. With dynamic typing and dynamic name resolution such as in Python, there's no way to know with certainty, even if you run it.
From my personal experience, dynamic typing usually works well with 1-2 developers and continues to be useful until about 4-5 developers (static typing too for that matter). After that, static typing usually wins pretty consistently.
My personal preference is static typing. I find it makes the code more readable and catches a lot of oopses early, at compile time. Otherwise you just end up writing a ton of test cases and hope to catch the same issues at runtime. So you have less protection (you have to catch it with a test), and you just end up spending more time writing tests anyways.
I do understand the benefits of both, I just prefer static typing because of the way I work. Both work and have their places. Like everything else, you need to use the right tool for the right job AND the right people.
I've never seen these consistent wins you talk about, despite my years at some of the largest corporations.
Someone mentioned maintenance, so I will also ask how old the codebases that you're working on are? For dynamic typed languages, as the code grows older (with more bug fixes and add-ons and one-offs) then it gets harder and harder to maintain as 100% error free (let alone debug).
I will also throw in the fact that doing software library version upgrades on dynamically typed systems is a pain in the ass. Some code branches have system level calls changed, and unless you have very good unit test coverages (which may or may not need to be re-written on a library version upgrade) then you may or may not catch the problem during the upgrade. With a statically typed language, a static analysis tool can tell you exactly where and how the library or interface upgrade affects your codebase.
"I will also throw in the fact that doing software library version upgrades on dynamically typed systems is a pain in the ass."
This is very true, but you gain a lot with dynamic languages in other areas. The last company I worked for had about 300 programmers in the office I was in. Roughly half did Java and the other half did Ruby. I was one of the few that moved between both ruby and java projects. I did not see these great benefits of static typing that people always insist exist for large teams at large companies.
The main disadvantage of dynamic typing for me is the lack of verifiable documentation about what data a function needs, and which data comes out of it. This becomes a problem when
a) the data is complex (e.g. dictionary of lists of items with certain properties)
b) I haven't looked at the function for a while.
In those cases, I find statically typed code easier to reason about.
On the other hand, it absolutely maddens me that static type systems force me to spell everything out, even where it's trivial. It slows me down, it bloats the code (especially when you have to create a new class for everything) - which again makes it harder to see the purpose of the code instantly.
That's why I decided to make my own little pragmatic experiment: In cases where complexity is expected (or experienced) - and only there- I use the Clojure pre- and post-conditions to check the shape of selected parameters and/or its return value. It looks like this:
(defn german-holidays
"Returns map of german holidays, in the year of d."
[d]
{:post [(like {(date 1 1 2012) :easter} %)]}
...)
(defn calendar [c start-date end-date]
{:pre [(like {:appointments {} :new (list)} c)]
:post [(like {(today) {:occupations [] :appointments
#{}}} %)]} ...)
You can instantly see how the data is supposed to look like, it will be checked automatically, and it is close to the actual code where you need it (unlike e.g. Unit Tests).I'm not yet sure how this experiment will fare in the future, so any suggestions or warnings are appreciated.
For example, here are some tests from the lisp interpreter I've been working on: http://github.com/akkartik/wart/blob/8a8cf96816/030.test
You're right that tests aren't close to code. But that can be good or bad. Since it's not next to the code it can be more verbose and thorough without adding a constant reading burden. And when I wonder, "why is this line here?" I can comment it out and run the tests to find out.
I think of tests as records of the input space of my program. Most of the time we go to great lengths to make explicit what we do but not quite what aspects of its behavior we truly care about. Where are the dont-cares in this program? If I refactor it am I restricted to a bit-for-bit identical behavior? In practice that's impossible, and without tests we fudge random parts of the state space without rigorously knowing what is important and what isn't.
People complain about C++ compile times but I've heard of big Ruby projects with test suites that take 20+ hours to run.
I'd assume those tests go well beyond type checking.
Absolutely. But I would say that is a different debate. In my case, I don't want to specify the behavior, but only the form, which is the counterpart of a static type, but more flexible (e.g. {} is likened to any structure that behaves like a map - the class doesn't have to be exactly the same).
With my like-function, I don't have to spend too much time specifying what is expected, and I get a lot of bang for the buck.
I want to do just enough so the code stays comprehensible and thus manageable.
(fn parse-int [str] ...) needs no type or unit-test to be understood.
(fn parse-appointment [str] ...) is better understood when it has {:post [(like {:id (UUID.) :name "me" :date (java.util.Date .)} %)]}
And as soon as the function gets really smart, and it's smartness isn't revealed directly by the code, it would be time for either a good comment or a Unit Test (or make the code better so that it does, which is an often forgotten option).
1) a REPL. Just give it a whirl and see what you get.
2) intuitive method names and good abstractions. If I call @user.posts in a Rails app, I can assume I will get an Array-like object that I can treat as an array without any problems. The actual type does not matter 90% of the time.
A REPL is in no-way tied to having a dynamically typed or interpreted programming language. E.g. Haskell's GHCi has an excellent REPL environment where you can, in addition to evaluating code, ask for the type of an expression and do other static analyses.
I agree that a REPL makes a huge (mostly positive) difference on how you write code.
You could also change @user.posts to be @user.contributions, for example, and that would hide the fact that contributions was just an array of Post objects.
In a large system you might have to jump through a lot of hoops to get an accurate result from the REPL. What if the thing you're trying to puzzle out is 20 call levels deep? As a new Ruby dev I struggle with this.
(Off-topic, the werkzeug debugger even lets you debug browser apps by jumping into a REPL anywhere in the stack trace, in the browser, after an exception is thrown. I think it also has a command that bakes you a pie.)
For me, switching from static (java) to dynamic typing (common lisp) has saved me a lot of development time. Or did it? Maybe it was Emacs? Maybe it was functional programming? Maybe it was the REPL? Maybe experience?
Cf. node.js
At the end of the day it's about what YOU can hack it with.
Use that language.
For the benefits of static typing I would rather look into something like Haskell which has a much stronger notion of type and builds many language features around this notion. It's probably harder to design a reasonable study comparing that with for example Smalltalk, though.
The crucial difference is that in python, these faster python idioms are for using C as the control code
The paper's title is casting doubts on the positive impact of statically typed languages as they had a negative impact on development time. (though not quality)
In the experiments the existence of the static type system has neither a positive nor a negative impact on an application's development time (under the conditions of the experiment).
What's the point of dynamic languages if they don't even make the initial implementation faster? They're certainly harder to maintain afterwards.
We measured two different points in the development: first, the development time until a minimal scanner has been implemented, and second the quality of the resulting software measured by the number of successful test cases fulfilled by the parser. In none of these measured points the use of a static type system turned out to have a successful impact. In the first case, the use of a statically typed programming language had a significant negative impact, in the latter one, no significant difference could be measured.
Dynamic code can be very fast, but in lisp, after algorithms, that means actually going and finding all of the calls to elt and replacing them by calls to nth. With a static language the compiler has a much better chance of specializing the code for you.
It seems the only question this experiment could possibly claim to answer is whether or not the additional finger typing required by static languages affects the coding speed of these particular 49 undergrads.
Sometimes you may need to type-dispatch when you want to do smart functions. A typical example is a function that takes a sequence/iterable/generator of strings or a string. Since a string is iterable in python, you have no choice but to check for BaseString.
That programmer quality shows way stronger effects than the measured effect of a typing system would suggest to me that
- the measurement was flawed?
- programmer ability beats language choice by orders of magnitude?
Or do I make a category error here?
You take Smalltalk for example, as it is the original archetype of a language that benefit from blurring the lines of the type system. A language like Haskell on the other hand was design with the intention that the programmer would use the type system to do a lot of heavy lifting.
Of course, no real-world language is "pure" in that sense. We've graft type systems onto Smalltalk's "way of doing things", and the GHC Haskell compiler now allows you to treat type errors as warnings.
So it isn't anything like dynamic typing, or even quite like making type errors warnings--it's just a way to compile partially incorrect code to make changing the code incrementally easier. It's also not designed to be used in production.
It just automates the existing practice of temporarily commenting out offending functions and replacing them with `undefined' to get the whole file to compile.
Explain? Or post a link?
EDIT: found it: http://hackage.haskell.org/trac/ghc/ticket/5624
They take 49 students and train them in the language - 16 hours for the dynamic version, 18 for the static, because of "the additional effort for teaching the static type system". The students have 27 hours to complete two related tasks. All activity was logged, so they could look at the time from a test run failing with type errors to a successful test run.
- Scanner task: overall, students using the dynamically typed language were significantly quicker to complete a scanner that passed the tests - on average, about a third faster. Within that, the time spent debugging type errors doesn't differ between the groups.
- Parser task (builds on the scanner): The implementations are tested after coding has finished, showing no significant difference in success between the languages. In both groups, about half the students didn't manage a meaningful parser at all. In this part, students with dynamic typing spent significantly less time debugging type errors.
Here are a few things to keep in mind, IMO:
- Good/capable/flexible static languages are much much harder to design than dynamic ones. Case in point is Haskell, where hundreds (thousands?) of researches have been working for years to widen the area of expression vs. area of safety. The devised language for this study seems very minimalistic to be useful. Most dynamic languages, on the other hand, pretty much let you do anything even when they have a simplistic design.
- I find that people take longer to become fast/useful in static languages. While you can just throw things together and tweak until it works with a dynamic language, a static one will force you more to know what you're doing. I had a semi-technical colleague who had a much much easier time getting up to speed with Python than with any other static language. Therefore, unless the study involves a long prep time, it will naturally be skewed towards lower devel time in dynamic.
- Static languages start shining as the project size/time-line grows. Key affected areas are refactoring, intra-team communication and incremental improvements on the code. To test for this, it would be interesting to stage a time lapse where developers are asked to modify their previous parsers after, say, a month of total separation.
I think a more interesting study would be to hire 20 highly decorated Python devs and 20 highly decorated Haskell devs and give them a few different computational tasks, overall adding up to a large # of hours. Naturally, the study needs to limit usage of 3-rd party libs and take other normalizing measures. Then we may get a sense for what the state-of-the-art in both fronts have to offer.
- Implement a parser for some protocol/data with testing, etc. - Implement a communication protocol/framework/driver/API - Implement a sophisticated-enough simulation for a real-world question you're trying to address certainly with some calculations inside. - Implement a game AI as defined by some spec - ...
I do like static type systems (like Scala) more than dynamic ones (like Ruby), and always thought it would perhaps people slow down. Good to hear it doesn't.
One would need to look into brown field development, if there is any positive/negative effects (I assume positive ones)
To quote:
We measured two different points in the development: first, the development time until a minimal scanner has been implemented, and second the quality of the resulting software measured by the number of successful test cases fulfilled by the parser. In none of these measured points the use of a static type system turned out to have a successful impact. In the first case, the use of a statically typed programming language had a significant negative impact, in the latter one, no significant difference could be measured.
What would be interesting is to take these same projects, and same team members and add some features a year later and see what that looks like and then take the same project and give it to a new team after 6 months and have them add some minor feature or fix a bug and measure that. Or double the performance of the project and measure what that costs, if it's possible. etc.. It's fun to argue and advocate for what you like though.
If static typing wasn't useful, I don't think anyone would bother with types. At the same time some static type systems are restrictive while coding, so you're seeing more and more type inference in languages.
Go does it by allowing one to declare a variable with an expression " a := 1".
C++ 2011 has it with "auto"
Haskell is pretty darned good at it, and a lot of people don't write the types of their functions, though I think it's good practice to make sure you and the compiler agree on what you've written.
That said there's languages like Clojure which are dynamically typed in a sense, and I believe pay a slight performance penalty because they have to use reflection to behave that way. There's ways to annotate types in Clojure to get around that. This is an interesting case because Lisp is typically a dynamically typed language.
At the same time there's awesome languages and environments like Racket that have statically typed and dynamically typed versions of their scheme dialects.
My feeling is that a ruling on whether types are useful or not is sort of a pointless discussion. It's not even true that "the jury is out". You're just choosing tools with different properties and some make sense for some situations and others for others.
With dynamic typing it's much more difficult to create large, reliable codebases. There's too much implicitness among the interactions of different actors, modules, and programmers.
With static typing it's much more difficult to create any codebase. The exploratory nature of programming means that you will have to constantly change and redefine the static types, signatures and interfaces.
What you want is a language where you can start prototyping dynamically and later on when the APIs stabilize gradually you can then stamp static type checking on top of them for cementation without actually having to rewrite anything, possibly in another language. When you can selectively force a freeze on a certain piece of code or API then you can gradually move from dynamic to "static enough" typing as the part of your development process.
The programmer's expertise is an important one and it is difficult to take in account. Static typing is to check code validity. If the programmers make no mistake, then of course specifying types is an overhead. When it comes to collaborative work, strong typing can save a lot of debugging time, meeting time and documentation writing and reading time.
Another aspect is the resulting code efficiency. Code is programmed once and executed many times. It is much easier for a compiler to generate efficient code when it is given more information to do so by the programmer. This benefit of the typing overhead is not taken in consideration.
As repeatedly said, use the appropriate tool for your application.
Or, y'know, according to any basic understanding of science whatsoever. Jesus.
They're essentially trying to test whether static typing optimises development time, and as with any optimisation, you only see a substantial increase if you're optimising the bottleneck. Static typing won't show any speed benefits if your coders are being slowed down by weird abstractions, poor tooling, or analysis of the problem.
The experiment didn't focus on use of the type system, but nor did it actually test anything close to a real-world scenario. All in all, it seems worthless to me.
The mean development time for dynamically typed languages is about 30% shorter in his first experiment, and it is about 20% shorter in the second experiment.
Statistical significance test determines how likely this difference would be if the difference development time in a large population was 0... It doesn't mean that the true effect actually is 0... it's just addressing whether we can completely rule that out.
A more accurate summary of his results would be "Dynamic type systems allowed 20% to 30% faster development in my experiments, but I had too few participants to reject equality."
Even from a Bayesian perspective, having a small sample that is too small to reach strong conclusions does not shift your posterior towards 0.
Try comparing the time one needs to change the codebase written in ML and the one written in Lisp and come back. It is experimentation and change that is slow in static typing.
It's all about the expressiveness of the language. If you can express more with less code, than it's also easier to change, to experiment.
If you change something in a dynamically typed language you still have to catch all places, where the change has consequences.
Only If you want to experiment with something locally without needing to update the rest of the code base, than dynamic typing has an advantage.
I think it's GHC 7.4, which allows something similar for Haskell, to have the typing checked at runtime, to allow this kind of experimentation.
I think that's the best of both worlds, because for the production code you can still activate the compile time type checking.
It will be in GHC 7.6.1 and the extension is '-XDelayErrors'.
http://hackage.haskell.org/trac/ghc/ticket/5624 http://hackage.haskell.org/trac/ghc/wiki/DeferErrorsToRuntim...
I remember numerous instances where I make a large change in one Haskell module resulting in a few changes in the module's external interface, the compiler systematically warns me of all the 20 other modules that needed changing, and lo-and-behold, if it compiles, it works.
> [Decreased development time means] that the quality must be improved since developers have more time left in their projects.
What kind of nonsense is this? What's this assumption based on? Hearsay? Shorter development time = better quality? What?
> [Increased development time means] decreases the code quality.
Again: what?
Caution: Not an academic research paper, but a real case study from Amazon.
[1] https://sites.google.com/site/steveyegge2/is-weak-typing-str...
The fact that type system had very small cost for initial development of small system should be seen as an invitation to use strong types.
Its the bug fixing time that it affects.. A dynamic language is harder to bug fix than a static one..
Of course, the static typing proponents you find on HN are generally not advocating incredibly limited type systems like java or the one used in this "study". I find it hard to believe that a language with such a limited type system is representative of languages with useful type systems like ocaml or haskell.
Hopefully for the next experiment they have them tackle a longer project, and have the programmers tackle short problems in multiple languages to 'rank' them.
2. They ought to check on maintenance effort and time with different type systems as well.
What I found after using Java, Gosu (basically Java but less stupid), Python and JavaScript fairly significantly is that all of them have their own problems. In that particular set, I'd probably value a static type system a little more than a dynamic one, but it gets eclipsed by other language characteristics (e.g. support for functional programming).
In fact, thanks to being scarred by Java, for the longest time I really liked dynamically typed languages more. However, I later realized that it was the lambdas and the higher-order functions and the clever abstractions and the terseness that I liked more than the dynamic typing.
Once I learned Haskell (and later OCaml), I've been converted to liking static typing quite a bit. The beauty in these two languages is not just that the type system catches more bugs than Java's while being less of a burden, but also that they type system can actually make the code more expressive.
My favorite example of this is the read function from Haskell. It is the opposite of toString--it goes from a String to some value. However, the really awesome thing is that you do not need to explicitly specify what type to parse to--the type inference can figure it out for you! Imagine being able to use "5".fromString() the same way you use 5.toString(). In a dynamically typed language, you would have to somehow specify what to parse to explicitly. So your fromString code would something like Integer.fromString("5"), which is less nice and throws away the toString/fromString symmetry.
I have about the same experience with dynamic (Perl, Scheme, JavaScript, Python) and static (Java, Gosu, Haskell, OCaml) languages and I like good static typing most.
Long story short: use Haskell!
On the rare occasion you really need the kind of anything-goes dynamism of Ruby/Python/JS you can just roll your own dispatch tables.
I don't think it's a big deal.