Tips for naming variables(makinggoodsoftware.com)
makinggoodsoftware.com
Tips for naming variables
http://makinggoodsoftware.com/2009/05/04/71-tips-for-naming-variables/
23 comments
Indeed, I think one very useful rule for naming variables is "the length of the name should be proportional to the scope". If you're iterating through a list of objects representing unfilled orders, it's OK to do this:
for uo in unfilledOrdersIterator():
oid = uo.id
status = uo.status
email = uo.customer.email
sendEmail(email, "Your order %s is in status %s" % (oid, status))
But if there's a 200-line method that does all sorts of other things with a single unfilled order, then calling the order "uo" is probably a bad idea.Shouldn't there NOT be 200-line methods in the first place?
There are some cases where 200-line methods are perfectly acceptable, when breaking the logic into smaller functions only complicates the understanding and development of the algorithm. Not everything can be broken into multiple elegant 10-line functions without obfuscating the purpose or control flow.
One thing I've occasionally done to tame large functions is this:
def frobWidget(widget):
def frobCog(cog):
## stuff involving both cog and widget
## stuff involving widget
frobbedCogs = [frobCog(cog) for cog in widget]
## more stuff involving widget and frobbedCogs
If frobCog were broken out into a separate function, then it would have to take widget as an argument, and if frobCog is never actually called from anywhere other than within frobWidget, then such separation makes the code harder to understand. Keeping the definition internal lets me take advantage of lexical scope; I can refer to widget within the definition of frobCog.In the example you showed I'd probably do the same, true, but I think there is no evil in passing widget as an argument.
In general, there's nothing wrong with functions that take everything they use as arguments. This is kind of functional programming (or a good part of it): every function is as independent as possible, which makes them easier to debug, easier to understand, and safer in terms of bugs. Functions that deal with data from outer scopes risk being less readable and less reliable.
In general, there's nothing wrong with functions that take everything they use as arguments. This is kind of functional programming (or a good part of it): every function is as independent as possible, which makes them easier to debug, easier to understand, and safer in terms of bugs. Functions that deal with data from outer scopes risk being less readable and less reliable.
Formally speaking, every line and every block (if, while...) can be moved to a separate function. Provided that functions are given fairly descriptive names, it is always possible to go as far as you wish in splitting your functions into smaller ones. I don't see any problem with that except reading/understanding, of course, which depends on your "target audience" so to say.
If you have a good sense of code aesthetics, you can make your code look like pseudo-code, which every decent coder is supposed to understand. So your quicksort may look almost like:
If you have a good sense of code aesthetics, you can make your code look like pseudo-code, which every decent coder is supposed to understand. So your quicksort may look almost like:
function quicksort(array)
var list less, greater
if length(array) ≤ 1
return array
select and remove a pivot value pivot from array
for each x in array
if x ≤ pivot then append x to less
else append x to greater
return concatenate(quicksort(less), pivot, quicksort(greater))
or it may be a 50-liner with no sub-routines. It's a matter of choice, really.Um, have you ever written code like this in a real program? Honestly? Why would you ever want to swap variables?
(I mean, I remember doing this thing in TI-83+ BASIC, where valid variable names were limited to the letters of the alphabet ...)
(I mean, I remember doing this thing in TI-83+ BASIC, where valid variable names were limited to the letters of the alphabet ...)
Check out some popular sorting algorithms, those that do the job "in place", i.e. without additional memory allocation.
Yes... but how many times have you re-written a sort? (Where 'you' is your average programmer, or, even, the above-average programmer who reads technical blogs and toward whom this post is targeted)
If you are an inventor of sorting algorithms, I'd guess you do that quite often.
But seriously, does it really matter? Short functions or blocks with variables of local significance do exist. Swap() was just the first thing that popped up, probably because I like messing around with algorithms and re-implementing them. Which every self-respecting programmer, umm, should do, I think.
But seriously, does it really matter? Short functions or blocks with variables of local significance do exist. Swap() was just the first thing that popped up, probably because I like messing around with algorithms and re-implementing them. Which every self-respecting programmer, umm, should do, I think.
Most projects contain at least a handful of utility functions that your base library doesn't offer. These utility functions are largely independent of the problem domain, and often of a mathematical nature. Therefore, short, undescriptive variable names (such as 'x') are perfectly acceptable.
Stopped reading here: "Good example: daysFromDateRangeStartToEnd".
Seems like the author didn't take his own advice - "2.- The variable name has to be as short as possible."
Hi babo,
you are absolutely right with your observation, that variable name its just a bad example, I have just edited the post and I have changed its name to daysDateRange.
Thanks for your feedback
you are absolutely right with your observation, that variable name its just a bad example, I have just edited the post and I have changed its name to daysDateRange.
Thanks for your feedback
Neither your original daysFromDateRangeStartToEnd nor daysDateRange seem to capture what it is supposed to represent. Perhaps if it was seen in context, it would be understandable, but by itself I do not think it is a good example.
> Example. If your customer just considers “order” an “order” that has been approved, don’t call “order” to a non approved one in your code, call it “nonApprovedOrder”.
Doesn't this violate his rule #5?
Doesn't this violate his rule #5?
Hi Deestann, good catch, I should have stressed that these are guidelines not rules, what I meant is if possible use positive logic, but it fits better the negative, use the negative one.
Thanks for the comment
Thanks for the comment
Ideally should be using short methods, so what's wrong with using generic names?
"Don´t use negative logic for your variable names."
Obviously written by a software weenie who lives far, far away from the actual hardware. ;-) (Digital logic often uses active-low signals for good electrical reasons. And some purely historic reasons: do memory chips actually need to power up in the activated state?)
Obviously written by a software weenie who lives far, far away from the actual hardware. ;-) (Digital logic often uses active-low signals for good electrical reasons. And some purely historic reasons: do memory chips actually need to power up in the activated state?)
What what what?
Many circuits work with Boolean values that are true in the 0 state, and false in the 1 state: negative logic. That had better be reflected in the variable names.
Small blocks with very obvious code are perfectly Ok to have short variable names in. All other rules in this post can be criticized as easily.
Hence, rule #8: forget about the previous rules, just be a smart coder.