Which is better, declarative or shorter code?
TL;DR: Be declarative enough but no more.
Problems
Readability
Solutions
Use a short version (or not).
Always favor readability >> Premature optimization.
Humans learn by examples, not by formulas.
Shorter is not always better.
Context
Last week, a tweet went viral because of a missing formula.
It is the DigiD digital authentication iOS app in the Netherlands.
Sample Code
Wrong?
private static string GetPercentageRounds(double percentage)
{
if (percentage == 0)
return "⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪";
if (percentage > 0.0 && percentage <= 0.1)
return "🔵⚪⚪⚪⚪⚪⚪⚪⚪⚪";
if (percentage > 0.1 && percentage <= 0.2)
return "🔵🔵⚪⚪⚪⚪⚪⚪⚪⚪";
if (percentage > 0.2 && percentage <= 0.3)
return "🔵🔵🔵⚪⚪⚪⚪⚪⚪⚪";
if (percentage > 0.3 && percentage <= 0.4)
return "🔵🔵🔵🔵⚪⚪⚪⚪⚪⚪";
if (percentage > 0.4 && percentage <= 0.5)
return "🔵🔵🔵🔵🔵⚪⚪⚪⚪⚪";
if (percentage > 0.5 && percentage <= 0.6)
return "🔵🔵🔵🔵🔵🔵⚪⚪⚪⚪";
if (percentage > 0.6 && percentage <= 0.7)
return "🔵🔵🔵🔵🔵🔵🔵⚪⚪⚪";
if (percentage > 0.7 && percentage <= 0.8)
return "🔵🔵🔵🔵🔵🔵🔵🔵⚪⚪";
if (percentage > 0.8 && percentage <= 0.9)
return "🔵🔵🔵🔵🔵🔵🔵🔵🔵⚪";
return "🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵";
}
}
}
// Full source
// https://github.com/MinBZK/woo-besluit-broncode-digid-app/blob/master/Source/DigiD.iOS/Services/NFCService.cs
Right?
private static string GetPercentageRounds(double percentage)
{
string dots = "🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪";
int blueDots = (int) Math.Truncate (percentage* 10);
int startingPoint = 10-blueDots;
return dots. Substring(startingPoint, 10);
}
Detection
[X] Semi-Automatic
This is a semantic smell. In this case, we can count the number of if clauses.
Tags
- Readability
Conclusion
You can read the original Twitter thread to take your own conclusions. There's some serious debate and, of course, several premature optimizators bringing obscure and unneeded solutions with (O) log(n) complexity and stupid benchmarks evidence for a loop that executes only once.
And lots of memes.
As a final conclusion, I asked ChatGPT and was not able to simplify it.
Relations
Code Smell 36 - Switch/case/elseif/else/if statements
Maxi Contieri ・ Nov 28 '20
Code Smell 20 - Premature Optimization
Maxi Contieri ・ Nov 8 '20
More Info
How to Get Rid of Annoying IFs Forever
Maxi Contieri ・ Nov 9 '20
Disclaimer
Code Smells are just my opinion.
There are two ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies.
C. A. R. Hoare
Software Engineering Great Quotes
Maxi Contieri ・ Dec 28 '20
This article is part of the CodeSmell Series.
Top comments (7)
The thing that confused me most about this function is the fact that the parameter is called
percentage
but it's not a percentage.It'll work if you pass a percentage like 37.5 or even 200.0, but it'll only display anything other than ten dots if it's < 1%.
Maybe that's what the code is supposed to do... but I doubt it!
Me too. Is more declarative. The spirit of the article is to create discussions
Why not just programmatically repeat the relevant glyphs the required number of times? Returning a substring of a string containing 10 of each glyph is a bit too magic for my liking, and difficult to see at-a-glance if you've miscounted.
This code is less declarative than the original one. It is very hard to understand what is doing without running it on your head
I don't usually use C#, I just saw that
string.Concat(Enumerable.Repeat(str, num))
is the idiomatic way to repeat a string in C# (as opposed to repeating a char, and '🔵' isn't a valid char due to being 2 code-units in UTF-16).You could always split that into its own function:
still less declarative
Under what definition of "declarative"? There's no explicit control flow whatsoever (whereas the original has 10 if statements, lol). What do you understand "declarative" to mean if it's not lack of explicit control flow?