6 ms·
> The biggest thing that contributes to refactorability has nothing to do with type safety. Instead unit test coverage, by a mile, is the thing that makes code
by NickPollard 13y ago
> The biggest thing that contributes to refactorability has nothing to do with type safety. Instead unit test coverage, by a mile, is the thing that makes code easy to refactor
Type Safety is Unit Test Coverage.
Typing is a statically checked test of correctness of your program.
Languages like C give static typing a bad name. Types are not things like 'float', 'int', 'double'. Types are 'degrees', or 'radians'. Types are 'buy', or 'sell', 'price' or 'yield'. Types guarantee that your code executes as you expect, and prevent you from writing incorrect code in the first place.
Is it 100% effective? No. But there's a reason that high level statically typed languages (Scala, Haskell, OCaml) usually work correctly after they compile.
- brandonbloom 13y ago> usually work correctly after they compile I still don't buy in to this trope. Q: What is true of every single bug in production? A: It passed both your type checker and your tests.
- NickPollard 13y agoThat's a tautology. By that reasoning, don't bother writing any tests, because all your bugs in production will get past them anyway! My bugs got past my type-checker, but only 100 of them. You have 1000 because the 900 my type checker caught, your dynamic language didn't. Then you go and write unit tests for them, and spend a day writing code that my compiler generated automatically for me.
- grey-area 13y agoIf you can provide statistics on bugs being an order of magnitude higher in dynamic languages to back up your figures here, it would be a far more convincing argument. I'm sure type safety catches a few bugs and prevent some from being made, but does it catch as many as you think?
- brandonbloom 13y ago> By that reasoning ... My reasoning in no way implies that. I simply said that I'm sick of this argument that "if it compiles, it works!" Nobody who knows what they are talking about actually believes that, especially not people who design and build statically typed languages!
- chimeracoder 13y agoLook at it the other way. In fact, you can do a blind test. Try writing in a strongly, (well[0]) statically-typed language for a while, and count the number of times your code fails to compile due to a type error. Each of those would likely have been a runtime error in a language like Python. Just earlier today, I had to write a short Python script (I normally write Go), and I was bitten by this. I'm used to the compiler telling me up-front when I try to concatenate a string and an integer, or when I misspell a variable name. Yes, there are other ways around this (and proofreading your code before you write it is a good practice, in addition to tests). But static typing can make development much faster[1]. Even if you claim that you would have caught all of those bugs in unit/integration/system tests (which I simply don't believe - no real-world project has test coverage that's that good), it's much better to catch bugs at compile-time, because (unless you're writing C++) your tests take much longer to run than your code does to compile. [0] I qualify this to rule out C, which has weak typing as well as memory management issues to complicate things, and Java, which just has a terrible type system period. [1] In some sense this is all a moot point, because any difference in development speed and/or code correctness between statically-typed and dynamically-typed languages is dwarfed by one's familiarity with the languages in question. The only real way to test this directly would be to use a statically-typed language that allows disabling of all compile-time type checks as a compiler flag or pragma, but few languages do this in a way that'd be straightforward to do a meaningful blind test.
- brandonbloom 13y agoLook at it the other way. In fact, you can do a blind test. Try writing in a strongly, (well[0]) dynamically-typed language for a while, and count the number of times your code fails at the REPL due to a type error. Each of those would likely have been a compile time error in a language like Haskell. Just earlier today, I was writing some C++ (I normally write Clojure) and I was bitten by this. I'm used to evaluating code in the REPL as I work, telling me up front when I try to concatenate a string and an integer, or when I misspell a variable name. Yes, there are other ways around this (and proofreading your code before you write it is a good practice, in addition to tests). But dynamic typing can make development much faster[1]. Even if you claim that you would have caught all of those bugs in a type system (which I simply don't believe - no real-world project has types that are that precise), it's much better to catch bugs at run-time, because (unless you're writing Go) your compiler takes much longer to run than your REPL does to eval. [0]: I qualify this to rule out Python, which has weak typing as well as mutability issues to complicate things, and JavaScript, which just has a terrible REPL period. [1]: In some sense this is all a moot point, because any difference in development speed between statically-typed and dynamically-typed languages is dwarfed by one's familiarity with the languages in question. The only real way to test this would be to use a dynamically-typed language that has an optional type system as an external tool, luckily quite a few languages do this in a way that'd be straightforward to do a blind test (Typed Racket, Typed Clojure, Erlang w/ Dialyzer).
- klibertp 13y ago> Types guarantee that your code executes as you expect, and prevent you from writing incorrect code in the first place. If you write a Rational class and implement it's + method as def +(other: Rational):Rational = new Rational(0) then no amount of static typing will save you. At least without dependent types. Static typing gives you a knowledge about what kind of object you're dealing with without the need to run the code. It's almost completely useless if the "kinds" supported in type system are as broad as 'int', but it does help quite a lot if the type system let's you differentiate between cm and inches. It still won't help you at all if you have a logic error - and this is where unit tests are valuable. Personally I find a mixture of Typed Racket and Racket with contracts and unit tests to be the right thing when it comes to producing as error-free programs as possible. I was also pleasantly surprised with Smalltalk, which has no static typing, but because it runs all the time and every piece of code becomes "live" the moment it's written you can use introspection in place of static typing with very similar benefits. Anyway, static typing is a valuable tool and one way of making software less wrong but it's important to know there are other tools and to use them all when it makes sense.
- mercurial 13y ago> then no amount of static typing will save you. At least without dependent types. Sure. Static typing also doesn't help with misunderstanding requirements, or a faulty test in a recursive function. But strong typing, especially in languages where there is no such thing as a NullPointerException, does eliminate entire class of problems. On the other hand, with dynamic languages, you are often a typo away from a runtime error.