Dynamic Languages: A Separation of Concerns

I saw Nick Muhonen give a talk on the new language features in C# 4.0 last night at the Portland-Area .NET User Group. He did a good job in spite of the constant questions I asked. He showed one example that I found especially compelling:

object GetConfig() {
  return new {
    WindowSize = new Size() { Width = 100, Height = 200 },
    ConnectionString = "...",
    ...
  };
}

Of course, you wouldn't hard code settings in your application -- you'd load them from somewhere (ideally a database, but that's another story : ). Anyway, in C# 4.0, I can write code like this:

dynamic config = GetConfig();
mainWindow.Size = config.WindowSize;
...

Notice the use of the dynamic keyword -- this means I don't have to know the type at compile-type -- I'll check for the WindowSize property at run-time ala .NET Reflection, COM IDispatch or VB "Option Explicit Off". Of course, this is the cornerstone of all dynamic languages, e.g. Perl, Python, Ruby, etc. These languages have been gaining in popularity for the last few years and I didn't understand why. Tim Ewald, my close friend and compadre, kept trying to explain it to me, but I'm just too slow to get it and I didn't ''til last night watch Nick do his thing. It wasn't looking at the code that Nick typed that made the point for me, it was looking at what he didn't type.

When writing dynamic code, there is no requirement to define a type.

That is, when I inevitably add another property or 10 to my app config, I have to write code to use the new properties, but that's all. I don't have to write a class and I likely don't have to update the save/load code either, because it's also going to be dynamic and just expose whatever data is part of the serialized config. Or, to put it another way:

When writing dynamic code, I only have to write the part I care about.

In the case of dealing with application config, that's about 2/3rds of the code I no longer have to write. Of course, this isn't a new idea -- Stuart Halloway has been talking about embracing essence (the code you care about) and rejecting ceremony (the code you don't) for a long time now. It just took Nick's concrete example for me to understand it.

And not only does this make dynamic code good for reducing the code you type, it always makes it good for the code you're generating, e.g. COM interop assemblies, database mapping code, XML mapping code, etc. In general, I find that most of the code we have generated for us in the .NET programming environment is code to map to foreign type systems, i.e. COM, databases, XML, web services, etc. With dynamic languages, you can write that code once and just use it. In fact, in C# 4.0, there's no need to use Primary Interop Assemblies (PIAs) anymore -- those can just be mapped to a sub-class of the "DynamicObject" type that .NET 4.0 ships to provide that dynamic mapping bridge.

When writing dynamic code, you don't need generated code layers to map to foreign type systems.

This means I don't have to do the mapping to databases per query or to XML per XSD -- I can just have an implementation of DynamicObject, point it at my configuration and go -- no muss, no fuss. Of course, purely dynamic languages have a construct for DO built right in, so it's even easier.

Around the table after Nick's talk last night, someone was complaining that with purely dynamic languages, I give up the benefits of the compiler doing static type checking (I think it was Nick : ). I argued that this was a good thing. The compiler is really just one kind of unit testing -- it's testing names. It can't do any of the other unit testing you need done, however, so you still need unit tests. What that means is that, with static languages, you've got some unit tests separate from your code and some baked into the code via types, casts, etc.

When writing dynamic code, you can separate unit tests completely out of your code.

Of course, as software engineers, we already know that separating concerns leads to better, more readable and more maintainable code, which is why we've long separated our applications into tiers, separated our view from our data, our interfaces from our implementations, etc. Dynamic languages let us do another complete separation of concerns with regards to unit tests that static languages don't allow. In a static language, the ceremony is required, thereby obfuscating the essence.

And all of this is great except for one question -- how do I get my list of possible code to write when I type "." if I'm using a dynamic language or dynamic features of a static language ala C# 4.0?

When writing dynamic code, I don't get Intellisense.

My name is Chris Sells and I'm an Intellisense addict. Admitting I have the problem is the first step...