Hacker News new | ask | show | jobs
by wyqueshocec 4868 days ago
> Besides, dynamic typing scares the hell out of me

Funny. I feel exactly the opposite. Static typing is false security.

I program in JS. My coworkers in Java. They have so many bugs that make it to prod because they assume that just because it compiles it must therefore be safe.

6 comments

Well, it's not like type checking is a binary attribute of a language - for example, Haskell/ML have 'stronger' type systems than Java/C++.

In the former languages, you can encode many more attributes of a program into the type system, and so you can have check at compile-time many more invariants of your program - e.g. enforcing a function does no I/O, enforcing that all possibilities are handled when pattern matching, enforcing the equivalent of nullptr checking, etc.

In languages like C++, there are techniques you can apply to allow the type system to help you out a bit (see this talk by Jordan DeLong for some examples [1]), but in general, the guarantees you get from a non-HM type system are weaker than those from one, and so the notion of successfully passing type-checking is correspondingly weaker.

[1]: http://vimeo.com/55674014

Yeah, Java is not a fair example. It has a type system with the worst compromise between being awkward (and infamously verbose) and not very effective: it gets the short end of the stick on both accounts. It's better than C, granted, but that's saying nothing. It does not compare to a good type system like Scala's or especially Haskell's.

Good type systems can catch far more bugs than you imagine. Moreover, they can actually make writing code easier: there are some extremely valuable and expressive features like typeclasses that simply cannot be reproduced in a dynamically typed language.

You are totally missing the point of the parent. Just because types work out doesn't mean the behavior of the program is correct.

The problem is not how to make something compile, regardless of how complex the types are. The problem is how to do the right thing. It is not enough to return a string - you must return the correct string, and that is not normally not something a type can solve for you. I suppose you may solve that problem too in haskell, but then you will get bugs in the type definition instead. TANSTAAFL.

"It is not enough to return a string - you must return the correct string, and that is not normally not something a type can solve for you."

It can, however, ensure that you have returned a legally-formatted email address instead of someone's first name, with proper use of the type system. You'd probably be surprised what you can do with a real type system, based on what you're saying here. It is not a proof of correctness, but there's a great deal more possible than in Java.

It of course can not ensure you returned the correct email address, but often that's a much less pressing problem, because the thing returning the address may very well have had only one address in hand to chose from, in which case it can't be wrong. There's a lot of logic like that you can deploy in Haskell, when scopes and inputs to functions are much more carefully controlled than a traditional language.

Nowhere in his post did tikhonj suggest that compilation == correctness, even in Haskell. Of course it isn't. The only people making that assumption are wyqueshocec's coworkers, and naturally they're getting burned as a result.

The key point is that a sufficiently expressive type system gets you far closer to correctness on the basis of type checking alone than does a weaker static system like Java's or a dynamic one like JS's. You should still write tests, you just won't have to write as many in order to reach the same degree of confidence in your code.

Not all static type systems are created equal. The sort of type checking provided by Java (and similar languages) provides far less safety than that of a full-fledged type-inferring language like Scala or Haskell.

I use Ruby and JavaScript professionally. I do like Ruby for a number of reasons, and JavaScript I can at least live with. But in both languages, I constantly find myself spending tons of time tracking down bugs that would have been discovered right away if I had Haskell's type system at my disposal.

I prefer static typing because those assurances reduce the number of things I have to manage--they mean I must keep less state in my head. I do not assume that it guarantees things that it does not.

Attributing your coworkers' "if it builds, it works" assumptions to static typing strikes me as incorrect. Static typing, at least in Java, ensures only a (relatively) small set of conditions are true; I don't think you can really blame that for increased/additional assumptions on the part of sub-par programmers.

Either way, you end up keeping lots of things in your head. With dynamic langs, you do have to think about types and use them conservatively. With languages like Java -- the same. No toolset is going to work well unless the dev is on top of things and good at using the tool well.

I've found that debugging in a dynamic environment is great for managing types in a well architected system. It falls down in a poorly architected one, in ways that static typing would not ave allowed. However, in such systems, "it compiles so it must be correct," programmers just get stuck in deeper snow.

This is true, but I personally find that the tools available in decent statically/strongly-typed languages--C#, Scala--can do a fair amount in encouraging the Right Thing in ways that dynamically typed languages (especially dynamically weakly typed languages) can't.

I'm even becoming more and more fond of C++ because of the constraints that you can work in with proper use of templates; my only beef there is that the error messages when you do the Wrong Thing are often not conducive to understanding what the Right Thing is.

I must admit that JS scares me more than anything else. Would love to hear about defenses you employ in JS.
Are there no tests beyond simple compilation?