(iterate think (think))

No Free Lunch

26 Jan, 2014

On paper static typing sounds strictly superior to dynamic typing. The compiler can track the data flow throughout our code and tell us when we're using the data incorrectly. This clearly eliminates a whole class of errors that are otherwise possible. What's more, types allow us to encode the business logic of our application allowing us to write code that's provably correct.

All this is unarguably correct, however these benefits do not come for free. One major problem is that static typing requires us to declare all the relationships globally. When you have global relationships a change at any level requires global refactoring at every level.

In my opinion, this makes static typing poorly suited for situations where your requirements are incomplete or subject to change, and in reality there are very few scenarios where your requirements are set in stone.

In most cases, we only care about a local contract between any two functions. What we want to know is that the function being called produces the type expected by the caller. A modification of a local contract should not cause global change in our code base.

Another cost of static typing is that it forces us to handle cases that are not part of the application workflow. For example, our code might have an undefined behavior, but the interface does not allow the user to access this state. This is a case of a tree falling in the woods when no one's around.

Regardless of the type system that you use, you will need to do functional testing in order to ensure that the business logic does what's intended. At the end of the day, the goal of the application is to handle the intended use cases as opposed to providing a proof of correctness.

When I look at the GitHub issues for my own projects such as Selemer or markdown-clj, vast majority of them stem from lack of specification. Practically none of these issues would have been caught by the type system. Had I used a statically typed language to write these projects, I would've simply had to jump through more hoops to end up with the same result.

In my opinion the value added by a static type system has to be weighed against the complexity of the problem and the cost of errors. Since it's obviously useful in some cases and provides dubious value in others, an optional type system might provide the right balance. Static typing is a tool and it should be up to the developer to decide how and when to apply it.

With an optional static checker we can add types where it makes sense and leave the rest of the code dynamic. This is precisely the situation CircleCI found themselves in.



tags clojure

comments


26 Jan, 2014 - Sgeo

Static typing can, in my opinion, encourage a culture that is less likely to make mistakes, less likely to have functions that behave a certain way 99% of the time but a different way in some edge cases. Dynamic typed languages can have such a culture too, but I'm guessing that it's less likely.

26 Jan, 2014 - Sgeo

In particular, I'm thinking of Clojure's trampoline, wherein to continue the trampoline, a function merely returns another function... but what happens when you want to exit the trampoline and return a function from the trampoline? What happens when you can return arbitrary values, and forget about dealing with the edge case of returning functions?

26 Jan, 2014 - Yogthos

@Sgeo

In my experience, this is a particularly rare problem in Clojure since most development is done interactively and you're always running your code as you go. If I'm writing a trampoline function I will test that it works for expected inputs before moving on.

In general, I would argue that difficult to reason about code is simply bad code that should be refactored to be readable. Having static typing doesn't automatically make code easy to reason about. You can have completely impenetrable code that the type checker will happily sign off on as being self consistent.

However, my whole point is that static typing is a useful tool, but it should be up to you to decide how it's used. This is precisely why I like core.typed as it allows having type checking where it's needed.

27 Jan, 2014 - Jeff

I've recently been throwing around the idea that it's not really about static vs dynamic typing. Rather is the language strongly typed?

Will the compiler make coerce an object into another type that is not immediately obvious when reading code? Will the language allow outside modification to types that may not be known to the executing code?

When I look at the languages I prefer, they are all strongly typed. And the one's I'd prefer to stay away from are not. I do agree that some types of problems are more suited to either statically or dynamically typed solutions.

27 Jan, 2014 - Fabrice Le Fessant

It's not about dynamic vs static typing, it's about your general mind: if you prefer to code faster at the beginning, and slower later (your coding speed is going to slow down dramatically with the size of your application), dynamic typing is good for you; if you can spend some time now learning static typing (OCaml is good !) before coding, you will lose some time at the beginning, but code much faster later (your coding speed will be almost constant during the application lifetime).

<br/> Today, in my experience, my coding speed in OCaml is probably higher than it would be in any dynamic typing language, the only things that can slow me down is sometimes the lack of a library that would be available for a language with a bigger community (and thanks to OPAM, this problems is gradually going away !).

27 Jan, 2014 - Yogthos

@Fabrice

I find that organizing your code to be modular avoids the problem of the slowing down when the application grows. Also, many code bases never grow to the size where this becomes a problem in the first place.

28 Jan, 2014 - Pseudonym

I far, far prefer strongly statically typed languages, and I'm the first to admit that the difference is entirely one of what you prefer. It doesn't take less time to develop robust code in a statically typed language than in a dynamically typed language. It doesn't take less effort. A good language is a good language.

However, the "what you prefer" is very important. That time that you spend supposedly satisfying the whims of the type checker is time that you would also spend if the program was written in a dynamically typed language. The difference is that in the former case it falls under the line item of "programming" and in the latter case it falls under the line item of "testing and debugging".

Strong static type systems are good for me because I prefer programming to debugging, and the type system lets me pretend that I'm programming instead of debugging.

Your mileage may vary.

15 Feb, 2014 - alexyz

Hm... I'm on the fence right now. I'm a Ruby developer, primarily Ruby on Rails, with some C# background.

Coding in Scala (which has much cleaner language design than C#) for the last 3 months I clearly see what static typing gives me. Tooling is awesome. I can change anything I want in the project and compiler notifies me if I have broken something. But when I write new code compiler forces me to cover all edge cases even if I don't have any idea of what should be done in that cases (it's a startup and we don't have business analysts to bother :) ). In such situations I have two options: 1) make some stub to keep compiler happy or 2) leave it ??? (unimplemented). Both approaches make application misbehave at some point in the future, when one of the edge-cases arises.

The next problem I found is that type system introduces additional surface for bad libraries, tools and frameworks design. There are so many ways to screw it up... Type annotations kill expressiveness of the language and force framework designers to introduce external DSL, like Play's conf/routes, *.config files, or SBT's build.sbt, which having their own syntax add significant cognitive overhead. Scala's Implicits address this problem, but undermine ones ability to reason about the code. Take a look at what magic Yesod framework does with Template Haskell to get concise type-safe routing configuration and model definitions.

"I’m not against types, but I don’t know of any type systems that aren’t a complete pain, so I still like dynamic typing." - Alan Kay

16 Feb, 2014 - Yogthos

My main point is that I think static typing is helpful in some situations. I'm arguing that gradual typing hits the sweet spot between having flexibility and safety. The developer should be able to decide where adding static types would provide the most value in their project.

20 Feb, 2014 - anonymous

Thanks Yogthos for your free instant pdf api on mashape.

22 Feb, 2014 - Yogthos

glad it's useful :)




help

*italics*italics
**bold**bold
~~foo~~strikethrough
[link](http://http://example.net/)link
super^scriptsuperscript
>quoted text
4 spaces indented code4 spaces indented code

preview

submit