Retour à l'aperçu

A humble lesson in maintainability

Par Bruno Latte

.NET

Sep 2019

A while back I needed to process some data that came from a webservice, a weather API. As you may know, these services usually have far more data then you generally need. In my case I just needed the temperature and humidity forecasts. The data needed to be processed so it could be plotted in a chart. Basically, you’d have one signal for temperature and one for humidity. (For simplicity, I just do an output to the console to simulate the processing of the data.) So, here was my solution.
class Program
{
	static void Main(string[] args)
    {
		var data = new List() {
			new WeatherData(){ Temperature = 15, Humidity = 65, UVindex = 6, WindDirection = "NNO", WindSpeed = 20 },
			new WeatherData(){ Temperature = 16, Humidity = 65, UVindex = 6, WindDirection = "O", WindSpeed = 35 },
			new WeatherData(){ Temperature = 19, Humidity = 45, UVindex = 8 , WindDirection = "W", WindSpeed = 45 },
			new WeatherData(){ Temperature = 13, Humidity = 75, UVindex = 3, WindDirection = "NO", WindSpeed = 65 } 
		};

        ProcessTemp(data);
        ProcessHumidity(data);
                                 
        Console.ReadLine();
    }

    static void ProcessTemp(List data)
    {
        foreach (var item in data)
            Console.WriteLine($"{nameof(item.Temperature)}: {item.Temperature} °C");
    }

    static void ProcessHumidity(List data)
    {
        foreach (var item in data)
            Console.WriteLine($"{nameof(item.Humidity)}: {item.Humidity} %");
    }
}

It worked, check-in, time to get a beer…

As you guessed, it got rejected.
What if the customer decides to track windspeed. Just create another method to process that parameter? And another and another and …. You see where this is going.

The tip was to use a selector, like they do with the Linq extensions.

The new code looked like this:

class Program
{
    static void Main(string[] args)
    {
        var data = new List() {
            new WeatherData(){ Temperature = 15, Humidity = 65, UVindex = 6, WindDirection = "NNO", WindSpeed = 20 },
            new WeatherData(){ Temperature = 16, Humidity = 65, UVindex = 6, WindDirection = "O", WindSpeed = 35 },
            new WeatherData(){ Temperature = 19, Humidity = 45, UVindex = 8 , WindDirection = "W", WindSpeed = 45 },
            new WeatherData(){ Temperature = 13, Humidity = 75, UVindex = 3, WindDirection = "NO", WindSpeed = 65 } 
		};


        ProcessData(data, d => d.Temperature, d => nameof(d.Temperature), "°C");
        ProcessData(data, d => d.Humidity, d => nameof(d.Humidity), "%");
        ProcessData(data, d => d.UVindex, d => nameof(d.UVindex));
        ProcessData(data, d => d.WindSpeed, d => nameof(d.WindSpeed), "km/h");

        Console.ReadLine();
    }

    static void ProcessData(List data, Func<WeatherData, int> selector, Func<WeatherData, string> propertyName, string unit = null)
    {
        foreach (var item in data)
            Console.WriteLine($"{propertyName(item)}: {selector(item)} {unit}");
    }
}

Ok, the signature of the method got a bit more complex, but if you’re used to working with Linq, this is not as daunting as it looks. But imagine the processing of the data happens in some other assembly, maybe even written by someone else. You would need to edit 2 files (or tell someone to update their API), adding a method to your business logic and wherever you’d implement that method (UI, service, whatever).
With the new method, I don’t need to edit the business side and just implement the method. Only 1 place to change a single line of code, also just 1 method to test and maintain.

This example gave me a better understanding of Linq and changed my view on what is a called “a simple implementation” of something. Many lightbulbs were gotten ?

Decorator Pattern Thumb

Par Paul Karam

Mar 2025

Decorator Pattern

One of the biggest challenges in our daily job is keeping our code clean, easy to read, extendable, and understandable. It's a difficult task, but it becomes ...

Strong Under Pressure: resilient HTTP clients Thumb

Par Michiel Mijnhardt

Nov 2024

Strong Under Pressure: resilient HTTP clients

Building resilient applications is crucial, and part of that resiliency is making sure your applications outgoing http requests are covered. The .NET go to ...

An introduction to NSwag Thumb

Par Karel Verhulst

Aug 2024

An introduction to NSwag

In the world of modern web development, API's play a crucial role in enabling communication between different software systems. The process of creating, ...

Cache primary btn default asset Cache primary btn hover asset Cache white btn default asset Cache white btn hover asset