5 ms·
> Why am I wasting time satisfying the type constraints of Java when my unit tests are already checking everything? Couldn't you invert the question for Java a
by giaour 10y ago
> Why am I wasting time satisfying the type constraints of Java when my unit tests are already checking everything?
Couldn't you invert the question for Java and instead ask, why am I wasting my time chasing 100% test coverage when the type constraints of the language guarantee a certain degree of correctness?
I've always found that dynamic language projects require twice as many tests as a Java project to get a similarly reliable test suite.
- formula1 10y agoI whole heartedly agree with this sentimate
- josephmoniz 10y agoThis reminds me of a talk from StrangeLoop 2012 by Paul Snively and Amanda Laucher "Types vs Tests". Well worth the watch. https://www.infoq.com/presentations/Types-Tests https://www.infoq.com/presentations/Types-Tests
- JoshTriplett 10y agoExactly. Types are a class of tests, checked by the compiler at compile time.
- mpweiher 10y agoRight. They are one class of tests that happens to be checked at compile time. But what about all the other tests that you still have to do? Which typically also coincidentally check the types (if I check that a value is > 2, I am also checking that its type is number (or int or whatever your particular numeric tower or non-tower says). And what is the value of "compile time", if the all this type checking makes the compiler so slow that just compiling is slower than compiling + running unit tests in a simpler language? What if it catches 10% of errors (optimistic estimate) but due to constraints in reusability makes my code 20% bigger (conservative estimate)? Likely around 10% more bugs. Don't get me wrong: I like static typing (to some degree). I just get antsy when it gets oversold.
- m_fayer 10y agoDon't underestimate the productivity boost provided by the little squiggly red line. The fact that your tooling will stop you from ever passing T when the expected parameter is Collection<T>, and that this "rescue" involves pretty much zero cognitive overhead, is invaluable. When I work in a statically typed language, I find that I pretty much never make "head-desk" type errors, and despair at their reappearance when writing... javascript.
- mpweiher 10y agoHmm...much of the disconnect might be that when people think "dynamically typed language", they think JavaScript and Python and Ruby. I also don't make these mistakes while writing Smalltalk.
- mwcampbell 10y agoWhat feature of Smalltalk, but absent in Python/Ruby/JS, prevents these mistakes?
- stevetrewick 10y ago>if I check that a value is > 2, I am also checking that its type is number Surely, you're only testing that it can be coerced to a number?
- JoshTriplett 10y ago> But what about all the other tests that you still have to do? You should do those too. > Which typically also coincidentally check the types (if I check that a value is > 2, I am also checking that its type is number ~$ python -c 'print "foo" > 2' True Now, on the bright side, Python 3 fixes that one: ~$ python3 -c 'print(2 < "foo")' Traceback (most recent call last): File "<string>", line 1, in <module> TypeError: unorderable types: int() < str() But most popular dynamic languages seem to have more where that came from. And if you have a sufficiently robust type system not to, then it starts to look a lot like the type system of a static language, minus the compile-time error detection. > what is the value of "compile time", if the all this type checking makes the compiler so slow that just compiling is slower than compiling + running unit tests in a simpler language? To the best of my knowledge, type checking is hardly the slowest part of most compilers. Many dynamic languages have somewhat faster startup times because they don't have a compiler, or they use a JIT at runtime. In any case, for many non-trivial programs, runtime dominates. A sufficiently thorough unit test suite may take significantly longer than compilation. And even if not, someone has to write the unit tests that handle what static type checking does for free. I'm not going to claim that static typing is universally better; for instance, it's a lot harder to provide a good REPL in a statically typed language. But personally, I like dealing with as many errors as possible up front, rather than discovering them later on.
- mike_hock 10y agoAlso, how does full unit (!) test coverage prevent a situation where unit A passes some type to unit B that unit B doesn't expect but happily runs with, but with different semantics? Documentation of interfaces in dynamic languages usually always specify the types of arguments and return values, and the code very often looks like this: def foo(arg) raise TypeError, "Integer argument expected" unless arg.kind_of?(Integer) # ... end Yup. That saved me a lot of typing (no pun intended) compared to void foo(int arg) { // ... } Reading (and writing) code in dynamic languages (including the tests!) always seems to me to disprove all of their purported benefits and underlines the need for a strong type system.
- spion 10y agoYup, the right tool for the job. Type systems are really good at enforcing inter-unit contracts, while tests (especially property tests) are very good at making sure that the implementation is correct for at least a subset of inputs.