Dynamic languages are an anti-pattern
I'm starting to think that it's much more difficult to write maintainable dynamically-typed code than it is to write maintainable statically-typed code. Many of the bugs I've been fixing lately would have caused type errors in a statically typed language.
13 comments
[ 4.0 ms ] story [ 31.5 ms ] threadIt is easy to say someone doesn't have adequate tests but much harder to make an "adequate" amount of tests in a dynamic language (1).
Given a choice, I would rather have a machine checking for correct usage of types as opposed to human written tests.
(1) Note I said tests and did not mention systems level behavior verification which is in-depended of a statically or dynamically typed languages.
When you are building infrastructure (buisness logic independent), static languages are better, because most things are clearly defined, and change rarely, so overhead is small, and the code is general (few special cases).
When you build the real thing, that includes business logic, dynamic languages are better, because it's much easier to change business logic and add special cases on the fly. And there are always special cases.
That's why big projects written in static languages often have implementations of some dynamic language embedded, and when they don't, they use unholy mess of configuration files and dependency injection to achieve the same goal.
I much prefer intentionaly designed embedded dynamic language to writing implementations of factories and changing xml files.
To see how much dynamic your static code is count all the casts from Object, and all template classes instanced for Object (especially common are List<Object>, Map<String, Object>).
Writing infrastructure code in dynamic languages - I agree - it's harder to get right than with staticaly typed languages, and the benefits aren't obvious.
(The language I'm using is Ruby).
The problem is not that Ruby isn't statically typed. It's that what I think of as type errors in Ruby pass without incident. The most irritating example of this is that if you don't pass enough arguments to a proc object the other parameters get filled in with nil. In my mind this should throw a type error, but in Ruby it doesn't.
Perhaps this is why Rubyists are so keen on testing, because their language is full of implicit behaviours.
Maybe automate checking this? I don't know Ruby much, but there's .arity method on proc that seems to be apropriate for this.
x = ->(a, b) { puts a, b }
x.call #ArgumentError: wrong number of arguments (0 for 2)
x = lambda { |a, b| puts a, b }
x.("just one argument") #ArgumentError: wrong number of arguments (1 for 2)