Alexander Beletsky's development blog

My profession is engineering

Extension methods and clean code

Extension methods is one of my favorite features of C# language. It appeared from version 3.0 and became very popular.

The main goal of Extension Methods is to provide ability of extension of any class, without creating any derived classes, modifying original type or do “whatever” hacks. It is allowed to extend any type with any functionality in a very seamless fashion. What also great about Extension Methods is they allow to beautifully emulate behavior usually called pipelining (in F# or Bash) and implement Chain of responsibility pattern.

But the most important as for me - Extension Methods help to keep my code clean. Clean code criteria is something I concerned a lot, nowadays.

I recently started to practice with code katas, that I found essential for any developers who cares about keeping their saw sharp. So, after several iterations I came up with extension methods implementation that I pretty happy about. I’m using Roy Osherove’s StringCalculator kata. It is about the implementation of simple method Add that:

  • Takes numbers separated by delimiter, as string
  • Determines if custom delimiter is set
  • Split up original string to array of number tokens
  • Validates the input (no negatives allowed) and returns the sum of numbers, ignoring numbers greater than 1000

I would like to show to you both implementation and try to evaluate them from “clean code” point of view.

Original one (this is of cause a little “unwinded” version, I had a different structure with smaller methods.. But idea still the same).

public int Add(string numbers)
{
    var delimiters = new[] { ",", "\n" };

    if (IsCustomDelimeterProvided(numbers))
    {
        delimiters = GetDelimitersFromNumbers(numbers);
    }

    var processed = numbers;
    if (IsCustomDelimeterProvided(numbers))
    {
        processed = processed.Substring(processed.IndexOf('\n') + 1);
    }

    if (IsContainDelimeters(processed, delimiters))
    {
        var splittedNumbers = numbers.Split(delimiters, StringSplitOptions.None);
        var validation = new NumbersValidation();

        foreach (var number in splittedNumbers)
        {
            validation.Check(number);
        }

        validation.Validate();

        return splittedNumbers.Sum(p => GetIntegerWithCondition(p, IgnoreNumbersMoreThatThousand()));
    }

    return Convert.ToInt32(processed);
}

Do you think is this code clean? I don’t think so.. Of cause, it might be not so difficult to understand it, but:

  • Method is just too long
  • A lot of if statements make it difficult to see instruction flow
  • It messes up “infrastructure” code (splits, validation) with primary functionality (sum of numbers)

Let’s try to read it: I got the numbers and I check if custom delimiter is set on the beginning of numbers string, if so I try to extract the custom delimiters from original string. After I pre-process the string to remove custom delimiter prefix, so do not break the rest of function. If numbers string contains the delimiters, I split it up, perform the validation by helper object (which will throw exception is something wrong). Run Sum algorithm that would: covert string to integer and ignore one if it is greater that 1000.. Otherwise, it just tries to convert to integer and return.

A lot of words, a lot of ifs isn’t it? Thats not good.

Now, my last implementation with using of Extension Methods:

public int Add(string numbers)
{
    var defaultDelimiters = new string[] { ",", "\n" };
    var delimiters = numbers.CustomDelimiters().Concat(defaultDelimiters).ToArray();

    return numbers.Replace(" ", "").Split(delimiters, StringSplitOptions.RemoveEmptyEntries)
        .RemoveSpecialSymbols().ToIntegersArray().ValidateIntegersArray().IgnoreIntegersGreatThanThousand().Sum();
}

Do you feel the power? I definitely do!

I believe that this code is very clean. It basically does not require any comments, because it looks like “plain English” explanation of what’s the functionality is all about! Anyway, let’s try to read: I extract custom delimiters from numbers string and concatenate them with default delimiters. I replace all space with empty symbol (note: this step is not in original requirement, but I put it to keep code robust), then I split them with delimiters ignoring empty lines. After I remove all special symbols in numbers string and convert the result to array of integers. I validate this array (no negatives) and ignore any numbers great than thousand. At the end I sum up everything and return the result.

What is good about this code:

  • Method is very short
  • All details are hidden
  • Control flow is very straightforward
  • All dependent methods has meaningful names
  • Method does exactly what it is suppose to do

Conclusion

Well, don’t get me wrong here. I’m not saying that now only Extension Methods is a way of solving the issues. Of cause not. But if you feel the smell of pipeline of chain of responsibility patters, extension methods are right choice. As always you should consider to do not “overplay” with some particular feature of language/framework.

You can use links I gave above to read about technical details in MSDN. Check out full implementation and tests as my example of usage.