Think about the larger projects you’ve worked on during your career. Did you have a dumping ground for odd pieces of functionality? Perhaps a utility class or even multiple multiple utility classes? It’s a very common thing to see a utility class in any codebase of reasonable size, especially one that has been around for a while.

Often there is just one utility class. Sometimes there are multiple utility classes. In some .NET projects, I’ve seen an entire assembly of otherwise unrelated utility classes. Typically these are a grab bag of useful stuff that doesn’t seem to have anywhere else to live. Almost universally, these utility collections become a festering mess of spaghetti code and a regular source of subtle bugs.

There is a better way. There are better places for the functionality to live - locations that are easier to discover, approaches that easier to use, structures that are easier to test, and code that’s easier to maintain.

One technique is to replace static methods with extension methods: If your utility class has a set of methods that all work on a common type, consider extracting them all out into an extension class for that type.

For example, on one project I worked on years ago, we ended up with a set of utility methods for working with strings. While that project was written in Delphi, here are some C# examples:

// Extract the prefix of a string before the first occurrence of a delimiter
var prefix = TypeUtilities.StringBefore(s, ":");

// Extract the suffix of a string after the first occurrence of a delimiter
var suffix = TypeUtilities.StringAfter(s, ":");

// Remove the prefix of a string before the first occurrence of a delimiter
var head = TypeUtilities.RemoveStringBefore(ref s, ":");

class TypeUtilities
{
    static string StringBefore(string s, string delimiter) { ... }
    static string StringAfter(string s, string delimiter) { ... }
    static string RemoveStringBefore(ref string s, string delimiter) { ... }
}

A key clue here is the presence of a common first parameter - they all take a string as the first parameter, and they’re all more focused on string manipulation than on anything else - an example of the feature envy code smell (see the famous Refactoring book for more detail).

Another clue is the way they all have String as a part of their name.

In a modern environment, we should replace those methods with new extension methods hosted by a dedicated StringExtensions static class:

var prefix = s.Before(":");
var suffix = s.After(":");
var (head, rest) = s.SplitAt(":");

static class StringExtensions
{
    static string Before(this string s, string delimiter) { ... }
    static string After(this string s, string delimiter) { ... }
    static (string head, string rest) SplitAt(this string s, string delimiter) { ... }
}

Note the use of C# 7 tuple syntax for the renamed method SplitAt(), which now returns both pieces instead of modifying the original.

It’s important when doing this to ensure that the Extensions class remains tightly scoped, else it falls into the pit of failure and becomes another utility class collecting cruft.

Perhaps the best way to do this is to ensure that the extensions contained by the class are all tightly focused on the same base type - hence the name StringExtensions, above. All other extension methods would live on other extension classes, with names based on the base type they extend - perhaps DirectoryInfoExtensions, FileInfoExtensions and DateTimeExtensions.

About this series

Cleaning up the dumping ground of the utility class.

Posts in this series

Using Extension Methods
Using Semantic Types
Using Consolidation
With Relocation
Using Premeditation
Next post in this series:
Using Semantic Types

Comments

blog comments powered by Disqus