Thursday, June 17, 2010

Natural Language Constructs

Yesterday I casually mentioned to Sean that in my code I seem to vastly prefer lambda over LINQ syntax. He translated that to mean that I probably prefer chaining my actions from one object to the next, or something like that. And, you know what? He was right. I thought about it a bit more today and what I discovered was the reason why I've never liked certain static method calls in C# (actually, I've never liked static methods in general and only grudgingly accept them where needed).

Taking this a bit further, I narrowed down a few key examples of static method calls I've never liked. Let's take a look at what are probably the two most common for me:

string.IsNullOrEmpty(input);
string.Format(input, args);

I can't tell you how many times I've begun typing a variable to check if it's null, only to remember that it's a string and have to back-track for a moment to make the method call. Or how many times I've begun typing a string only to later remember that it needs to be formatted and to back-track for a moment, etc. It's just a little thing, but it irks me a little bit every time.

(In fact, this is probably the reason why it took so long for me to catch on to using string.Format() instead of just concatenating strings together, which I've always done until recently. I hope all the places I've ever worked will forgive that.)

But no longer must I accept these things. For now I can write extension methods! Behold:

public static string FormatWith(this string s, params object[] args)
{
  return string.Format(s, args);
}

public static string IsNullOrEmpty(this string s)
{
  return string.IsNullOrEmpty(s);
}

You may be wondering if that second one will break if it's called on a truly null variable. It doesn't. Man, I love C#.

I can't speak for everyone else, but to me this makes the code so much easier to write. I feel like a weight has been lifted. It's all in how we look at what we're writing, I guess. For me it's about the subject at hand. In this case, the variable. I prefer to start with the variable and chain my commands to it accordingly. (This is also why I hate output parameters and things like Array.Reverse(), which by the way I've also replaced with an extension method). I mean, compare for yourself:

if (string.IsNullOrEmpty(s)) return false;
vs.
if (s.IsNullOrEmpty()) return false;

return string.Format("The value is: {0}", s);
vs.
return "The value is: {0}".FormatWith(s);

At the very least, it's less typing. But, more to the point, it starts with the subject and then proceeds with the actions on that subject. That's how we learned to speak English, that's how some of us want to write our code. It just seems like a more natural language construct, doesn't it?

Either way, I've been making a lot of these extensions, and getting ideas for more from various sources online. StackOverflow has a great thread on the topic.

[Edit: I renamed IsEmptyOrNull() to IsNullOrEmpty() because, unlike Format(), the compiler doesn't seem to complain that it's a name already in use. It can tell the difference between the two.]

4 comments:

  1. This kind of natural language flow you are going for is what a lot of people really enjoy in coding. Look how there are fluent interfaces for a lot of the big libraries we work with. These kind of internal DSLs to give us more expression and flow in our writing. jQuery is pretty famous for it's chaining ability and I think we all can appreciate FluentNHibernate.

    I rather enjoy this as well, although I don't really spend anytime trying to develop the fluent APIs to allow my code to be chained together in a natural way. I think this can make you more productive as you learn the API because generally the API will be trying to conform to how a programming would spill his ideas into the code. So it can eliminate some of the hurdles and backing up you were talking about.

    I do see a lot of this internal DSL stuff coming out of the Ruby community. It seems to be pretty popular and the language is flexible enough to allow a lot of expression in the writing. That and Rob Conery's post about moving their Tekpub site to Rails has sparked some new interest in that language.

    Maybe C# is still a little too low level or restrictive to cleanly express somethings. I suppose for the .NET world there is IronRuby or Boo, but I wonder if the DSL thing will really catch on or still just be spill over from other communities.

    ReplyDelete
  2. Man I need to write some posts

    ReplyDelete
  3. I'm already noticing that my code looks cleaner in using these extensions, so I'm currently in the process of just building an extension library to allow for these natural chains. Be on the lookout for places where this can be done, we can build quite the library here.

    I was thinking about jQuery last night while doing some of this, actually. It definitely exemplifies the model. I've just never really grokked it or had that "ah ha!" moment with jQuery. I'm just not really a JavaScript programmer, honestly. It's never settled in to my skillset comfortably. Hopefully the improved support for it in Visual Studio 2010 will help me in that regard.

    As for writing posts, I was really hoping John and/or Bink would be interested as well. Maybe I invited them too early when this blog had nothing to offer, but I kind of like the direction we're taking it. We just need more readers and more contributors :)

    ReplyDelete
  4. Yeah it would be cool to have either of those guys write some blogs. I know Bink has spent a lot of time on NHibernate. It would be great if he wrote about some of that.

    I really like working with dynamic languages in general it seems, but one thing that still gets me is how to test and maintain javascript.

    ReplyDelete