Too big or too clever?

2007-12-20, , Comments

When it comes to programming languages, not everyone equates dynamic with better, but I was surprised to read Alex Martelli cautioning against it. Here he is though, in a recent post on comp.lang.python, responding eloquently to the topic “What’s better about Ruby than Python?”.

Too clever

Martelli identifies a fundamental difference between the two languages:

… Ruby’s TOTAL, unbridled “dynamicity”, including the ability to “reopen” any existing class, including all built-in ones, and change its behavior at run-time — vs Python’s vast but bounded dynamicity, which never changes the behavior of existing built-in classes and their instances.

He considers this:

… a crucial issue — one that makes Ruby much more suitable for “tinkering”, BUT Python equally more suitable for use in large production applications. It’s funny, in a way, because both languages are so MUCH more dynamic than most others, that in the end the key difference between them from my POV should hinge on that — that Ruby “goes to eleven” in this regard (the reference here is to “Spinal Tap”, of course). In Ruby, there are no limits to my creativity — if I decide that all string comparisons must become case-insensitive, I CAN DO THAT! I.e., I can dynamically alter the built-in string class so that

    a = "Hello World"
    b = "hello world"
    if a == b
        print "equal!\n"
        print "different!\n"

WILL print “equal”.

In python, there is NO way I can do that. For the purposes of metaprogramming, implementing experimental frameworks, and the like, this amazing dynamic ability of Ruby is _extremely_ appealing. BUT — if we’re talking about large applications, developed by many people and maintained by even more, including all kinds of libraries from diverse sources, and needing to go into production in client sites… well, I don’t WANT a language that is QUITE so dynamic, thank you very much.

I’ve heard this opinion before, nudged even further along the static-dynamic scale. Some argue Python is too dynamic for large applications; that you’re better off with something more disciplined, statically typed, enterprise ready, something with decent IDEs to keep your code in shape — something like Java.

Too Big

In “Code’s Worst Enemy” Steve Yegge rants about his own large application:

… a beautiful game [written] in an ugly language … lovely on the outside and quite horrific internally

The ugly language turns out to be Java, 500,000 lines of it. Eclipse won’t load it. The code base has collapsed under its own weight.

Yegge identifies size as the enemy. More controversially, he argues some of our conventional allies in countering this enemy are, in fact, traitors. Refactoring, for one: applied to Java, it can result in code bloat. And all that design-pattern boiler-plate. Look, even our precious IDEs deceive us!

Java-style IDEs intrinsically create a circular problem. The circularity stems from the nature of programming languages: the “game piece” shapes are determined by the language’s static type system. Java’s game pieces don’t permit code elimination because Java’s static type system doesn’t have any compression facilities — no macros, no lambdas, no declarative data structures, no templates, nothing that would permit the removal of the copy-and-paste duplication patterns that Java programmers think of as “inevitable boilerplate”, but which are in fact easily factored out in dynamic languages.

Completing the circle, dynamic features make it more difficult for IDEs to work their static code-base-management magic. IDEs don’t work as well with dynamic code features, so IDEs are responsible for encouraging the use of languages that require… IDEs. Ouch.

I think Yegge gets a lot wrong in this rant, but it’s clear he speaks from experience, and for all his swagger it’s also clear he’s thought hard about what he says. I agree with his main point: size is the enemy. And I agree with his conclusion too. You need a language which allows you to dispense with boiler-plate, a language in which you don’t have to repeat yourself. A powerful language. A dynamic language.

Who’s Right?

So, who’s right?

For a large application developed by a large team and maintained by a larger one could a language like Ruby be too dynamic?

Or is size the enemy? Do we need a language so powerful it absorbs design patterns, so dynamic we never need repeat ourselves, so succinct we can fit the code in our heads?

I’d say the latter. A dynamic language might be too slow (for a few parts of a system) but it can’t be too dynamic. Meta-programming requires taste and restraint, of course, not to mention boundaries; and we mustn’t expect any one programming language to fix our design. For any large system, I’d expect multiple components, layers of abstraction — and layers of languages.