Advertisements
Posted by: jsonmez | April 23, 2010

Extension Methods Are Helper Methods That Taste Like Candy

Several people have asked me to write about  C# extension methods, or to give my general guidance on them.  I have to admit I have been waffling on the subject.  It is a very hard subject to address.  It almost feels like the goto statement.

I talked about static methods here, and how bad they are.  I also talked about why you should get rid of helper methods and how to get rid of them.

But, I haven’t really addressed extension methods even though I alluded to them in my post about static methods and they obviously can qualify as helper methods.  Most of you who read my blog would probably assume that I am against extension methods since they are static methods and also helper methods.

I’m gonna start with a question / example for this one

I’m not going to say what I think just yet.  Instead, I want to present you with a situation, and I want you to think about it from an object oriented and system design perspective.

Let us say that we have an application that frequently has the need to use a string as a URI.  Perhaps in that application you will generally have the need to have a browser goto that URI.

You might have some code that would look like:

string webAddress = "http://simpleprogrammer.com";
Uri uri = new Uri(webAddress);
GotoUri(uri);

Not hugely complex code, but let’s say that it is sprinkled throughout your application in different forms, because it is a cross cutting concern. How does this code make you feel?

string webAddress = "http://simpleprogrammer.com";
webAddress.AsUri().Goto();

// or even

"http://simpleprogrammer.com".AsUri().Goto();

I want you to think about the differences between these two examples just in terms of readability. Nothing else. Put away your other concerns for now, and just answer the question.  “Which is easier to read?”

Ultimately the art of software development is about making trade-offs

The true art part of software development is involved in making trade-offs between different values.  We have perhaps an ordering in our mind of what practices are of what precedence or importance.  Sometimes to get flexibility to you have to sacrifice simplicity.  Sometimes to get clarity, it comes at the cost of length.  Sometimes to get simplicity, it comes at the cost of efficiency.  It is somewhat situational as to which of these values trump the other, although I think the software developers you most respect are going to have different basic weights to these values.

My main point here, is that there is one value or principle in software development (of code that must be maintained), that trumps almost every other value.  That value is readability. Perhaps the most important thing we can do is make our code readable.  Derick Bailey has an excellent post on Expressive Code that really illustrates this point by showing how he is willing to double the size of his code to make it more expressive.

In the example I have shown you we are actually reducing the lines of code, even down to 1, and making it more expressive or at least just as expressive.  We are also making it easier to read (because it is plainer English), and easier to write.  But, what’s the price we are paying for this?  The price we are paying is that we are adding static helper methods.  Yes, this is generally a bad thing.  Yes, if you point-blank ask me if static methods are bad, I will not even say “it depends”, I will just tell you “yes”.  Yes, if you ask me if helper methods are bad, I will give you the same answer.  No, I’m not contradicting myself.  What I am doing is making an understood trade-off in value.

I’m not going to suggest putting lots of code into extension methods just because it is cool or it is the easy thing to do, but when you see a situation where you can get a large improvement in readability and reduce lines of code, you might want to consider that an extension method might be worth the trade-off.

Taking one more look at the example

One thing to consider about this example is that if we apply the normal logic for getting rid of helper methods, how will that work?  Normally we would ask where a helper method should really live.  Who does it actually belong to?  In this case, we could say that the ToUri is appearing on string so obviously it belongs on string.  The problem with that is, do you really want to couple your string implementation to Uri? Probably not.

It also works fine to have string as a constructor to Uri, because string happens to be treated as a base type in C#, but if string were some other class, you would have to strongly consider whether you wanted to couple two classes together at all.  Yes, yes, you can create an interface and use dependency injection to decouple the classes, but that has a cost.  That cost can be high.

Extension methods can be a great way to conditionally connect two concrete classes in a system together in certain paradigms. If you want to play in the playground of Uri’s and webpages, import the extension methods that let you treat strings as Uris and let you automatically goto Uris.  If you don’t, just don’t import that extension method.  If you want your IEnumerable to be able to do select and where clauses, import the LINQ extension methods.

Speaking of LINQ

It is pretty hard for us to say extension methods are bad, then praise LINQ.  If you like LINQ, and you like the syntax, then you have to in some way accept that extension methods can conditionally be useful and good.  Microsoft has basically built into the language a guidance by adding LINQ.  Since so much of the code you will be writing will be written against their API, it is not advisable to try and fight against extension methods.  The battle has already been won.

Discoverability

I am just going to briefly touch on this subject, since I want to cover it in much more detail in a separate post.  One thing that is cool about extension methods, and is one of the huge problems about regular old static helper methods, is discoverability.  The problem with regular static helper methods is they are hard to find, so you may not even know they exist.  With extension methods, they show up and are discoverable from the object they operate on.  This may not seem like a big deal, but when working with large or complex systems, disocoverability of APIs is very, very important.

Wrapping it up

In short, I am not advocating the overuse of extension methods, but I am giving them my official seal of approval.  I believe overall they present a positive value to C# as a language because of the uses where they greatly simplify readability and reduce code.  It is still very important to remember to carefully think about when and how to construct extension methods.  Another thing to think about as far as extension methods are concerned is that they are not polymorphic since they are static.

Advertisements

Responses

  1. I like extenstion methods because they make the code more readable. Coming from a VB background, readability is high on my importance list.

    Classic VB used to have a intrinsic Left() and Right() functions built into the language, but for VB.Net these were provided as functions in the Microsoft.VisualBasic namespace. The .Net solution (assuming you want to minimise the use of the VisualBasic namespace) is to use Substring, but this leaves a rather ugly and difficult to read syntax…

    Dim FullName As String = “Joe Blow”

    txtFirstName.Text = FullName.Substring(0,3)
    txtLastName.Text = FullName.Substring(FullName.Length-4)

    By creating extension methods in our Common.Extensions module we can now simply write statements like…

    txtFirstName.Text = FullName.Left(3)
    txtLastName.Text = FullName.Right(4)

    … much more readable, and all the ugly Substring code is out of sight.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: