Well chosen variable names are crucial for understanding what a program is doing. I plan to write about naming well but for now, it’s more fun to criticize bad variable names.
1. Nondescript Loop Counters
move 0 to #i
while #i < 50
show ‘Hello World’
add 1 to #i
end-while
Sometimes we just want to do something fifty times. The loop counter has no purpose beyond controlling the loop. More often, we do something else with the loop counter. It might index an array, or control an evaluate command, or contribute to a formula in a let command.
If we use it beyond the while test, it must have some meaning, and so it should have a name that reflects that meaning. Even if it is just a loop counter, it should have a distinctive name. Someday, the loop may contain a procedure call, and that procedure may contain a loop. If we’re not careful, we’ll use the same global variable for both loops, and it won’t be pretty.
2. TLA (Three Letter Acronyms)
Obvious, isn’t it, that $ccn is the variable containing the customer contact name? What’s the variable name for credit card number?
3. My Fingers Are Too Tired For Long Names
I once programmed with a version of BASIC in which variables could be a single letter or a single letter followed by a single digit. Some programmers, perhaps hunt-and-peck typists, still use the shortest possible variable names. That’s not much worse than acronyms, but after a page full of $a1, #b2, $a2, $d5, you’ll be begging for acronyms.
4. I’m Paid By The Byte
The opposite problem is variable names that are too long.
let #sick_leave_accrual_rate_for_union_members_in_hours_per_month = 7
OK, that is self-documenting code. It also risks bugs from typos and it elongates any command that uses it:
let #current_sick_leave_balance_in_hours = #sick_leave_carryover_from_previous_year + #current_month_of_this_year * #sick_leave_acrual_rate_for_union_members_in_hours_per_month - #sick_hours_taken_year_to_date
Did you notice the typo?
5. It Is A Value, Isn’t It?
There are variable names that are like the generic canned goods that enjoyed brief popularity a few decades ago. A can of peas would be wrapped in white paper with no photo and no brand name. The word “Peas” and a barcode would appear in black. Or was that just an Andy Warhol painting? I don’t remember.
The variable equivalents are like $string, $date, #value, #number, #total. We can assume that #total is the sum of a group of numbers. Perhaps there’s only one possible meaning for “total,” in a report of employees’ annual salary … until someone adds a column for year end bonuses.
6. The Variable Is The Value
let #one = 1
let $one = 'one'
If #one equals one, we could use the literal instead of the variable. If #one does not equal one, it’s confusing. What application is interested in one as a mathematical concept or a Platonic ideal? We’re interested in headcount or expenses or coordinates on a page. Did you notice the number of bad variable names I promised in the title (#ten)? Look down, and you’ll see that #ten = 12.
7. Is That A Dash Or A Minus?
The first version of SQR did not have the let command nor expressions in if and while commands. The only way to subtract was with the subtract command. It allowed dashes (which look like minus signs) in variable names.
The SQR compiler will warn you of variables like #age-1. I avoid dashes unless I have a situation like one where the variable that contains a person’s age as of a year ago. In that case, I might write:
put #weight #height into annual_checkup(#age)
let #age-1 = #age – 1
! put command doesn’t allow the array index to be an expression
put #prev_weight #prev_height into annual_checkup(#age-1)
let #weight_change = annual_checkup.weight(#age) – annual_checkup.weight(#age - 1)
8. Have I Met You Before?
Without disciplined naming conventions, it’s easy to forget what we called something. We might start the program with variables like this:
- #num_emp (number of employees)
- #vac_hrs (vacation hours)
- $start_date (first day of a period of time)
After a week of programming, we may be writing with variables like this:
- #nbr_emps (number of employees, but with a different abbreviation for “number” and a different policy about plurals)
- #vac.hours (vacation hours, but with a different word separator and abbreviating “vacation” but not “hours.”)
- $begin_dt (first day of a period of time, but with a different synonym for first and an abbreviation for date.)
We only want one variable to hold the number of employees, but we’re counting them in one place and printing them with a variable that was never changed from zero.
9. Recycled Variables
I’d be surprised to find someone reusing a variable name for something completely different. For example, $start_date containing “01-JAN-2009” in one part of the program and “California” in another part of the program. It’s probably less unusual to find $name containing an employee’s name in one procedure and a dependent’s name in another. It’s probably most common to find variables containing different date formats at different times:
input $as_of_date ‘Enter date (mm/dd/yyyy)’
… (50 lines of code, including five procedure calls) …
let $as_of_date = datetostr(strtodate($as_of_date, ‘mm/dd/yyyy’), ‘dd-mon-yyyy’)
begin-select
…
where effdt <= $as_of_date
end-select
Here, $as_of_date has the same meaning throughout, but it is formatted differently at different times (American date format versus Oracle DBMS date format). When you see this variable scattered through the source code, do you know what it contains? Is it suitable to print on a report? Is it suitable to use in a SQL statement?
10. What’s The Difference?
Sometimes variables are closely related. It may be tempting to give them long, similar names:
- #dept_subtotal_overtime_hrs (hours that earn time-and-a-half)
- #dept_subtotal_overtime2_hrs (hours that earn double time)
- #dept_subtotal_overtime_amt (the dollars paid for overtime)
Most of the characters in the variable name repeat what the variables have in common (dept_subtotal_overtime). If these variables are embedded in dense code, it’s hard to tell them apart. It may be worthwhile to highlight the differences in the variables.
- #hours_of_1.5overtime_dept_subtotal
- #hours_of_doubletime_dept_subtotal
- #earns_of_1.5overtime_dept_subtotal
11. OK, you knew this was wrong
I can’t remember whether I’ve actually seen these variables, or just dreamt them in a nightmare. (What, you don’t dream about SQR programming?)
let #xxxxxxx = 3.141592653
let #xxxxxxxx = 2.718281828
12. I heard you the first time
It’s not that these are bad variable names. They’re just an excess of unnecessary variables. Redundancy reduces clarity. Repetition lessens understanding. Multiple statements of the same information leads to confusion. Creating several versions of the same variable makes code harder to read. Expressing an idea over and over will annoy your reader. (Enough?)
begin-select
EMPLID &EMPLID
let $emplid = &EMPLID
from PS_JOB
…
end-select
This programmer may not know that SQR will automatically put the value of EMPLID from the database into a column variable called &EMPLID. The option of naming the column variable is for cases where:
- We want to call it something other than the name of the column in the database, or
- We want to perform an operation on the database column (max(), to_char(), etc.) and we want to put the result of that operation in a column variable, or
- We a selecting the column with a dynamic variable (see next week), and SQR doesn’t know which column it will be at the time of compilation.
Also, we can use the column variable (&EMPLID) throughout the program. We don’t need to copy the value to a string variable ($emplid) unless:
- We need to alter the value later, or
- We are calling a procedure from multiple places in our program, using employee IDs that came from multiple sources, and the subroutine needs to work with the employee IDs from those multiple sources.
Request For Information
Nominate more variable name bad practices. How about bad procedure names (do process)?
Looking Ahead
The SQR language allows us to embed commands of SQL. The two languages communicate in many ways. Obviously SQL sends data to SQR through the column variables, but it also sends status information through the SQR reserved variables. SQR sends data and commands to SQL through variables, dynamic variables, and compile-time substitution variables.
Next week, we’ll look at three ways SQR embeds varying values in the SQL statements it sends to the database.
Brain Teaser
A palindrome is a word or phrase which is the same forward and backward: It may be possible to reverse every letter, as in civic, rotor, level, racecar, or “Madam, I’m Adam.” Or, we can reverse the order of words, while leaving each word intact, as in “Fall leaves after leaves fall.” (For my non-English readers, “Autumn ends after every leaf drops from its tree.”)
This game is both easier and harder in a programming language like SQR. Easier, because variables can be anything that follows a #, $, or &. Harder, because there are fewer keywords and fewer valid sequences of keywords.
What is the longest VALID command you can form that is also a palindrome, disregarding spaces and special characters? Let me start:
“show $wohs”
“add #ot to #dda”
“clear-array name = emanyarra-raelc”
Let’s also count beginnings of commands, like “create-array name = emanyarra-etaerc” and word-invariant commands like “show #show.”
I scored 8 points! Woo hoo!!
Nondescript loop counters: Guilty! In my partial defense, I’m doing it in C++ so the variables are local. I don’t need to worry about calling a procedure inside the loop.
TLAs: I’m GAC (Guilty as charged). But I use them for short-lived variables and they’re better than calling them “temp”.
Fingers too tired: This is closely related to nondescript loop counters, so anyone who commits one of these probably earns double credit. I sure do – at least for short-lived temporary variables.
Paid by the byte: Well, at what point does this rule kick in? I’ve had some names that I thought were on the long side, but they weren’t quite as bad as your examples. And of course, in C++, typos get caught by the compiler.
It’s a value: I’ve sometimes named a short-lived temporary string variable ‘str’ or ‘s’. Along with the loop variables and “my fingers are too tired” variables, I’ve earned three points for this habit. HA! IN YOUR FACE!
Variable is a value: I’ve done this too, but in a very narrow situation. If I want to pass a one or a True to a procedure, but for some reason, the procedure requires me to pass a pointer to the value (this is in C++ again) I’ll do this.
Recycled variables: I’m not sure if this counts, but I’ll name a variable ‘fileName’ and then use it as temporary storage while I compute the file name. The variable will ultimately end up with the file name in it, but for a short time, the variable name is a misnomer.
What’s the difference: Yup! Maybe I’ll need a string in both ANSI and Unicode formats, so the names will be subtly different. Making the difference obvious is so subjective… at least it’s obvious to me!
This was a fun article. Thanks! And it supports my basic philosophy that if code is hard to write, then dammit it should be hard to read!
Thanks for the inventory. I’ll bet it feels good getting that off your chest. Now tell me, what’s the worst operator overloading you’ve ever done?
I’ll bet you could find a lot of these bad variable names in well-respected programming textbooks.
Do foo and bar count?
I feel there is some amount of confusion in this article. specially the reference of teh bottom keywords with real humanly words. but that is what has interested me.
Agreed. Bad variable names can cause confusion when someone is reading the code. The compiler can handle a variable like “#ten” without “thinking” about the number 10. A human reading it has to struggle to remember that the value of “#ten” is actually 12.
I realize that Bob Josephson’s enumeration of the bad variable names he uses was done semi-humorously, but maybe he should consider either cleaning up his act, or getting out of the programming business.
Perhaps I should let Bob speak for himself, but the first step to self-improvement is to understand one’s own shortcomings. Are you sure that your code is any better than his? Perhaps it is just as bad – or as good – or exactly the same. If you want to make the world a better place, try starting with the man in the mirror.
Hey, Ed, didn’t you point out earlier that “well-respected programming textbooks” have bad variable names, too? So don’t go ragging on me. And besides, if you follow all of Steve’s recommendations, what’s left to use for a variable name?
Steve points out shortcomings in variable names, and I won’t dispute that they’re real. But in certain contexts, maybe some of these names are appropriate.
But I’m sure you’re perfect. Why don’t you share some of your code with us here, so we can see if you’re the pot to my kettle. In other words, put up or shut up before trying to kick people out of the profession, you self-righteous little brat.
Let’s try to stay constructive, both of you. I don’t want a flame war, but I’d be happy to see an educational exchange of code. Remember Edward, Bob is just trying to earn a living. How bad could he be if he reads this blog? And Bob, how could you possibly know whether Edward is a little brat? He might be 6 foot 2.
I don’t need to prove anything to you, Bob, and I’m not about to start posting proprietary code here. Besides, given your enthusiasm for lousy variable names, I wouldn’t trust your judgment anyway.
Do you have code reviews at your place? I’d bet money you don’t – and it’s lucky for you.
But I’m not going to stoop to name calling. The administrator is right: we don’t want a flame war here. So this is my last port on this topic. Go ahead and respond if you want – you can have the last word.
Well, Bob, I guess it’s a good thing that you and Edward aren’t co-workers. It seems like you’re fairly easy-going while Edward takes his craft very seriously. Edward is giving you the last word, but I’d advise you not to provoke him.
I’m glad you see the virtue in no longer posting, Ed. I hope you’ll be equally virtuous in the future.