Tuesday, May 08, 2007

Static Typing is Communist Bureaucracy

In a conversation that came up at No Fluff, Just Stuff Denver this last weekend, a fundamental realization came to me. We were talking about dynamic languages like Ruby and Groovy, and a lot of the Java developers just couldn't get over the idea of dynamic typing. They feared that utter chaos would reign if we discard typing. First, I asked them about the significance of testing: "Do we all agree that testing is important?" to which they replied "Of course". And, in the course of the expert panel, we had discussed the appropriateness of code coverage, what it tells you, what it cannot tell you, etc. The general consensus was that code coverage is a Good Thing, and that we should all aspire to 100% as much as possible. After all, it's the tests that tell you if your code if correct or not.

Once we had agreed that testing + code coverage is a good thing, I realized: Static typing is Communist Bureaucracy. "To get bread, you must stand in the line over there, but first you must get a blue stamp on your booklet." If you have pervasive testing, static typing == more typing. The static typing is nothing but a requirement to type extraneous code to satisfy a compiler that isn't telling you anything interesting anymore.

I've said it before and I'll say it again: testing is the engineering rigor of software development. Testing destroys the need to static typing. Dynamic typing speeds up development because there is physically less to type. And testing verifies the correctness of your code, not just that it compiles.


News said...

I enjoyed your talk at JavaOne Today and watching your presentation was helping me appreciate that strong typing is overkill.

I think in addition to your notion of testing and coverage, I think the find bugs guys will be talking about annotations to further communicate intent which further adds to the argument that instrumentation and testing surpasses any thing strong typing could provide.

Tetsuo said...

Static typing (well, they say that ruby is a dynamically-strong-typed language) isn't only about catching trivial errors, but also tooling (ctrl+space) and enforcing contracts at build time (instead of relying on human memory, conventions, and textual documentation).

Years ago, I used to do Perl programming, and while I remember it was very fun, I also remember that reading a 200-lines-or-more program code written a week before was just not possible.

Well, the syntax of the language doesn't help much, but the problem is also because I had to keep in my head all functions and variables all the time, because the IDE (aka plain-text editor) didn't help either.

Dan Manges said...

Well stated Neal - I like the analogy.

Chris said...

Good post. The most important sentence that I take away from this is "testing is the engineering rigour of software development". That said, I don't view testing and static typing as being opposed to each other per se. Static typing is merely a test which fails if you try to call a function with an argument of the wrong type. When I use Python, there are times when I'm writing a function and I want to say "please bomb out if someone calls this function with the wrong type". Static typing would be nicest way to achieve that.

Darren Hobbs said...

I value the explorability that static typing gives you. On a codebase of any significant size and in a team environment any single developer will write far less of the code than they read. Being able to navigate your codebase becomes of high importance if you are to avoid duplication creeping in. While there are certainly examples of being able to navigate dynamic code (Smalltalk), the power is limited to pattern matching on strings, and it is very hard to look at a variable in the IDE and ask it 'what other methods can you respond to?'. You have to backtrack to where it was created to figure out what type it is, or use careful naming conventions instead. That seems like a backwards step to me.

Valery V said...

Well, saying that static casting is eval, please, explain how u a going to deal with enterprise application, eg bank systems, which requires many difficult calculations.

Geoffrey Wiseman said...

I'm finding this logic hard to follow.

Testing is good, coverage is good. Static typing is, among other things, a way to have the compiler test your code for type issues.

Since we like testing, this makes static typing good, right?

John said...

Hi Neal. Really enjoyed seeing and meeting you at NFJS Denver. We chatted briefly about the idea that focusing on typing is akin to focusing on the least important 5% of the problem.

I believe the Static-ists are fixated on Safety requirements, and static typing only gets you a tiny bit of the way there. As opposed to pervasive testing, which gets you much much further.

The Staticists are Type wise but Test foolish.

And the IDEs will get there... It's a trickier problem but as Ted Neward pointed out at NFJS, Smalltalk did it decades ago.

Final point, seems like no one has mentioned another big reason that dynamically typed languages are (re)surging: the relentless march of Moore's Law.

Petr Panuška said...

I was not that lucky to see your presentation (as I'm neither at JavaOne nor at NFJS conferences) so I do not know if there are more arguments for dynamic typing than you described in your post; but I do have few arguments against it.

One argument have been already mentioned by tetsuo - typing does help understand the code. Also, all tools, syntax checkers, code completions, etc. help the developer a lot.

I agree throughly with testing and 100% code coverage but detecting a bug during testing can't be beaten by catching the error during compile time.

Static typing is about giving information, about expressing intentions (Charles Simonyi has already described it, see Intentional programming, I'm sure you know it), about stating precisely what one is up to. Static typing brings an order, although it also costs someting - more typing. I believe, this cost is nothing in comparison with the value it brings.

I'm not sure how much experience you have with communism, I have a little and I know - communism is not an order, it is a big lie ;-).

If it were possible to see your presentations recorded anywhere, I would be happy to see it :).

Martin Cron said...

As a previous commenter mentioned, there is more to static typing than just the compiler catching stupid mistakes (though that is nice).

With statically typed code, tools such as ReSharper can understand in a more meaningful way the code that I'm working with.

This, plus code-completion, seriously reduces the amount of typing, but also the safety of the work.

For example, as the tools understand what it means for me to rename this method/property/class, I can safely do it in one place, and let the tools fix everything for me.

George Jempty said...

My biggest gripe with static typing is that it has given rise to the colossal hack -- er "methodology" -- that is AOP. Given the proper dynamically typed language, it should be mind-bogglingly trivial to provide the benefits of AOP with a fraction of a fraction of the effort.

Jeff said...

And testing verifies the correctness of your code, not just that it compiles.

Hmm, have you thought what compilation is?

static typing = proving properties about the program at compile-time.

Dynamic typing = proving properties (via testing) at test-time.

Ok, so currently you can't prove as many things statically as you'd like, but research is moving in the right direction (abstract interpretation, partial evaluation, more sophisticated typing - see Haskell!).

Comments like "static typing == more typing" is just not true. Take a look at C# 3.0 and "var" for example. Type inference is used to get the benefits of static typing without the baggage of extra key presses. Java has similar proposals floating about.

I think the central point that has got lost amongst the soundbites is that testing is important, but I hope we all knew that already!

Unknown said...

As Jeff said, by removing static typing you are displacing bug detection from compile to execution time, which is A Bad Thing. The first are easier to detect, and your IDE helps here.

Mario said...

I totally agree with the spirit of your post except for the connection between static typing and communism. That form of government has been a source of real oppression for millions of people. The comparison trivializes hardships endured by people who would prefer a better life for themselves and their families.

I am sure that was not your intention. I don't know whether you have any family living in a communist country. I do, though, so the matter is a serious one for me, as it is for many like me.

gwenhwyfaer said...

Ignacio said "by removing static typing you are displacing bug detection from compile to execution time, which is A Bad Thing". But if compilation is merely partial evaluation in advance, then there's no useful difference between compile time and execute time except when they happen... which raises the question of why they should be kept separate at all.

That would mean your statement could be rewritten as "by removing static typing you are displacing bug detection from evaluation [time] to evaluation time" - which is clearly meaningless.

So I suggest that the distinction between static and dynamic typing is not only a false dichotomy, but not even a useful distinction; in a sufficiently advanced system, types merely become one form of constraint or assertion, and all constraints can be verified - and errors reported - as soon as there is enough information to do so, whether that's as soon as a line of code is written or at the end of a lazy evaluation chain.

Cedric said...

John: I don't know if you misunderstood Ted Neward or if he really said that, but either way, it is incorrect: Smalltalk never did refactoring the way Java does it because there are certain refactorings that simply cannot be done without knowing the types of the objects you are dealing with.

I can easily show you a code snippet that simply cannot be refactored without human intervention.

And if you must know, Smalltalk's renaming was never more than a global search/replace.


Unknown said...

I think everyone here agrees that testing and code coverage are paramount when authoring software in any language. What I'm surprised about is that no one has called attention to your stated gain from stripping out static typing - "There's less to do". If the time it takes you to key in your a static types is a significant bottleneck in your development process you're one of 2 things: a) a super genius who can conceive, design and code in parallel or b) writing crappy, ill-thought out code on the fly. Hell, why not just use 2 character variable and method names! That'll save you dozens of expensive key strokes!

Now clearly if static typing gave you nothing those extra keystrokes would be worth nothing and, as little time as they take, would make no sense. But it doesn't give you nothing. Among other mentioned here it gets you:

1) compile time checking - More code coverage!
2) more verbose, readable code
3) the ability to use tools to dramatically speed coding - Whoa talk about saving time. How often do you have to look back at a class definition because your dynamically typed language has no idea what a variable is at write time.

Unknown said...

Very few people I work with write unit tests. Sad but true. I guess if everyone was perfect and wrote tests this whole line of reasoning would make more sense to me. I wonder what percentage of developers actually write unit tests? Maybe 2-3 percent?

Stephan Leclercq said...

Actually, static typing is like knowing in advance what kind of documents you need, before going to the administration office. Dynamic typing is like being said, once you are there, sorry, this document is not the one that we require. Even if the road from the post office to your home is short, you would not like that... So don't do it when programming either!

Anonymous said...

The argument that dynamic typing saves key-strokes cannot be dismissed easily. Here's a use-case from C++:

std::<map<std::string, std::string> mymap;
for (std::<map<std::string, std::string>::iterator it = mymap.begin(); it != mymap.end(); ++it)

I'd love to omit the iterator type definition in this case, because it really does take time and concentration away from work. The upcoming C++0x standard will probably allow this with the "auto" keyword using type inference:

for (auto it = mymap.begin(); it != mymap.end(); ++it)

As has been said before, you need type information in the IDE for auto-completion and refactoring. Static type-inference is fine, as this can be done by the IDE or compiler. But as soon as the result of an assigment depends on input data only available at runtime, you're screwed. That's why I think full dynamic typing is not worth the gain in key-strokes compared to type-inference.

seoppc said...

I agree with you totally code is the soul of software development and testing glorifies its accuracy.
Static typing would be a way to achieve that for correct types.