3 ms·
You can also have bugs in statically typed languages. Perhaps not the trivial bug of passing a string instead of a number, but you still can have the (more like
by goto11 4y ago
You can also have bugs in statically typed languages. Perhaps not the trivial bug of passing a string instead of a number, but you still can have the (more likely) issue of passing the wrong number, i.e. a logical error.
Lets say `add(a, b)` contains a bug. Perhaps it doesn't handle negative values or overflow correctly or something else. But it still returns a number, just the wrong number. This kind of bug is much more likely. If this wrong number is stored somewhere you also might get obscure errors down the line and a static type system will not discover it. And this bug will be much more insidious and harder to track down.
So you need unit tests anyway to protect against logical errors. If a unit tests verifies the behavior of a function it will also implicitly verify the types without any extra work.
- int_19h 4y agoThe case you describe is handled by some form of checked types. In Ada, I'd just declare the range and let the compiler handle it. In a more conventional OO language, I can have a wrapper type for that number which enforces all constraints in the constructor. Either way, the point is that things blow up as soon as possible. Broadly speaking, this is the contract-based approach: at every data flow boundary, explicitly describe your contract, so that any violation can be detected immediately instead of propagating and poisoning derived state. Eager type checking is just a subset of that, true. That means that static typing is not enough, not that it's unnecessary. OTOH unit tests cannot fully express contracts, because even with parametrization you can only test so many of the possible inputs.
- goto11 4y agoHow do you define a contract which guarantee that the result of `add(a, b)` is correct? Not just that the result is a number, but that it is the correct number? Of course `add()`is a silly example since this is already a built-in in any language, but consider a function `calculateSalesTax(product)` - how do you define the contract which guarantees the result is the correct number?
- tines 4y agoThere is no way, in any language with any type system or any amount of tests (except maybe in a pure language with tests that cover the entire domain of the function, in which case you're just reproducing the entire function in the tests), to guarantee that calculateSalesTax produces the correct number in all cases. So the problem you describe exists equally for both dynamic and static type systems with tests. Dynamic type systems just rule out fewer possible errors (and fewer possible correct programs as well, to be fair) before the program runs.