25 March 2013
Avoid returning null…

…is all you need to avoid handling them. Quoting NOOO:

Options over nulls

Before digging into the argument, let’s take something simpler.

One of the worst thing of imperative code is all that ugly null checks.

Anyway please don’t feel disappointed, before realizing and getting in touch with FP; I as first filled my code with these.

For example take a C# code snippet like this that returns a collection of Order types.

var orders = DB.GetOrdersByDate(DateTime.Now);
if (orders != null)
{
  foreach (var order in orders)
  {

    // do something with order
  }
}

There’s no reason to design DB.GetOrdersByDate() to returns a null when no Order satisfies the request. An empty collection, easly obtainable with

return Enumerable.Empty<Order>();

would be great, the following code could became

var orders = DB.GetOrdersByDate(DateTime.Now);
foreach (var order in orders)
{
  // do something with order
}

When orders value is empty (or better an empty collection) no iteration will be performed, hence no kind of check is required.

Anyway cases could present in which you must check for order presence (in the old semantic the null check). Now we can elegantly write:

var orders = DB.GetOrdersByDate(DateTime.Now);
if (!orders.Any())
{
  // no orders
}

Because this code is semantically correct, hence is intrinsically more robust.

MayBe monad

As Mark Seemann says in this article: the BCL already has maybe monad.

He proposes the following construct through extension method:

public static class LightweightMaybe
{
    public static IEnumerable<T> Maybe<T>(this T value)
    {
        return new[] { value };
    }
}

So when you face an API (which you can change or not wrote by you) you can treat it like the sample above.

var client = LegacyDB.GetSingleClient(id: “101”);

if (client.Maybe().Any())
{
  // result is not null
}

As you can see this extension method put the T value inside a generic IEnumerable<T>, in this way you can use the beatiful Linq syntax to write readable code that clearly states its intent.

But this mean you should design code that returns null? No, you shouldn’t. I take the extreme position that returning a null is comparable to having a bug in the code.

If you can refactor LegacyDB.GetSingleClient() change its signature from:

public Client GetSingleClient(string id)
{
  if (found)
    return new Client(...);

  return null;
}

to

public IEnumerable<Client> GetSingleClient(string id)
{
  if (found)
    return new Client[] { new Client(...) };

  return Enumerable.Empty<Client>();
}

There’s nothing bad neither logically neither semantically to have a method handling one item returns a collection containing one item or otherwise an empty collection.

To me it’s wonderfully clean, clear and concise!

Alternative

However I can understand criticism to this design, that could distract you from the main argument of this post: not returning null to avoid handling it.

You can design the method above using a singleton like string.Empty following the Write once immutability pattern, as explained in this Eric Lippert article.

public Client GetSingleClient(string id)
{
  if (found)
    return new Client(...);

  return Client.Empty;
}

The fundamental point here is that having a value, is always better than handling a null.

This is the reason why functional language like F# use option monad to describe if a result has or has not a value.

When keep it

New compiler constructs and projects like Code Contracts could remove also this necessity.

But for now there’s nothing bad to check null to validate method parameters.

public Client GetSingleClient(string id)
{
  if (id == null)
    throw new ArgumentNullException("id");

  if (found)
    return new Client(...);

  return Client.Empty;
}

However also here my opinion is a bit extreme: guard clauses are just against null; everything else falls into other application concerns such as validation.

But deepen it goes beyond the purpose of this post.

Conclusion

This blog post starts with a reference to NOOO. This is because this work is extracted from an unfinished and partly unpublished document.

The project aims to defined guidelines for developers who want to design API adhering to functional concepts from multi-paradigm languages like C#.

If you’re interested in this collaborative work, write to me (gsscoder AT gmail DOT com) or ping me via Twitter (@gsscoder).

Or visit this web site in status of work in progress.



How to comment

You can add a comment to this post by sending me a pull request. If you prefer discuss this post on Twitter or somewhere else with a permalink. Send me the link, and I may add it as a comment.