de.velopmind | The Det about Programming

June 5, 2008

Types: Static, dynamic and the quirks of velocity

Filed under: Experiences, Java, Language, Other-lang — de.velopmind @ 11:24 am

Until shortly I was someone who felt often annoyed by the verbosity of Java and the restrictions of the type system, which much too often seemed to stand in the way of fluid development.
Even Generics seemed at a first glance to add to this pain, and not alleviate it.
I blamed the principle of strong and static typing as well as the edit-compile-run cycle for that and so oftentimes called for a dynamic language, best to all interpreted, to gain more development speed and flexibility.

But recently I stumbled over the flaws of dynamic typing, interpreted code and multi-language mixup in our codegenerator.

It began with a method which returned a Collection (and I must say, that everying worked somehow before I laid hands on). Porting some code from 1.4 iterator syntax to the new for-loops and thus introducing type parameters revealed a design failure: A method in a subclass of a hierarchy shadowed a superclass’ method far up in the hierarchy with the same name but different return value. Well, indeed only different for the compiler after parameterising the returned Collection, so it was some sort of “duck typing” before.
This flaw was never detected as the methods were called in different contexts, each expecting the type of items in the Collection which it indeed got. But after parameterising the Collection with the respective types, the IDE/compiler immediately uncovered the shadow-problem.

Now, in an IDE renaming a method is a simple refactoring step. Much too easy, so with no effort done even far at the end of a development timeline.

Unfortunately I was not aware that this method was called from within a good bunch of velocity templates, and the IDE was indeed not aware of the dependency between this templates and my Java class.
As velocity templates aren’t compiled but interpreted, there was no way to detect that mismatch during build time.

The application, as I just mentioned above, was a codegenerator, so the problem first occured on test runs, now in some classes generating lesser code than before (what generally is good, but not if happening without intention 😉 ).
Tracing the phenomena made me feel a bit … weary.

It was easily detected to be caused by my renaming action. The template code called the method under its old name, but instead of the expected collection it got an empty one. This was, because after the renaming refactoring, the actually called method was the one from the upper class.
This returned (un-)fortunately an empty collection, otherwise some other template code would have called the items in a way impossible for the type actually carried by that collection, and an exception would have thrown.
But so, simply this code was bypassed due to the empty collection, resulting in a lack of output.

What to do? Well, the calls to the method using its old name had to be changed.

Unfortunately there was no way to determine where in the templates this method was called, other than doing a dumb grep.
After changing the mass of templates, all seemed well at a first glance.
So building the codegenerator again, deploying it and doing the next test run.

But what surprise! Even more files changed, missing parts of formerly generated code!

It took now a good while to detect what was going on.

The template was used in different contexts, where it produced the same lines of generated code.

But to do that, it called the mentioned method on a reference, expecting the retrieved Collection to always contain the same type of items. Only that the type of the objects on which the method was called was not always the same! The template was also used in a context, where another type of objects was referenced, its class not being in the hierarchy mentioned before, so not sharing a common type. A typical case of duck typing: As long as it responds to my message and I get what I want, all is fine. Forget about TYPES!

So what happend so far was:

  • Class One: renaming the method after getting compiler errors due to
  • Templates: renaming the method calls after detecting that mistakenly the superclass’ method was called, leading to misbehaviour.
  • Now: getting even more misbehaviour due to wrong method calls on other types.

The latter misbehaviour resulted from the fact, that velocity does indeed not complain if in code like the following the Dependencies property cannot be found.

#foreach ($dep in ${element.Dependencies})

So the all in all consequence:

  1. Duck Typing works by intentionally doing the right things at the right time.  Knowing that, it becomes part of your development process.
  2. You can do it easily in Java too, simply use Object and the raw type Collection whereever you can. In this way:  Don’t know why people rant against Duck Typing. They did it in the pre-Generics era anyway.
  3. When intending to work with typing to get the most from the compiler, interpreted code and dynamic typing can stab you in your back, especially when your interpreter does the favor to silently ignore incorrect method calls and the like.

At the end more seriously:  After I had to maintain and first of all refactor some … ahem … not so well written foreign dynamic script code, and after getting in contact with Scala, I start to rethink my animosity against strong static type systems and compilers.
I recognise, that it mostly was driven by Java’s verbosity and implementation details than by principles.

Things changes, me too.


Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

Blog at

%d bloggers like this: