Dynamic Languages are Wrong

No one is ever going to read this post thus it doesn't matter if I take an absurdly extreme position, so I'm going to come right out and say it:

Dynamic Languages Are Just Wrong For 99% of All Development


There has been a flurry of excitement over ruby and a few other dynamically typed languages in the last few years, driven mainly by rails on the server side and javascript on the browser. Rails is a great project and is far better for most websites than the J2EE stack, but that unfortunately obscures the fact that the language it is built on, ruby, while superior to Java in many ways, just isn't the right thing for most developers.

This is a relatively new opinion of mine. You can see
previous posts of mine where I'm very enthusiastic about ruby. And, at some level, I'm still enthusiastic about it. Many of the features Ruby offers we've translated into GScript at Guidewire and I'm forever in debt to it for that. But that doesn't change the fact that I think it is wrong for most developers.

In order to prove this somewhat ridiculous claim, I'll compare what I consider the key features of ruby and how GScript matches up in its statically typed world.

Terseness

Ruby is incredibly terse when compared with many statically typed languages. As a motivating example, a simple enterprise-y method definition might look like this (
Note: I intentionally include an assignment to a local var in order to contrast with GScript):

  def employees_over_age( age )
    emps = @employees.find_all { | e | e.age > age }
    emps
  end



Compare that with the five to ten lines of java you would have to write to accomplish the same task, with all the generics and types you would have to annotate. I can't even bear to write it all out.

But let's look at the same function defined in GScript:

  function employeesOverAge( age : int ) : Employee[] {
    var emps = _employees.findAll( \ e -> e.age > age )
    return emps
  }



I'll admit, it is more code. But not a ton more and I think most of the additional code is pretty reasonable: you have to annotate in and out types at the method level, which is good because you can restrict your implementation details from leaking out of the method. You have to put an explicit return statement in the code which I actually find more readable. And you have a slightly more verbose but also more consistent syntax for blocks.

So ruby wins in terseness but GScript gets pretty darned close even though it is statically typed.

Open Classes

Ruby elegantly (or hackily, according to tastes) solves another common problem: what if someone hasn't designed a class to your liking, omitting an obvious method or two, and you want to add this functionality to it. In java, this has lead to a proliferation of *Util classes: StringUtil, ObjectUtil, DateUtil, FileUtil, etc. There are thousands of these util classes filled with static methods floating around java code bases. Some code bases are so large (*cough* Guidewire *cough*) that there are many multiple different versions of these utility classes, often with subtly different names.

In ruby, you can simply add a method to a class like so:

  class String
    def my_method()
      puts( "Holy Crap!!! I've added a method to Strings!" )
    end
  end


These are referred to as "Open Classes." Pretty neat, eh? Well, it's so neat that we decided we needed something like that in GScript, so we added something called Enhancements. Here is an equivalent Enhancement:

  enhancement MyStrEnhancement : String {
     function myMethod() {
       print( "Holy Crap!!! I've added a method to Strings!")
     }
  }


Not bad, eh? And because GScript is statically typed and because we provide an IDE for it, you will get very nice code completion when you hit '.' after a string object, with your shiny new method available and quite discoverable.

So I think GScript actually wins here by a hair because it formalizes the class extension mechanism in a new language construct, but both are just about equivalent. The point is that you don't need dynamic typing for this very useful feature.


MetaProgramming

The really killer aspect of ruby and what lets rails clean J2EE's clock in terms of ease-of-development is the metaprogramming ability you have available. This allows you to dynamically generate classes on the fly based on, well, whatever you damned well please. This is how ActiveRecord builds classes based on your database schema, with no code-gen phase in the middle to gunk up the works. You change the schema and,
*bam*, your class is updated.

It's hard to contrast this with GScript's alternative in a succinct, blog-friendly way, but I'll try. GScript has an "open" typesystem allowing anyone to implement a TypeLoader and custom Types in java (which underlies GScript.) That TypeLoader can construct its types based on whatever metadata is wants to just like in ruby. At Guidewire we use this feature to build type systems on top of our web-UI files, on top of our internationalization properties files and on top of our OR layer, to name just a few. This allows GScript code to access these resources in a typesafe way but without any sort of a code-gen step.

GScript's Type System, therefore, is very flexible in much the same way that Ruby's is: developers can implement their API's in terms of types that they create dynamically rather than statically, based on whatever metadata they like.

An Anti-Feature: DSLs

A lot of developers are excited about DSL's in ruby that take advantage of the flexible nature of the ruby langauge. I'm not sure they are such a good idea. I think developers, on balance, would prefer to program in one sufficiently powerful language. I would imagine this is especially true in the enterprise space. I also think language design is pretty difficult and putting a bunch of people to work churning out specialized languages wouldn't turn out as well as we might hope. I think there may even be a biblical story about that sort of thing.

Rather than domain specific languages, I think there should be domain specific type systems: as I mentioned above we have type systems for our web layer, our OR layer, our permissions layer, etc. and it all works out grand. You have access to all these resources in a single language, GScript, presented in (one hopes) a nice API shaped by the dynamically generated types of the particular TypeLoader.

No new syntax to learn, just more libraries. Nice.

So Why Are Dynamic Languages Wrong?

Really it boils down to two reasons: tools and static verification. The first reason is
far more important than the second one.

Being able to hit '.' and see what the hell you can do with an object is priceless, particularly on larger projects. I know some people say "don't get involved in larger projects" but, well, sometimes it happens. Refactor tools (yeah, yeah, SmallTalk, blah blah blah) are far easier to implement correctly with statically typed languages than dynamically typed languages. And total-program analysis tools become possible. If the syntactic and expressive price is low enough (and in GScript, it is) then there is no reason to give up all this functionality for a dynamic language.

Static verification has gotten a bit of a bad name lately and we often joke at Guidewire that "well, it compiled, it must be right." Still, when you are making big changes and you have tens of thousands of tests to run, it is really nice to have something relatively fast (a compiler) point out things you have obviously missed at compilation time rather than waiting to run a series of test suites (even on our distributed testing cluster, it often takes up to an hour to hear back about every test after a checkin.)

But really, I could have stopped at '.'

Good code completion pretty much QED's the argument in my book.
|