When you learn a programming language, your initial coding style is dictated by the lessons; your teacher; the books you study. My first programming language was Sinclair BASIC on the ZX Spectrum 48K. I had a book on how to code simple games, that would influence how I'd name variables, etc. (mostly as single letters, which was a terrible idea).
Several years later, I'd got into developing with Visual Basic, Hungarian notation was all the rage; (TL;DR, prefixing variable names to indicate its type, e.g. iCount
for an integer variable to count something with).
Even later, when I was learning C#, Hungarian notation had fallen out of favour, mostly due to Visual Studio compile-time type-checking; and that it was deemed healthier and maintainable to have semantic variable names. You adapt with the times (and your development teams) and evolve your coding style.
Tabs vs spaces
My long time personal preference for indentation is tabs. It made sense to me. A single character of variable width (configurable in your code editor/IDE). However most development teams that I've worked on have had a stronger preference for the use of spaces, so we'd end up have tiresome debates on which was better. (When I became the Lead Developer on my team, there were less debates, tabs would win out).
This all changed when I started working on open-source projects. The evilest type of indentation is mixed tabs & spaces - it's the kind of thing that'd turn my stomach! You have to pick a style and stick with it; consistency. Of course, I would pick tabs, but when I receive a pull request contribution, I'd often find there'd be either a mix of tabs & spaces, or worse, entire files re-indented from tabs to spaces... things would get tribal.
I soon came to the conclusion that I was swimming against the tide arguing for tabs, when the majority of developers would use spaces. I wanted to play nicely with others, I cared less for the bike-shed, so I adapted to use spaces and evolved my coding style. (It took me a few years to get used to this!)
Note: With the widespread adoption of the
.editorconfig
specification, (circa. 2017), it became simpler to enforce a consistent coding style for an entire project.
Brace! Brace!
Code readability is something that I'd become more aware of since contributing to open-source projects. Reviewing code changes on pull requests in a web browser can get a little tricky to mentally process.
For example, take a single line conditional, I'd be tempted to write...
if (input == null) throw new ArgumentNullException(nameof(input));
This is fine and acceptable. However if we were to modify this line, say with an extra condition or change the exception logic, the line gets longer; the diff looks messy; it can take a little more mental processing to understand the exact change.
I opted to take the more verbose approach of having newline-braces for all code blocks, including single line conditionals.
if (input == null)
{
throw new ArgumentNullException(nameof(input));
}
The C# compiler doesn't care, and it's more readable to me.
Ternary conditional operator
I do like the ternary conditional operator, (?:
uh huh huh), it can make simple single-line if/else statement more succinct. In a similar vein to the code blocks, I end up placing the resulting expressions on indented newlines.
public string GetResult(bool flag)
{
return flag == true
? "Success"
: "Failure";
}
Again, more verbose, but more readable in my mind and gives a structure for any future amends; understanding diff changed, etc.
Cognitive load
On the topic of code readability, you may have noticed in my previous code snippet I added == true
to the condition. Many developers see this as ugly and redundant code, as the condition is implied to be true
. Sure, once you understand that's happening, that's fine, you're an experienced developer, totally acceptable.
Let's take this condition...
if (!string.IsNullOrWhiteSpace(input))
When we read this condition, we think, "okay, if the string is not null or empty or whitespace then proceed". But optically, scanning the text from left to right, you have to mentally take note of the unary logical negation operator (!
bang), then understand what the string.IsNullOrWhiteSpace
method means; in both terms of resultant object-type (hopefully a Boolean) and the argument parameter. Your brain is keeping track of a couple of things here, the negation and the method result, then cognitively swapping them around to make a natural English sentence (in my mind).
Taking the same example, but now with the explicit Boolean operator...
if (string.IsNullOrWhiteSpace(input) == false)
For me, optically, the text scans the way I comprehend the logic, "is the string null or empty or whitespace? no? then proceed".
The C# compiler doesn't care whether you use the !
bang or == false
, it all compiles down to the exact same bytecode, (trust me, try it out in LINQPad, view the generated IL code).
If you strongly disagree with me on this one, that's cool, there's a special reddit thread for experienced developers.
C# language evolutions
Much of my C# syntax keeps changing as the language itself evolved. It didn't take me too long to switch over to using var
declarations and $"Hello {name}"
string interpolation. But some other new language features have taken me longer, like the file-scoped namespace declaration (as opposed to have surrounding braces for the namespace), or Span<char>
pattern matching (way too much cognitive load, it hurts my head).
I try to evaluate the latest C# language features, to get a feel for if they appear comprehensible to a newcomer. If so, then I'd most likely adopt it.
Top comments (3)
It's good to identify another
== false
fan. I forget who first suggested this to me, but my eye for detail is so poor that this must have saved me a bunch of times.I'm afraid you might've been onto something with the tabs thing adamtuttle.codes/blog/2021/tabs-vs... 😉
💯 😁