Dotnet logo

.NET Tools

Essential productivity kit for .NET and game developers

How-To's

Put it down in layman’s terms – code smells series

This post is part of a 10-week series by Dino Esposito (@despos) around a common theme: code smells and code structure.

So far in this series about code smells, we’ve made the point that keeping the language of the code close to the language of the business is crucial to reducing misunderstandings and speeding up development. Naming classes, methods, and sparse values appropriately is part of the job. Today, let’s look at bringing the code even closer to the business language!

In this series:

A very common scenario in nearly all types of code is checking the value of a variable against a fixed range of values, mostly constants. In modern programming languages, the enum type is the artifact used to declare a list of named integer constants.

public enum RoomState
{
    Unknown = 0,
    Available = 1,
    Occupied = 2
}

While the value of any constant is an integer, an expression that evaluates to any of the constants is of a type that inherits from System.Enum. In the code snippet, it is RoomState. Enum values are typically assigned to variables or evaluated in conditional statements.

if (state == RoomState.Occupied)
{
    Console.WriteLine("Room not available");
}

Even when all you need to do is check a value against a constant, you never know what can happen next as the code base grows. Turning explicit constants into enum values is a good first step.

Checking values using the == operator doesn’t help readability, even when names are chosen properly and in full respect of the ubiquitous language of the business domain. Again, ad-hoc methods come to the rescue! We can make our code more explicit by adding a couple of methods.

Here’s a sample Room class with a State property expressed via an enum type.

public class Room
{
    public RoomState State { get; private set; }
 
    public bool IsOccupied()
    {
        return State == RoomState.Occupied;
    }
 
    public bool IsAvailable()
    {
        return State == RoomState.Available;
    }
 
    // More methods
}

To programmatically check the state of the room, you can go with plain if statements. However, using ad-hoc methods makes the result much easier to read.

if (room.IsOccupied())
{
    Console.WriteLine("Room is not available");
}

Finding code with structural search

Let’s say that you developed much of your code using plain comparison via the == operator. There might be hundreds of occurrences to find and fix. Is there a quick way to find all of them in a single (and reliable) shot?

Well, ReSharper allows you to do that in a rather comfortable way! You can make use of structural search. From the ReSharper | Find menu, we can Search with Pattern.

ReSharper - Search with pattern

ReSharper’s Search with Pattern looks for all expressions that match the specified code pattern. In this case, you may want to make sure that $var$ (the placeholder for the left-hand side of the comparison) is an expression of type System.Enum or any derived type.

Search for expression with type

Once the pattern is defined, you can run the search and explore results. All that remains to do is to go through each occurrence and apply the necessary fixes – either manually or by using structural replace.

Search results

A wrapper method doesn’t just make your code easier to read, but also hides the details of the comparison being made. Depending on the complexity of the code you are writing, it might not really be far-fetched that at some point the comparison becomes a more sophisticated operation. Now is the time to fix them. The sooner, the better! Your future self will thank you.

Next week, we will look at new vs. factory methods and where it makes sense to use them.

Download ReSharper 2018.1.2 or Rider 2018.1.2 and give them a try. They can help spot and fix common code smells! Check out our code analysis series for more tips and tricks on automatic code inspection with ReSharper and Rider.

image description