Stupid Question 60: Should I use named variables in a loops, lambdas, exceptions etc?
I’ve had a few days of from the Q’ and A’s due to work, but I’m back!
Should I use named variables in a loops, lambdas, exceptions etc?
A few days ago I opened up an older project, and had to look up some code. I found myself staring at a loop trying to figure out what the numbers meant. And I was annoyed at the i.
[sourcecode language=“csharp”]
for (int i = 0; i < 52; i++)
{
//Some action
}
[/sourcecode]
And I decided to rewrite the loop using variables and a constant. (this is just an example)
[sourcecode language=“csharp”]
// Declared outside method body: private const int NumberOfWeeks = 52;
for (var partyEvenings = 0; partyEvenings < NumberOfWeeks; partyEvenings++)
{
//Some action
}
[/sourcecode]
I actually find the the last example more readable even if it is more ‘verbose’, and I think I’ll start doing that from now on. Another question would be, should this be done even with lambda exrpessions? And what about catching exceptions?
[sourcecode language=“csharp”]
private void DoSomething()
{
try
{
var listWithString = new List
{
new NumberData() {Name = “One”, Number = 1},
new NumberData() {Name = “Two”, Number = 2}
};
var selectedItem = listWithString.Where(x => x.Number == 1).Select(x => x.Name);
//named variables
var selectedItem2 = listWithString.Where(numberData => numberData.Number == 1).Select(numberData => numberData.Name);
}
//named variables
catch (StackOverflowException stackOverflowException)
{
Log(stackOverflowException.Message);
}
catch (Exception e)
{
Log(e.Message);
}
}
[/sourcecode]
What is important is to be consistent, and knowing how annoyed I am with from x in list where x.Whatever and so on, I’ve pretty much deciced to type those extra letters, spending a millisecond more doing that, but saving minutes reading the code- and making it easier for the devs on my team or whoever will need to maintain my code.
What is your view on this?
My poetic answer is
Don’t be lazy (type out a word), but don’t go crazy (make it fairly short).
Commit to a way (be consistent), but let the project have it’s say (there might be exceptions to the rule)
For inspiration:
Using single characters for variable names in loops/exceptions
Lambda variable names - to short name, or not to short name?
Comments
I must say, I am quiet annoyed by your blog posts. I have looked through many of your "stupid" questions, and none of them are in fact stupid, they are really good. :-)
Interesting question! In my for-loops I usually use i (for index). I would do this: private const int numberOfWeeks = 52; for (var i = 0; is.Country=="Sweden") but maybe list.Where(customer=>customer.Active) Also when the expression gets a bit carried away, I tend to use shorter names.
You know you're not hardcore until you use no letter for lambdas. I've seen this: Foos.Where(_ => _.id == 1); Consistency is key. In my team, we try to agree upon letters to use (if we use letters and not variable names).
Pretty much what Roman said, if I'm using a ForEach loop and I'm using the item out of the iteration I'll name it. For exampleforeach(var order in orders) { order.DoSomething(); }
Even for simple lambdas I'll use a shortened version like;var result = reports.Select(rpt => rpt.IsActive);
Naming your variables give's them context. Although I'm overly concerned about a simple loop structure such as:for (var i = 0 ; i = 9 ; i ++) { result = i++; }
My opinion for Loops There is any reason to write somefullvariablenameforthatinteger in the loops. Exception might be when there is nested loop, but I have never been in that situation, so I am using i always. (abbrevation for integer???) Lambda I use abbrevation of type name I am currently working with in Lambda statement.var names = listWithString.Where(nd => nd.Number == 1).Select(nd => nd.Name);
Exceptions Same as Lambda. I use abbrevation of exception type.catch (StackOverflowException soe) { Log(soe.Message); throw; }
Since the number of reads of code are orders of magnitude greater than the writes of code, one should try to keep it readable. Readable code is mantainable code and mantainable code can be easily modified to be secure, fast, reliable etc... When I find myself writing a comment for a piece of code I usually use that comment as the method name for a new method containing that piece of code: Extract Method Refactoring. Hope this helps. :) P.S.: Refactoring + TDD really improves code quality
Regarding for-loops: You are absolutely right - you should use real names, unless: 1) You are simply doing stuff a number of times (variable is unrelated to the action) 2) Your variable is used as index in a collection, in which case it is a wellknown idiom to use i,j,k,l,m (if you need this many you should rethink your design ;-)) For lambdas, I think that if 'x' is giving you trouble reading your code, then your collection is named badly. This is bad: var sum = theCollection.Where(x => x.ValueTime == somedate).Sum(x => x.Value); This is better, but still not right: var sum = theCollection.Where(stock => stock.ValueTime == somedate).Sum(stock => stock.Value); The above quickly becomes verbose, and actually can be harder to read, if there are lots of conditions. I like to do it likes this: var sumOfFunds = stocks.Where(s => s.ValueTime == somedata).Sum(s => s.Value); The 's' helps to make it clearer what I am looking at, in case there are more than one variable. So the right naming is important to readability, but verboseness should be used in the right place - in my book, that is not inside the lambdas. In your last example the listWithStrings is an extremely bad name. It is a collection of NumberData, so an appropriate name might be NumberDatas, NumberDataCollection, NUmberDataList etc. Normal naming convetion for collections is to simply use the plural of the type contained in the collection, so a list of string, should be named 'strings'
I think that i is fine as long as you only have one level of loop. When you have loops within loops (and you get "j") it breaks down. To some extent, i is fine, simply because someone who sees it knows that the code is part of a loop, especially if the loop is small and the whole of the loop is visible. Don't sweat it too much. In my experience, it's the people who don't worry about their code being maintainable that write the unmaintainable code.
I'll keep it short and sweet as I should be in the lab right now. For loops and exceptions I like something more verbose than i or e as I have to think less about what these actually represent. For lambdas I prefer the short single letter as it reminds me that this could be anything (within reason). So to put it another way I like to not think about stuff when I shouldn't need to and be reminded to think when I should :) Keep up the good work on this series.
Pretty much, to each their own. The constant for weeks I agree with. A simple i for an index in a small for loop I'm also fine with. If there are nested for loops or other variables that can be confused with the index, then a proper name. For Lamda's again for simple things a single character. I usually use the same first letter as the object being queried. ie A list of numbers (n => n+2).
For a foreach() I'll generally use a descriptive name. But, with a for() I generally just use a single letter. Using your example, consider the part you didn't show: for (var partyEvenings = 0; partyEvenings < NumberOfWeeks; partyEvenings++) { Console.WriteLine("Party on {0} !!", partyDates[partyEvenings].Date); } The longer name for the index is pretty much redundant, and you'd want something the doesn't call attention to itself. BTW, since someone asked, the use of "i" (and "j" and "k") as for loop variables goes back to the early days of FORTRAN. In an early version, variables that started with the letter I,J,K,L,M or N were by default, "fixed point" while variables starting with any other letter were floating point. Fixed point was sort-of like an int (and a bit like a decimal in .NET) -- essentially it was an integer with a decimal point offset. So, you could say "FIXED (5,2)" to mean "5 digits, 2 of which are after the decimal point", and the compiler with store numbers from 00000 to 99999 but know to treat them as 000.00 to 999.99. (Fortran's floating point numbers were essentially the same as doubles in .NET)
My first language was C, so my for loop looks like this: for(int i = 0; i < something.length; i++) { } If I need another counter for some reason my for loop is more exotic: for(int i = 0, auxcounter = 1; i < something.length; i++, auxcounter += 2)
Last modified on 2012-10-16