Saturday, July 04, 2009

Are dynamic languages evil?

Maybe unit tests for dynamic languages have to do what static language compilers already perform. But there are drawbacks like simple delegation...
The never ending religion war between static and dynamic languages has earned another debate with this post.
First, define what we are talking about: in static languages variables has a fixed type that has to be defined by the programmer when he writes the code. If we are talking about objects, you can only call methods on an object that belong to that particular class or interface. Example of these languages includes C (and its superset C++) and Java.
dynamic languages are the ones commonly used for scripting: Python and Php are the most widely spread in the open source world. In Php, $foo is a variable which type can change at any time. When you make an assignment in Python, the type of the variable matters in the subsequent executed code, but it is not checked at the compile time, primarily because there's no compiling in Php or Python (excluding the .pyc bytecode files and other stuff like Apc, whose compilation serve performance purpose and not proof of correctness).

Different architecture
Unit testing is a more radical proof of correctness of an application: it serves also to provide a specification for components, but the aspect of interest in this post is that the code is run. Static languages performs compile-time checking to catch bugs and errors even before the program loading.
However, static types checking is not enough to provide trust in code, so we have unit tests that loads the classes or procedures in question and feeds them canned data to see if they respond well.
In dynamic languages, we also have unit test (think of PHPUnit), but part of these tests are dedicated to ensure that the class does not explode. If there's a very dumb error, like passing wrong parameters to a method (string instead of array instead of object), this is discovered only when dispatching the real call, at runtime. With a single file in your editor, you can only run some syntax checking (php -l in our example).
This aspect is part of the dynamic languages architecture: the checking cannot be done a because the flow of the program will take a radical different road basing on the state of the script. In Java, a variable in a method is always the instance of the declared type; in Php it can be a string or integer or object depending on another string method value. Even the name of a method call can be a variable.

Dynamic point of view
On the other hand, these limitations on checking are the power of a dynamic language like Php, where for instance you can:
- call $object->$method()
- call $class::$method()
- code a decorator for a twenty methods interface with __call() and two lines of code.
- instance a domain model class basing on a parsed (and validated of course) string. This does not need reflection.
The decorator example is explanatory, because it's a rapid way to implement delegation using the __call() magic method. One __call() definition substitute the need to replicate all the methods signatures of the chosen class. Decorating a typical framework class of Doctrine or Zend Framework would otherwise require 100+ lines of code, making inheritance the choice even where composition would be better, to respect Lsp.
The introspection on the classes and methods provided by a dynamic language is not static checkable, but it's a very handful way to reduce verbosity and repeated code. Choose what is the right language for your job.

No comments: