Cognitive load : static vs extension methods

Cheese board sitting on cans of tomatoes
Extending tools beyond their original purpose

A c# specific example to follow up my blog post on cognitive load, since it coincidentally came up at work.

What are extension methods?

The example concerns c# extension methods. For those of you who aren’t C# developers, they allow you to create a static method that can be called as if it was a class method, without needing to modify the original class. They’re mainly useful for extending classes or basic types with new functionality, such as business-specific rules. For example, the LINQ library extends IEnumerable types with a number of functions, including Where() which provides the filter functionality found in functional programming, allowing users to write code like:

int[] array = {2, 3, 4, 5, 1};
return array.Where(x => x % 2 == 0); 
// returns {2, 4}

The x => x % 2 == 0 in the above snippet is a lambda expression that takes an input x (for the Where method, each member of the array) and returns the result of the expression on the right of the arrow.

LINQ example

The discussion centred around whether extension methods like the above were preferable to code using static methods such as :

int[] array = {2, 3, 4, 5, 1};
return Where(array, x => x % 2 == 0);
// returns {2, 4}

As you can see, here array is passed as the first argument (which is what extension methods do behind the scenes).

The example I raised looked like the following, where a number of these methods are chained together. Note that all the methods return a new result, as they are built to allow immutable collections, such as input buffers.

Static methods

filteredthing = Linq.Where(thing, x => x.Deleted == false);
orderedthing = Linq.OrderBy(filteredthing, x => x.CreatedDate);
result = Linq.Select(orderedthing, x => new y(x.Name, x.Id)); 

Chained extension methods

thing.Where(x => x.Deleted == false)
    .OrderBy(x => x.CreatedDate)
    .Select(x => new y(x.Name, x.Id)); 

I argued that the former requires more thought, and therefore a higher cognitive load to understand which variable to use, and the density of code requires makes it less readable and therefore makes the next developer’s job harder.

String example

The most interesting example however, was the one that started the discussion. Which of the following forms do you prefer, and why?

mystring.IsNullOrEmpty()

or

String.IsNullOrEmpty(mystring)

In particular, note that we don’t have the variable or code proliferation as in the LINQ example, and the return value is an explicitly different type.

The most persuasive argument I heard against the extension method version is that it explicitly works when mystring is null, which leads to a counterintuitive situation where, as developers, we are trained to spot potential NullReferenceException problems, and will immediately view the first form with suspicion, until we realise it is an extension method.

Question

Which form do you prefer, and would either one stop you in your tracks as you were scanning code and break your train of thought.

Advertisements

5 thoughts on “Cognitive load : static vs extension methods

  1. Craig,

    “The most persuasive argument I heard against the extension method version is that it explicitly works when mystring is null..”

    That is not an argument against extension methods, an extension method is a static helper which can be expressed slightly nicer way in C#

    Take the string example you mentioned, both the static and extension expression will result in exactly the same behavior.

    Like

    1. Of course it works but the syntax makes it look like a likely NullReferenceException, so a defensive programmer will need to do a double take to understand they don’t need to check for null before the call.

      Universal rules such as ‘always check for null before dereferencing’, are easy to follow. Any variation or exception to that rule is a cognitive load on the developer and distracts them from the train of thought. It’s not always easy to see if string.MyExtensionMethod() is safe to call without checking for null.

      Like

      1. I take your point, but I still don’t really see this as being a problem with extension methods.

        Like you say, its not easy to see if string.MyExtensionMethod() is safe to call without checking for null.

        but is MyExtensionMethod(string s) any easier to see if its safe to call without checking for null?

        Like

      2. It’s about expectations. I expect the caller to check in the former case and the callee to check in the latter.

        Like

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