Why static typing matters
This is a short post about an experience I had where the loss of type safety caused a nasty bug.
Look at the following code:
val tenYearsFromNow:Long = System.currentTimeMillis + 10 * 365 * 24 * 60 * 60 * 1000
It has a bug. Can you spot it?
The bug is that 10 * 365 * 24 * 60 * 60 * 1000 is computed as an integer and oveflows. tenYearsFromNow then holds a value that is twenty days from now.
Where I work this caused the server to stop functioning twenty days after being restarted...
The bug was not detected by the compiler because of the Java/C legacy where the compiler automatically promotes integers to long. So the loss of type safety is what caused it to be undetected during compile time.
Furthermore, this bug is not detected by unit tests (you don't wait 20 days...), so this is an example of how unit tests cannot cover the loss of type safety.
Conclusion? Type safety matters.
- ittayd's blog
- Login or register to post comments

Comments
Integer.toLong() works correctly for every possible value of Integer, so this operation is always safe.
On the other hand, Integer * Integer does not work correctly for big numbers, so in the ideal world it should throw an exception of overflow, exactly like divide by zero does.
In this particular case, scala compiler could see that constant is incorrect.
I created a simple program in C:
The compiler was able to spot a problem in it:
So if the scala compiler did not warn, it's worth a bug report to scala-lang.org. Otherwise, it's your fault. Type safety is important, but your example is not a good illustration for this ;-)
Type safety means that I must do things explicitly, or the compiler will issue an error.
Consider the following:
By your logic, since 'Person(someString)' always works correctly, it should be possible to do 'people + "ittay"'. Fortunately, the compiler will issue an error for this expression, and I'd need to explicitly do: 'people + Person("ittay")'.
Now you rhetorics is based on the semantic difference between string and Person. Unlike Long and Integer, which have exactly the same semantics.
And regarding the word "fortunately", it's not a matter of fortune, but a matter of the decision to have a separate keyword "implicit". In C++ you would have this conversion (supposing the list would have '+' operator), as the syntax for implicit conversions is having corresponding constructor.
The root of the problem is ignoring the overflow condition in JAVA during runtime. You try to persuade us that forbidding implicit int->long conversion would force you to add the 'L' to one of the integer consts, but it would not help you if you had
The only error proof solution is to have multiplication throwing an exception on the overflow, all other solutions (like the one you proposing) can work in some cases and not work in others.
Catching the overflow at compile time can only be done for trivial expressions. What happens if you have a method `square`. Catching at runtime is I believe a performance issue.
About your second example, sure it would not help. And there are tons of other errors that cannot be caught at compile time. So what? Compilation can't prevent us from doing mistakes, just help avoid them. If I'm taking 2 longs and multiplying them, I need to watch for the possibility of an overflow. But in the original case, the problem was that an Int was behaving as a Long, and while the expression was a long way from overflowing with longs, it overflowed with an int.
By the way, not everybody that disagrees with you is using rhetorics. Its unfortunate, but some people just think differently than you. Try to respect their views.
It's very fortunate that people think differently from me, in particular you think better than me very often. You brought bad analogy, I spotted it. If what I wrote insulted you, I'm sorry, that was not my intent.
Looks to me that this problem was caused due to the combination of static typing and a developer that relies too much on the compiler. In a static typing system you either say for each element its type, or MUST know exactly what the compiler would do when you don't provide this info. In your example the developer didn't say that the 10 is the long 10, but rather relied on the compiler, which defaulted to the int 10 (same for the rest of the numbers).
For me this is an excellent example why static typing is more overhead then help - type safety is too important to be done by a developer and should be handled by the combination of the language, compiler and the runtime environment.
For scheduling capabilities, it's better to use one of out of the box solutions:
http://java-source.net/open-source/job-schedulers
Writing logic like "ten years from now" and counting milliseconds using epoch based calculations seems like very "low level" and time waisting.
The value is a default value for a deadline (Even using schedulers you need to supply the argument values). It was meant to be "infinite", but not using Long.MAX_VALUE, to avoid overflow. The irony is that overflow is exactly what happened...
And the design could have probably been better (creating a Deadline class with Infinite object extending it) but that's another subject...