Mar 29, 2010

Testing is not a Replacement for Static Typing

I feel like I haven't pissed anybody off in a while, so it is time to write another "controversial" post. This time we'll revisit the old dynamic vs. static typing debate, mainly because I was walking around and it popped into my head (this is how many blog posts get written).

This time though, I won't pick on any specific languages. Instead let's take language S which is statically typed and language D which is dynamically typed (ignore the fact that there are actual languages with these names, just pretend those don't exist for a moment). Let's also say that these two languages are identical in all respects except for this single fact - the argument of whether or not this is possible can be saved for another day, so again I ask that you pretend that it is possible. Also assume that they are both strongly typed.

In this situation I would argue that S is a better language than D. Why? Well, because static typing gives you tests for free. The compiler will check to see if all the types match up like they are supposed to, so that you don't end up adding an integer with a network socket or something ridiculous like that. In D the check will also be done, but it will be done when the code is executed instead of at compile-time. This is normally a bad thing, so we write automated testing suites to catch this kind of bug.

All this is obvious so far (or at least it is to me). Why am I talking about it? It's because sometimes when I talk to dynamic-typing enthusiasts they tell me that the compiler-check is overrated and that if you have a good testing suite then you're just as well off. Sometimes they even say that the testing approach is even better, since you should be writing tests anyway.
The problem with this argument is that it ignores the human factor. Writing tests is optional, making the code pass a static-type check is not. Therefore writing tests requires programmers to have discipline. This is not a good thing, because many times the programmers don't have the discipline, or they get lazy, or they have a deadline to meet and the thing that gets scrapped is the test suite. Therefore you can have typing errors sneak in which would have otherwise been caught by the compiler.

So what is the problem with my argument? I'm still assuming that S and D are identical in all respects except for the nature of their typing. This is a bit of an idealized scenario (I blame it on the fact that I'm back in school, where "real world issues" sorta fade into the background and you get a nice clean thought-experiment environment where unexpected things don't happen). In real life, there aren't many languages that are equal in all respects, so we can't really compare two languages on their type systems alone. Instead you would have to have some sort of empirical analysis to measure productivity based on the typing systems of the languages, while accounting for other technical factors like expressiveness, presence of a REPL, available tools, etc. and human factors like ability, team size, etc. (I'll be posting another stats article on omitted variable bias/confounding soon which will address a major issue in statistical analysis).

Anyway I deviated a bit from the main point that I want to get across. Testing is not a replacement for a static type check because it requires programmer discipline/effort/time to implement it, and it is optional. Therefore there will be times when it will not get done where a static type check will always be done (in a statically typed language anyway). So if you want to argue that dynamic language D' is better than static language S', you'll have to argue other features of D' than the typing system (from my anecdotal experience, I believe that it is the expressiveness of the dynamic languages I've used that make them more productive than the statically-typed languages I've used, not the type system - using Scala seems to confirm this, since a lot of my Scala code seems to be about as long as my Ruby/Python code).

9 comments:

roboprog said...

It really depends.

For a small, smart, team doing a startup, or just one-person throw-away work, static typing simply gets in the way.

For the typical corporate "Enterprise" (Beam me up, Scotty....) environment, you are dead on, unfortunately.

What I would really like to see is a language that lets you "slip" the typing when you were in a hurry (perhaps if you asked nicely in a pragma at the top of a file?), but made use of static typing information otherwise to constrain things when given or demanded.

Stephan.Schmidt said...

"For a small, smart, team doing a startup, or just one-person throw-away work, static typing simply gets in the way."

Not sure how it "gets in the way."

Nice post, a little bit like my
"Dynamic typing as safe as static typing is based on wrong assumption"

http://codemonkeyism.com/the-unit-testing-lie-aka-dynamic-language-lie/

Cheers
Stephan

Nick Gerner said...

I've been looking for just such a post :)

By the way, I work at a small, smart, team and we do tons of statically typed stuff. It's great! As you point out, it's like testing for free.

Jonas Lindström said...

F#?

hqdo said...

So are you saying "an application written in a static type language with no test" should have less bugs then "an application written in a dynamic type language with tests" ?

Brian Takita said...

So verifying that your software works is optional?

Brian Takita said...

Sorry, let me answer my own question. Verifying your software works is also optional. Writing correct software is optional. Writing good code (whatever good may be) is also optional. So what's mandatory?

Rob Britton said...

hqdo: Nope, I'm saying static typing with no tests is better than dynamic typing with no tests.

hqdo said...

if that is the case, the title of your post is misleading and should be renamed to something like "Static typing is better then dynamic typing if you don't have tests". Your whole argument seems to revolve around the fact that static typing is better if you don't plan on testing your code.