Compiling is not a very Useful Test
When those that like statically typed languages (like C++, Java or C#) and those who prefer dynamically typed languages (like Python, PHP or Ruby) meet, two very different worlds collide. But let's for a second stop enjoying the fight and laughing at the bloody noses and look at one of the “arguments” that is being thrown around.
(Just think on someone “enterprisy” saying the following:)
“Dynamic languages2) are OK for prototyping but when you want to write big software they don't work cause you never know what kind of object you have. Statically typed languages are better because the compiler checks that for you.”
Now this argument looks like it makes a lot of sense: The compiler enforces that kind of correctness. If your Java method only accepts instances of the class
Klass and you try passing it an instance of
NotKlass the compiler will puke all over your terminal. Bad coder, go back and fix your code! Problem solved…
But what does this test actually tell us? It tells us just that we have only put the right types into functions, that we implemented all the weird interfaces and whatever else the language requires (raising only predefined exceptions for example). There is no doubt that that is a test but I dispute the actual usefulness of it.
What do we actually care about in code? Correctness, we want our code to do exactly what we intended it to do without side-effects that might break stuff (cause in general, breaking stuff is bad™). Having the kind of correctness a statically typed compiler can find only brings us a few baby-steps closer to what we want: Yes, it can check that the code is syntactically correct and that the types somehow fit. It says absolutely nothing about whether the code does what we want it to do.
If we want to check whether our code works most people will probably answer this with the same two words: Unit. Tests. You define tests that actually test the behavior of the code, if your tests run through, your code will do exactly what you want it to do (assuming that your test code does actually test what you need tested). This is true for both camps: The Java or C# crowd loves unit tests just as much as the Ruby or Python people. Why? Because unit tests check what we actually care about: That our code does what we want it to do.
When I look back at when I had to learn Java at university, I can still remember how it worked: Write code, run javac, fix the compiler errors somehow, javac, try fixing it again. Rinse and repeat. We didn't use unit tests, we just tried getting something to work. The compiler was helpful in pointing out that Java needed a “;” at the end of each line, but it never helped with logic problems. Later I had to grade some student's Java code and I got stuff that might have compiled but that was utter nonsense in any meaning of the word.
Now this is not about saying that dynamic typing is superior. Dynamic and static typing are two different paradigms that appeal to different kinds of people, they match different ways of thinking: When we try to write code, we build a model of the things we are implementing. In a statically typed language you have all kinds of rules that try to coerce you into writing something that “makes sense”. The rules limit what you can do but they are intended to help you avoid doing something stupid.
For many people it doesn't work like that. I personally can't work effectively in statically typed languages because I need some freedom to have my ideas and creativity (wow, big words there ;)) unfold. The rules and limitations don't help me get stuff done, they hinder me. Others don't like the kind of freedom dynamic languages give, they feel that stricter rules allow them to model more clearly and give them a feeling of safety. Both views are completely valid but what I want you to get out of this post is that the kind of test the compiler does for you isn't really a useful one from a semantic perspective.
If you prefer the strictness of static typing, use it but don't complain when even simple tasks become an annoying chore. If you need the freedom of dynamic typing, use it but don't complain when you shot your own foot. Twice. But don't let people tell you that only static typing gives you enough “structure” or “safety” to do big jobs - statements like that are full of shit.
Whatever type of language you write your code in, you have to write automated tests. No software will create them for you magically, no compiler, no library, no magic box. You have to specify the requirements and model them in a machine readable way (and that is all that writing tests is!).
The language wars are over, use what you like best. And write unit tests.
The text of this post is released under the Creative Commons Attribution-Share Alike License.