Back to overview

A humble lesson in maintainability

By 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 ?

Outside in testing - To mock or not to Stub Thumb

By Ben Luts

Jul 2025

Outside in testing - To mock or not to Stub

I’ve been going around conferences talking about it a couple of times now, so why not write a blog post about it. So what is outside in testing? In a ...

.NET Methodology
Decorator Pattern Thumb

By 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

By 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 ...

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