What you're not getting about programming

Posted at Wed, 23 May 2007 17:24:10 GMT by Wilco Bauwer

Scott Hanselman tries to explain what people may be missing about Ruby. One of the key reasons he provides is programmer intent. Another is that it's simply one of the languages you can look into to stay (or become more) open-minded. To understand what else things could be like for you as a programmer.

Let me start by admitting that I agree with the points he makes. Programmer intent is an important aspect. It's what drives many of the abstractions, in the form of compilers, APIs and tools. I don't write code to design a WinForms app, but instead use the designer in VS. It's a fairly easy way to express my intent. And I'm glad I don't have to write for loops to query a DB either. SQL lets me express my intent more clearly and concise. You get the point. The right tool for the right job, etc. And by looking into new languages, you simply end up with more tools in your bag you can pick from. If not for anything else, it'll give you new insights, alternative approaches and generally just an updated way of thinking which may very well be applicable in the language you already use.

Now with that out of the way, I do want to raise a few additional points. Points that I think people coming from a statically typed world like C#/Java will often relate to when they argue with themselves about dynamically typed languages such as Ruby. Whether they're excuses for them to not look into the language, or whether they truly think those points (however valid they may be) make a language pointless.

The first point is that generally people seem to be talking about a programmer's intent, followed by a basic example that makes sense to the one writing it. What about the other programmer's intent? You know, the one who wrote that library. At rubyrailways.com there are a bunch of examples about the expressiveness of Ruby. Take the XML example near the end:

Ruby:
1 
2 
3 
4 

tree = a {
            b { d e }
            c { f g h }
         }

This should result in a tree of XML. The programmer's intent seems fairly trivial. The intent of the library he's using seems less obvious (guess what the XML output is for this code), at least to me. Maybe it's not a fair point if the 'library' he's using here was written by the programmer and is part of the application's domain. But if it's a general purpose XML library he's using here, I really don't find it that obvious that this code results in an XML tree with nodes of the name 'node', with an attribute name that contains the value specified by the 'nodes' in the code above. Arguably this is more of a flaw in the library than in the language though, which brings me to the next point.

The second point is discoverability. There's a lot of info available in APIs written by statically typed languages. Type information being the most notable one. This is one of those things that doesn't require you to do a context switch to figure out the intent of the other programmer. Take something like a Button. It may have a Width property. Your intent is to set the width to 75px. You specify '75' because, well, so far you've been pretty lucky being able to specify widths in pixels using most APIs. Turns out the API is actually slightly more flexible and expects a Unit type. You now have to go back and fix it. Yes, once you're so accustomed to intellisense and compile-time errors this does seem silly. 'We're' so spoilt that our intent can lack. We're backed up by the 'application's' intent. The compiler will simply tell you what's wrong before we find out the hard way. A level of confidence often strikes us when no compile errors are left. Similarly to the confidence we have that our application is correct once our unit tests are still passing. (I'd like to make a point here, but instead I'll be making a more general point at the end of this post to cover this.)

Yes, early confidence about correctness, because our tools were able to infer a lot of things. They can, to a certain extent, tell us the code is in a pretty good state based on the information we provided. And it can do more. It can do a bunch of other tricks based on this information. Refactoring anyone?

I could go on and on, but, even though it may seem I am trying to point out that statically typed languages are superior, I am not. And any further points I'd make, either in favor of dynamically typed languages or statically typed languages, would be kind of missing the point.

Yes, the point. In my eyes anyway.

Rhythm. There. I just summarized my post with a single word. It's short, so it must be good. No seriously, this is probably very naïve, but I think it's what it all boils down to. People using dynamically typed languages are just working in a completely different rhythm. It's a different lifestyle. The compile errors you get may be critical to you, but someone working in a dynamic language can probably just as quickly run his unit testing tool than you can run your compiler. And they'd be fairly sure their code is semantically correct as well. And yes, you can pretty quickly use find/replace to refactor your code, which will probably only affect a few things anyway because of your short increments. But someone using a statically typed language with the right tools can keep hacking things together and when the time is right, refactor things to something more sensible. No, a find/replace over tens of thousands of lines of code doesn't feel very comfortable.

Coming back to Scott's latest point, about learning a new language every year, I think it's about exactly this. Try a different lifestyle. Understand what it feels like. Understand the good parts and the bad parts. Many of them may very well be applicable to your own lifestyle. You just came from a different background, so you never realized it.

Oh, and learning a new language like Ruby doesn't have to mean you have to throw away everything you invested in. This is one of the points of the CLR and the DLR. Allow people with different lifestyles to live and work together. Yes, I personally wouldn't write all my .NET libraries in Ruby. But yes, I think I could benefit a lot if I would use it to write my Silverlight or ASP.NET applications. The missing_method concept alone really is quite convenient. :)

An easy to read and well written article by someone who knows what he's talking about. What I like is that it refuses to drop into the all-to-easy dynamic/static mud slinging match.

Good job Wilco, as always, look forward to your next post :)
Is different lifestyle the reason Ruby is as breakable as a flake?
Define breakable. Without any code coverage, arguably any kind of code is pretty breakable in the long term.
Great post, Wilco and a great way to pin it down to a word - rythm!

I see these arguments quite a bit as well, and since I come from a background of a mostly-dynamic language (FoxPro/xBase) this is a discussion that comes up quite frequently for me. It's interesting that in that space especially it's very hard to confer the benefits of the other technology until you've tried it and can really appreciate the rythm differences you are talking about. It absolutely is a different approach that affects just about everything you do with the language.

Since I still go back and forth quite a bit I can easily say that the two biggest benefits of static languages for me (in .NET) is the 'compiler crutch' to catch my syntax errors, and the rich, rich discoverability. I think the latter could maybe be addressed with dynamic languages and really smart development environments, but we're not there yet. There's nothing as frustrating like going back to FoxPro and hitting the . key for Intellisense and get either nothing or barely usable information (compared to say C# in VS.NET).

Personally I think that some of the things in C# 3.0 (and VB.next too I suppose) and LINQ are a good balance to get more dynamic functionality and expressiveness without abandoning the benefits of the static model.

But what would be really cool IMHO, is if we could more easily switch and access dynamic language code right from within static code for those few operations when dynamic code is just easier. The easy ability to define say a Ruby code block and just execute it inline or via some stringbased mechanism would really allow bringing the richness of dynamic code to static languages. The DLR almost has this, but it stops just a little short of making this code more genericly callable.

> "Since I still go back and forth quite a bit I can easily say that the two biggest benefits of static languages for me (in .NET) is the 'compiler crutch' to catch my syntax errors, and the rich, rich discoverability. I think the latter could maybe be addressed with dynamic languages and really smart development environments, but we're not there yet."

I believe one of the things the Python guys are working on is adding support for optional typing. This would make it a lot easier for tools to provide help without having to go down "unconventional" paths, and instead provide a similar discoverability as people are used to from statically typed APIs. It'd be interesting to see where that would go and how people would apply optional typing...

> "But what would be really cool IMHO, is if we could more easily switch and access dynamic language code right from within static code for those few operations when dynamic code is just easier. The easy ability to define say a Ruby code block and just execute it inline or via some stringbased mechanism would really allow bringing the richness of dynamic code to static languages. The DLR almost has this, but it stops just a little short of making this code more genericly callable."

I think much of this depends on the richness of the DLR hosting APIs. Imagine things like (purely hypothetical):

C#:
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 

override void OnLoad() {
  scriptEngine.Merge(this); // Make local vars accessible to script.
  myButton.Click += scriptEngine.CreateDelegate<EventHandler>(@"proc {
    |sender, args|
    myLabel.Text = 20.minutes.ago; // We're accessing a field from the C# class.
  }");
}

...

DateTime backThen = scriptEngine.Execute<DateTime>("20.minutes.ago");



Having support for primitive things such as these should keep the barrier low and keep the programmer's context switches to a minimum. Plenty of opportunities...
Your message will be encoded/formatted when it is displayed. If you want to post code, please put the code inside [code=X][/code] tags, where X is the language of your code (C#, ASPX, SQL, etc).
Name:
Email:
(will be encoded using JavaScript to keep it functional and prevent it from being picked up by spammers)
Url:
 
Message:
3 + 3 =