It almost looks like a property

Leave a comment

[This blog was moved here]

Based on a true story. Only the names, places, and events have been changed.character2-c

Many people today forget that the tools are just tools. Doesn’t matter if it’s OO or functional programming, take any language: there’re plenty of ways to write awesome and even more – to write terrifying code. lets . compose . these . functions . until . your . type-checker . explodes . btw . did . you . save . everything?

Today I’ll share a simple code-reducing trick, which I came up with a couple of years ago, but still like it for some reason (if you don’t – just deal with it). So what the problem is?

Now answer the question – Do you believe there might be anything except the classes?
(No) No problem. At all. There’s a class, with a bunch of fields. The end.
(Yes) Ok, let’s say the objects of this class suppose to describe the weather conditions. Moving on,

1: class Weather
2: {
3:     public double Temp { get; set; }
4:     public double Humidity { get; set; }
5:     public double Pressure { get; set; } 
6:     public double Rainmm { get; set; }
7: }

You may say, the temperature is usually reported as a range. Here we go:

1: class Weather
2: {
3:     public double MinTemp { get; set; }
4:     public double MaxTemp { get; set; }
5:     public double WindChill { get; set; } 
6:     ... // other properties
7: }

Nice, but there’re also different observations for the night/morning/afternoon/evening forecasts, which one may want to include into the same forecast:

1: class Weather
2: {
3:     public double MinNightTemp { get; set; }
4:     public double MinDayTemp { get; set; }
6:     ... // other properties
7: }

Now add several predictions for future dates, whatever. On a rainy day you may find out the number of fields somehow approached fifty, *sigh*, add another one and forget about them.

And then the Universe decides that it was not fun enough and you should make the predictions more consistent with reality (or at least pretend to do so), for example, by including the information from other sources like <insert your favorite weather forecast website here, I’d better take an umbrella anyway>. You quickly run an experiment with the min/max temperatures and expect to get a 10% improvement in accuracy by weighting the observations from different sources… But there’re more than 50 properties already, remember?

1: var w1 = 0.8;
2: var w2 = 1 - w1;
3: var result = new Weather 
4: { 
5:     MinNightTemp = w1 * orig.MinNightTemp + w2 * ext.MinNightTemp, 
6:     MaxNightTemp = w1 * orig.MaxNightTemp + w2 * ext.MaxNightTemp,  
7:     ... // oh, why is that intern on vacation now? who will fill in all this stuff?                          
8: }

It could be anything else, the key is that there’s a set of operations, similar for all the fields, and the fields are somewhat similar too – in our case, they’re all of type double.

Let’s create an array instead, where the fields are the elements of this array:

1: for(int i = 0; i < n; ++i)
2:     x[i] = w1 * y[i] + w2 * z[i];

But… but now we don’t know what is what. Ok, here’s the answer:

1: enum P 
2: {
3:     MinNightTemp,
4:     MaxNightTemp,
5:     ...
6: }
7: ...   
8: var res = x[(int)P.MinNightTemp];

What about a kind of vector? It looks even better:

1: var x = w1 * y + w2 * z;   
2: var res = x[P.MinNightTemp]; // compare to x.MinNightTemp

– Saves a lot of typing, decreses the probability of potential mistakes;
– You don’t need even a dictionary – an array is already enough;
– The enum part can help to preserve the order (in original case that was mandatory requirement), nothing breaks if you add a new feature somewhere in the middle;
– Every field automatically has its own underlying value, you avoid the mistake of assigning the same value to the different constants (e.g. MinTempInd = 42 and MaxTempInd = 42);
– There’re good chances no one will ever notice, that Weather is not a separate class any more. It almost looks like a property.


Instead of conclusion

There’re simple yet annoying problems, and to solve them you don’t need a dataframe or any complicated data structure or even a separate class. C# is not that bad in the end, no one forces you to write only overly-OOP code.

That doesn’t mean you can’t come up with more concise solutions using a different language or solving a different problem. Only that there’re ways – in everything – to do the familiar things differently, the ways not everyone notices.