Create helper methods to capture key concepts, even if they are only one line. Giving these concepts a meaningful name helps people reason about the rest of the code.

Consider this fragment of code, particularly the if test inside the loop:

public Course Find(string cde, bool throwIfMissing)
{
    foreach(var c in _courses)
    {
        if (String.Equals(c.Code, cde, StringComparison.OrdinalIgnoreCase))
        {
            return c;
        }
    }

    if (throwIfMissing)
    {
        throw new InvalidOperationException("Course not found");
    }
    return null;
}

While it’s easy to make the case that the test is easy to read, there are multiple issues to consider:

  • Any developer reader will need to reverse engineer intent from the code.

  • The policy of using StringComparison.OrdinalIgnoreCase for case comparison is widely repeated, opening the door for subtle defects due to inconsistencies.

  • If the policy of case-insensitive code comparison ever changes, every occurrence of this will need to be changed.

To address this, introduce a helper method HasCode() to do the test:

public bool HasCode(string code)
{
    return String.Equals(Code, code, StringComparison.OrdinalIgnoreCase);
}

This localizes the policy of code insensitivity in one place, ensuring consistency across every use and giving one place for a change if ever required.

With this helper method, you can rewrite the original loop like this:

foreach(var c in _courses)
{
    if (c.HasCode(cde))
    {
        return c;
    }
}

Now the code reveals the intent more clearly - there is no need for a developer reading the code to reverse engineer what it means.

Prior post in this series:
An Introduction
Next post in this series:
Use Standard Library Features

Comments

blog comments powered by Disqus