Archive for March, 2006

At the edge of the world: Ruby NilClass versus Eiffel NONE

This post is an analysis of the difference in philosophy between static and dynamic typed languages and the pragmatic ramifications of these philosophical differences. I will use Nil/Null/None-types as basis for the example.

The Nil-value is used in OO programming languages to designated a non-assigned value. Any object reference can be nil, which gives it a special role. In effect, Nil is an instance of all types. This is a concept that can only be expressed in a language that supports multiple inheritance. As far as I know, the only programming language that expresses this “correctly” is Eiffel, where the type NONE inherits from all other types in the system. In a language that checks that no object may receive a message that is not defined by its type, this is the only logical conclusion. A variable of any type can be assigned the value NONE, because NONE is an instance of all types. Other static languages express Nils as a special exception to the type hierarchy. For example in Java, most klunky special-case code that I encounter is code for dealing with nulls.

In contrast, Ruby defines NilClass independent of all other classes. As Ruby variables do not have types, any variable can be assigned to any object, independent of its type. There is no reason you could not make your own NilClass if you wanted to. This works through the principle of Duck Typing: If it responds to the message walk() like a duck and it respons to the message quack() like a duck, it’s an instance of type Duck. The class declarations and inheritance hierarchy has nothing to do with it. This means that the analytical concept of type is separated from the implemenation of types. It also means that there’s nothing really special about nil.

At first, Duck Typing seems like a philosophically sloppy, but pragmatic solution to the problem of typing. “If we weren’t so lazy, we could categorize the world neatly and correctly into structures of types and subtypes”. However: The world is not like that.

When I first graduated from college, I imagined the world could theoretically be described mathematically. Since then, I’ve learned a few things. One of these things is that categorization is artificial. Categories like color, species, grammatical classes, and even gender are human simplifications: They do not exist in the external world as well-defined things (the same can be said about the distinction between static and dynamic languages, incidentially). When we talk about them, it is always as a pragmatic shortcut, much in the same way as with duck typing in dynamic languages.

The problem with strict categorization is not only that it is time-consuming - it’s that it’s not an accurate description of the real world. Philosophically, static languages build on a flawed understanding of the world.


PS: This does not mean that I’d always go for a dynamic language. Static languages have some technical advantages over dynamic languages. Most importantly, tools for working with static languages are currently more advanced.

Comments

Best of Jason Yip

One of the blogs I enjoy reading is that of Jason Yip: You’d think with all my vide game experience that I’d be more prepared for this (excellent title!). He usually writes short and sweet posts that gets a point across in just a few sentences. Here are a few of my favorites:

It’s a blog well worth subscribing to.

Comments

The Reverse Guatanamo Principle

Aslak Hellesøy created the …. interesting tool Guatanamo. From the documentation: “Do you have problems maintaining high test coverage? All code is guilty until tested innocent. Send the untested code to Guantanamo!” (that is, delete it)

I think this is a very interesting policy, and even though it is too extreme to ever be practical, it reveals an underlying principle: If code doesn’t have tests, it doesn’t have value. Chances are that it is rigid, poorly designed, and wrong. I call this the Guatanamo Principle: If code doesn’t have tests, it does not have protection from other team members desires to delete it. Go ahead, delete the code!

However, I have noticed a conflict between TDD and the YAGNI principle. Much of our code is only used directly by tests. This often happens when I (or someone else) design a subsystem to be generic before I use it. This code is almost always no good. It is complex and often does not even solve the specific problem it was made to solve. The lesson is that you never need to impement a “generic component”. You need to write a specific component to solve a specific problem (”what is your code doing?”, “oh, you know, something generic. A little of this, a little of that”). This doesn’t mean you shouldn’t generalize, but you should always keep the specific problem in mind. (Thanks to Kevlin Henney for this point)

So, I propose an addendum to the Guatanamo Principle: The Reverse Guatanamo Principle: If a class or public method is only directly used from tests could (and possibly should) be deleted, along with its test.

(When applying the Reverse Guatanamo Principle, please make sure that the class is not included in XML-configuration files, too….)

Comments

Creative Commons Attribution 3.0 Unported
Creative Commons Attribution 3.0 Unported