Clean Code in C# Part 4 Formatting

Code    formatting 
is a
very important                                           topic 
and                                cannot be  


ignored. 

Introduction

Just as the initial text in this post might seem "a little weird", code formatting can also have significant effects on those reading your code. When writing code, I find it important to think about those who will maintain your code in the future. Just like writing a book, sending messages through apps, etc. The style of how text is written can have positive or negative effects on the form how we communicate with others.

Vertical Formatting

According to Uncle Bob, almost all code are read from a left to right and top to bottom manner. Each line of code can represent an action or thought and a group of lines exposes a complete action or line of thought. These actions should be separate with a blank line.

Example 1:

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace Application;

public class Startup
{
    public IConfiguration Configuration { get; }

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseStaticFiles();
    }
}

Example 2:

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace Application;
public class Startup
{
    public IConfiguration Configuration { get; }
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
    }
    public void Configure(IApplicationBuilder app)
    {
        app.UseStaticFiles();
    }
}

In the code Example 2, written in .NET 6 all blank lines were removed the code could be a bit harder do interpret at first glance, especially in the using and namespace section that is grouped together. As seen in Example 1 and Example 2 the inclusion of blank lines for separation of actions, could improve the readability of code.

Class variables

Variables declared within a class that are outside of any methods, should follow a location on where it is instanced. The consistency of declaring variables on known locations, could help developers create standard formatting. Uncle bob suggest creating variables within a class in the top of the class before any methods as shown in the code below:

Example 3:

public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    [HttpGet(Name = "GetWeatherForecast")]
    public IEnumerable<WeatherForecast> Get()
    {
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = Summaries[Random.Shared.Next(Summaries.Length)]
        })
        .ToArray();
    }
}

Analyze Example 4, when variables are declared randomly within a class, as this class grows it may cause confusion to where the variable is located. Having a consistent location to declare variables is recommended.

Example 4:

public class WeatherForecastController : ControllerBase
{
    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    private readonly ILogger<WeatherForecastController> _logger;

    [HttpGet(Name = "GetWeatherForecast")]
    public IEnumerable<WeatherForecast> Get()
    {
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
    }

    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };
}

Class methods

One class can have multiples method, the recommended location for methods is to have the ones that have similar logic close to each other. The code in Example 5 displays methods with similar logic near each other:

Example 5:

public class UserService
{
    public string GetFormattedName(string firstName, string middleName, string lastName)
    {
        return $"{lastName}, {middleName} {firstName}";
    }

    public string GetFormattedName(UserModel userModel)
    {
        return GetFormattedName(userModel.FirstName, userModel.MiddleName, userModel.LastName);
    }
}

Horizontal Alignment

Uncle bob recommends that every line should not contain more than 120 characters. The code bellow has an example of a line with 120 characters.

string longNameVariable = "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW";

Limiting the number of characters in a line depending on the application can be challenging, and this recommendation could be applied and modified based on the scope that developers work on.

Horizontal Spaces

Keeping code with consistent horizontal space and correct identing can significantly impact code, consider the code:

Example 6:

public class UserService { public string GetFormattedName(string firstName, string middleName, string lastName) { return $"{lastName}, {middleName} {firstName}"; } public string GetFormattedName(UserModel userModel) { return GetFormattedName(userModel.FirstName, userModel.MiddleName, userModel.LastName); } }

The code in Example 6 is the same as the one displayed in Example 5. At first glance of Example 5 one could easily identify the class name and its methods.

Visual Studio Shortcut

I currently use the Visual Studio IDE for developing most of my projects in C#. This ide has a shortcut key: "Crtl + K, Crtl + D". This shortcut automates some of the horizontal spaces formatting. The figure bellow has the location of this and related shortcuts located in the edit > advanced tab.

Conclusion

Having a strategy for formatting code should be considered by most professional software developers. The rules presented in this post are mostly recommendations of uncle bob. There are a couple of formatting patterns that I currently use that are not described here.

In a development team environment it would make the life of future and current developers working on the solutions better if the format of these projects follow similar or perhaps the same rules.

References

  1. Clean Code: A Handbook of Agile Software Craftsmanship by Robert C. Martin.

17