My name is Alex.... and I once use bad variable names...
Back in the day, while fresh out of college and wet behind the ears in the programming world, I used to name some variables very badly.
The worst of which was my counter variable names. I now use i, j, k, and so on for local counts and things like activeRowCount for the more descriptive names. Before, in the early years mind you, it shames me to say, I would name my counters things like Dracula, Chocula, MonteChristo?. They are all counts after all. I apologize for my intial variable naming conventions and shall go beat my face now as punishment.
-- Alex
'I recall a programmer who used to work for me who named variables "pig", "cow", "dog" ...' Some of the worst I've seen are using the lowercase "ell" and uppercase "oh" as variables:
l = l + 1; This = That + O;A PetPeeve of mine was someone I worked with who liked to name miscellaneous C character arrays "mystring". Was he afraid that someone else would come along and misuse his variable? (I think that misuse is much less likely if you give them a clue as to what the variable's *FOR*!)
Perhaps a habit derived from using the 'my' operator in PerlLanguage? -- DominicCronin
A good variable name should indicate its use, like "ErrorMessage" or "InputBuffer". And if it has several different uses, you should probably split it up into several different variables.
I couldn't believe this one: "Information" - duuhhh, so that's what it's for(!)
I have a class called Codes. It has a property called data. Guess what its type is... - that's right! CodeData? -- DorKleiman
A pet peeve of mine was someone I worked with who liked to name miscellaneous C character arrays "mystring".
I am working on a project right now, where I have taken over someone else's Java code. It often goes something like this:
public class Foo {i.e. the prefixes my, the and a are used a lot. Perhaps it is some kind of HungarianNotation? :)private String myString;
public Foo(String theString) { myString = theString;
int aPos1 = 0; int aPos2; // ... }
}
This is similar to UncleBobsNamingConventions. It takes some getting used to, but it can help make code read more like prose and disambiguate scopes.
We are currently attempting to correct a number of serious problems in a particular component of a large C++ system. We found the following declaration in one of the files:
const int TWENTY_EIGHT = 28;What in God's name were they thinking??? --ChuckMcCorvey
The problem here is that you assume they were thinking! ;->
[Maybe they wanted to support other values of 28?]
At a past company, the coding standards forbid using MagicNumbers. We ran a tool that counted coding standards violations, and we included that value in our team status reports. I ended up defining FOUR = 4, etc., since I didn't have the time to enter meaningful names.
Maybe it was a descendent of an old UNIVAC program or by an old UNIVAC programmer? Twenty eight was the number of words per sector in old UNIVAC disk hardware and it lives on to this day. See http://www.fourmilab.ch/documents/univac/fastrand.html#28
#define ONE 1 #define ZERO 0No, I'm not kidding. I'm glad I didn't have to work on it. --RobCrawford
''At least it wasn't the following:
#define ONE 0 #define ZERO 1''
Weird as it might seem, it is not uncommon in Fortran to define constants like one for 1.0d0 and zero for 0.0d0. I thought it was insane at first, but after I got burned by very subtle type errors a few times, I started doing it myself. Have mercy, I only do it in Fortran.
I guess the real solution is to never program in Fortran, and to not release old Fortran programmers into the world. ;-) --Mike Gertz
Some people started programming a long time ago when FORTRAN was most of what there was. Some of us have adapted and do different things as well now -- JohnFletcher
I think you are solving the wrong problem. You should define constants with names describing their purposes not their values. You need to define constants like "NumberOfFingersOnAHand" not "Five".
Let's not confuse fingers with digits. The human hand normally has five digits, only four of which are fingers, and one digit being the thumb. "NumberOfDigitsOnAHand" should be "five", "NumberOfFingersOnAHand should be "four"
There's a reason for that. Old FORTRAN compilers would use one memory location for each instance of a constant in the source file. That is, if the number 0.0d0 appeared twenty times in a program, it would appear twenty times in the compiled code. Add to that the low memory available to early FORTRAN programs, and you see why a declaration like DOUBLE PRECISION DZERO/0.0d0/ would be useful. And, of course, the older programmers teach the newer programmers.
Memory storage really was small, bulky and expensive by modern standards thrity years ago. I have a section of memory assembly 4K x 16 bit from a Honeywell 316 which is about the size of 2 Zip disks (holding 500 MBytes)!. Also the 0.0d0 was needed as otherwise the double precision variable was initialised with single precision zero and the rest nonzero rubblish. This could easily cause errors later. -- JohnFletcher
A similar trick was used often in AtariBasic, in which you would see the first line of a program looking like this:
10 N0=0:N1=1:N2=2:N3=3:N16=16:N100=100:N53248=53248The reason was that Atari BASIC would store every constant in a program as a float, which took about six bytes, even if the number was a really small integer. On the other hand, variable references used only one or two bytes. So large programs with big memory requirements would save memory with this trick. -- NickBensema
This trick was also used in Sinclair Basic on the Sinclair ZX81 (which was known as the Timex 1000 in some parts of the world). Because the machine only had 1Kb of memory as standard, it was common for the first two lines of any program to be:
10 LET O=PI-PI 20 LET I=PI/PIFloating point numbers were stored as five bytes, so this trick saved four bytes each time O or I was used. Also, the symbol PI only took up one byte (Sinclair BASIC was tokenised), so using PI-PI or PI/PI saved two more bytes in the initialization. --SpencerCollyer?
It could have been worse. Imagine if it was:
#define ONE 0 #define ZERO 1:-)
There is a product out there that defines ONE as 0, and TWO as 1 to provide handy constants for a function taking an integer parameter
I worked once on a program that had a section of code sort of like this (my C is a bit rusty, so forgive any errors...)
#if FALSE ... some code. #endWhen debugging a section of code, I introduced a change that would break the "some code" bit, which I didn't care about because I was going to remove it shortly. Imagine my surprise when the "some code" bit failed to compile. It turned out that, about 2000 lines above this particular code snippet, somebody had done the following:
#define FALSE TRUE
I saw that some years ago in a C program. -- Jeff Grigg -- The coder used it in may loops and was trying to save space. (Not that automatic variables on the stack really take up much space!) It was a disaster when you had nested loops... in different functions! >-P
There's a corporate database with a table that has two columns: KEY and VALUE
I find I'm continually fighting against programmers who don't see a problem with null-semantic names like "value" or "data" and even "variable", but I was somewhat saddened to encounter a body of code written by an ex-colleague where all the variable names were expletives or obscenities. "names don't matter, and it's a bit of a laugh" ... -- FrankCarver
Supposedly an old DEC C programming manual recommended writing this:
#define PI 3.14156in case you needed to change the ValueOfPi.
And if that's the value you were using for pi, you would need to change it!
(Yeah, yeah. :-) That was as much as I could remember at the time.)
I'll argue in favor of defining PI (but using a more accurate value ;-)
How about
const int MinutesPerHour = 60;This is good, not because the value is likely to change, but so as to reduce confusion with SecondsPerMinute (which is also 60). -- DaveHarris
Recently encountered this in a production program, used to compare date/time values without the bother of converting to Julian dates:
year*980294400 + month*2678400 + day*86400 + hrs*3600 + min*60 + secIt's not an example of BadVariableNames, but it is an example of Bad MagicNumbers: It works, but when I double-checked the numbers, I was surprised to find that they assumed 366 MONTHS in a year!
2678400 seconds/month = 31 days/month * 24 hours/day * 60 minutes/hour * 60 seconds/minute 980294400 "seconds/year" = 366 months/year * 2678400 seconds/monthI can live with 31 days per month -- a reasonable compromise to compute a value used for sorting. But 366 months per year??? That's just an error -- they clearly meant to do 366 days per year, but didn't get the numbers right.
A set of constants like this would have helped:
const SecondsPerMinute = 60; const MinutesPerHour = 60; const SecondsPerHour = SecondsPerMinute * MinutesPerHour; ...and so on, say with... const MaxDaysPerMonth = 31; ...-- JeffGrigg
I had a student once who named his variables after local radio stations. I always expected that I'd see the same program from another student with more meaningful names, but I didn't. Yeah, s/he was JustaStudent...
Someone I went to University with claimed he used the characters in AnimalFarm for variable names - in commercial code.
I once had to read code where the variable names were all names in Tolkien or Frank Herbert's Dune.
I also had a discussion with a colleague who objected to using i and j as indexes in loops etc. He preferred US for universal subscript. Otherwise he was a wise programmer. We were both working on the same program -- in COBOL -- and so I went along with US, US2, and so on.
A German student in England wrote a large FORTRAN program where every integer variable had a name that started: ZEIT (meaning "time" in english.)
Using obfuscated and / or arbitrary variable names like this is bad for code that is supposed to be useful, but I found it very liberating when learning to code that I could throw the names in without having to bother what each variable is used for. It increases your programmer capability. :)
I have a friend that recalls running across a particularly useless name in a basic program once. He chose to name his company after it. Visit him at http://q7.com. -- WardCunningham
See also: FunnyThingsSeenInSourceCodeAndDocumentation
A program I once worked on had two modes of operation for one algorithm - either it was "FooClipping", or it wasn't. So there was a global, called isFooClipping. If you were not FooClipping, one array needed to be one element longer. The allocation of said array ended up like this:
array = AllocateMemory(baseSize + isFooClipping)
Someone has "saved" code and time by reversing the sense of the global. So now we had a isFooClipping variable that's was TRUE (1) if you were not FooClipping!
-- PaulHudson
If and only if this is the least arcane solution, I routinely normalize integers in C (or even C++) as Boolean values (0 or 1) and use the Boolean value inside an integer expression. The correct way to do this is with the double-bang notation. For example, !!foo will normalize foo from 0 to 0 or non-zero to 1. Then I could use foo like "length = bar * !!foo;"--although "length = foo ? bar : 0;" is obviously clearer in this case. In the case of isFooClipping, a single bang would have been sufficient to invert and normalize the integral value. -- SunirShah?
How about mixed language names for variables? No, I don't mean Java/C++. Try English/Chinese:
const long ZHANYIZHOUQI = 1000; //1000 const long ZHANYIZHOUQI_WITH_NOZZLE_CHANGES = 100; // const int ENDING_SLOT_NUMBER_OF_FRONT_SIDE = 38; const int NOT_SHIELD = 0; const double PANZIGAILUU = 0.1;Anyone care to translate? -- ChrisBrooks
I have been writing some PythonLanguage programs for calculating sumo statistics. There just aren't useful English words for banzuke, sanyaku, heya, etc, but a sumo fan reading the code will know exactly what I mean. I think mixed languages are perfectly accesible in context. (For the record, a banzuke is a listing of ranks for wrestlers in a particular tournament, sanyaku translates as "three higher ranks" but means either the four highest ranks or the third and fourth highest ranks, and heya is usually translated as "stable" - it's essentially a wrestling club.) -- JohnFarrell
John, this isn't so much a case of using mixed languages, as using the domain language (in this case, sumo jargon) for variables. It's just a coincidence that the domain language consists of words from another natural language. --RobertWatkins
See Also: DontNameClassesObjectManagerHandlerOrData
(Technically a label, not a variable name, but they have the same syntax... ;-)
VbUnit does this in several places:
On Error GoTo Hell ... Hell: ' Error handling code.(I changed all the error handling code labels to have more meaningful names, for the benefit of my customer, where we're trying to get more RegressionTesting going.)
That's funny. Recently, a company that I used to work for "officially" banned the usage of "On Error Goto Hell" due to a similar circumstance. To be honest, labels in VB should *only* be used for error handling. Given that, if the only labels that exist are error handlers and if there is only one per method, then "Hell" is perfectly acceptable if used consistently (standardized). Since my production code is 100% c++ now, its not an issue. I still use it for my VB unit testing code though. It brings me a little joy....bkt
Sometimes constants like "ZERO", "ONE" and even "TWENTY_EIGHT" help to distinguish, for example, 28 from 28.0 or '28'.
For example, financial calculations in Smalltalk can be measurably affected by comparison tests such as
(aValue = 0) ifTrue: [].A trick I like is to replace this with
aValue ifZero: []where #ifZero: is appropriately implemented in the numeric generality system.
Question: When is 0 not Zero? Answer: When Zero is 0.0 or 0.00000 or '0 asDecimal'
Failure to test against the correct constant in a loop can force an unexpected coercion of aValue, significantly slowing the loop.
-- TomStambaugh
And then there's someone who declared "bool BooleanValue;" in several places in a C program, with no consistency of spelling or capitalization, and doesn't see why "tmp" might be a better name... I'm glad I don't have to maintain his code. --AlastairBridgewater
Try this one:
int temp = 0;AAARRRGGG!!!! ALL variables are temporary! The information content is ZERO (0) here!!!
I have to disagree: although temp/tmp/t *is* overused, inside small blocks it can concisely indicate that the variable is meant as scratch space.
In a past company, I encountered all three of the following:
BITS_PER_DEGREE = 72; FIVE_DEGREES = 325; /* (in BITS_PER_DEGREE) */And a little work with a calculator tells you that "FIVE_DEGREES" is really 4.513888... degrees.
[I guessed at the value for FIVE_DEGREES, from the text above. Please correct if I'm off. -- JeffGrigg]
If only it were so simple. I believe the conversion factor was 57.12-something-something bits per degree, for reasons that predated my time on the project and which now escape me.
* In this context, the magic number 57.xxx leaps out; conversion from radians to degrees: 360/(2*3.14159265) = 57.2958...
so the code would have read
FIVE_DEGREES .EQU 0101H or something similar
The conversion factors themselves never actually appeared in the code. They were written down in a several-year-old memo in a dusty ThreeRingBinder on the lead engineers' shelf. There was no point putting them in code - the 8088 assembler on the HP64000 development station had no preprocessing capabilities beyond simple (textual) macro substitution.
Why weren't the constants commented then? Well, the HP64000 assembler had problems dealing with input files larger than ??? bytes in size, and we were always close to those limits. Development environment limitations were just some of the many areas in which we pushed the limitations of the technology used on that project.
No variables, but bad class names. In java instead of using packages to partition code, the programmer used very long but abbreviated class names all in the same package, and failed to differentiate functionality. SelfSubAdmTermUser?, SelfSubAdmRevokeUser?, SelfSubAdmAddRole?, and a dozen others, all in the SelfSubAdm? package. There was also a SelfSub? package. I refactored into packages and renamed the classes to remove the leading SelfSubAdm? prefix and give them shorter but more meaningful names. In particular to clarify the difference between Term and Revoke (the former was expiring the user, the latter was purging it.) -- StevenNewton
From Patrick O'Brian's book "The Unknown Shore":
"Guns on the gun-deck," said the quartermaster, with intense relish. "He looked for to find 'em there; hor, hor."
"We only call it the gun-deck," explained Jack. "The guns are all on the upper-deck and quarter-deck, which is natural in a one-decker. The Wager is a one-decker, Toby."
"But there are at least four storeys, or decks, as you say in your jargon," cried Tobias, with some indignation.
"Ah," replied Jack at once, "we only call her a one-decker, you see."
No doubt because she has no guns on her gun-deck... -- TomStambaugh
I was trying to read through a program my boss wrote that calculated something. It kindof-sortof looked like a tree, except it didn't seem to have any branches.
The problem was that the program was actually manipulating a singly linked list, but the node record's "Next" pointer was named "Daughter"!
Not only does Daughter imply a hierarchy instead of a list, it would be more typing than using "Left" and "Right".
A linked list is a degenerate tree...
Granted, but in context the name obscured meaning.
The sheer laziness of people when naming variables is what disturbs me. "c" for "customer", "u" for user, etc. One of our ex-developers was a C-coder-turned-Java-wiz whose methods were typically 300 lines long and looked like C code. He also used some corrupt form of HungarianNotation (ugh), no doubt helpful since his methods were so ridiculously long. The last straw was when I came across the variable "sz"... zero terminated string in Hungarian, right? Nope:
int sz = list.size();Apparenly typing two more letters would have killed the guy.
I worked at a job where the GLOBALS!!!! were given one or two letter names in a 20,000 line program. No IDE, just use an editor. Oh yes -- printer variables often contained the vowel removed pnt or ptr. Never mind what pointers were called. Very frustrating.
I just found this in a beginners tutorial for LingoScriptingLanguage (http://brennan.young.net/Edu/Lingvad.html):
For clarity I have called the local variable myV, but you could call it pizza or fireman if you liked.
I think most of the myValue or aString variable names come from tutorials and similar how-to books. In the book, the code has no real purpose, so the variable names are irrelevant. -- OleAndersen
The myV-example is part of a small (but complete) game, intended to show the benefits of using OO.
Brennan Young (author of the aforementioned lingo tutorial) adds: Out of context it looks as though I am recommending the use of 'pizza' or 'fireman', which is actually the opposite of what I am suggesting. In addition, 'me' in lingo is similar to Java's 'this', so use of the pronouns 'me' and 'my' in Lingo variables (and indeed in Applescript and other related languages) almost exclusively refers to the instance and not the programmer.
See UnderscoreVersusCapitalAndLowerCaseVariableNaming.
/* important global variables */ unsigned int x; unsigned int xx; unsigned int y; unsigned int yy;The only other comment in the entire system's code was /* Oooh, neat trick */.
The story goes about a customer complaining about a 'obvious' compiler error. The customer handed the code in, so the compilerguys could test it out. all variables where called i, ii, iii and so on! After days of variable renaming, they found a place where one of the is was missing. I only hope the customer had to pay for the time spent hunting his bug.
On an old VB project, I had asked the other programmer to be sure to use long descriptive variable and control names. This was to make sure he didn't use extremely short variable names (like 'x'), which was the 'standard' in our shop at the time. The form he was working on was quite complicated, but instead of using the names to simplify the form, he ended up using names like lblFraOptFrmAssumptionsTabGrpPrbTabTttL2d and lblOptFraOptFrmAssumptionsTabGrpPrbTabSymMra.
I have a friend who likes to use variable names that have a string length that is a power of 2. They rarely go beyond 8 letters, though.
http://opensource.lineo.com/cgi-bin/cvsweb/pm/MP3/Daemon/bin/pimp?rev=1.1&content-type=text/x-cvsweb-markupdisclaimer: This is not a reflection of the code written at Lineo. My friend has not ever worked for Lineo. If you look at the other code for MP3::Daemon, it's rather sane compared to pimp. -- JohnBeppu
Seen recently in a C module:
#define AND |I have seen this too. The explanation from the programmer was that they got confused by building a bitmask with the | operator, like
FileAccessMask = O_READ | O_WRITE | O_BINARY ;They thought that it would be less confusing to write:
FileAccessMask = O_READ AND O_WRITE AND O_BINARY ;I could not convince them that defining OR as AND was potentially a lot more confusing, and they would be better off getting used to the idiom of building bitmasks with |. I have also often seen people use:
FileAccessMask = O_READ + O_WRITE + O_BINARY ;This works fine as long as each symbol represents a discrete bit, but often leads to errors when combined masks are used:
NORMAL_ACCESS = O_READ ;Windows has a lot of predefined combined masks, so wheras a UNIX programmer may get away with this idiom, in Windows you will get caught out eventually.FileAccessMask = NORMAL_ACCESS + O_READ + O_WRITE + O_BINARY ; //wrong!
FileAccessMask = NORMAL_ACCESS | O_READ | O_WRITE | O_BINARY ; //OK!
My buddy's company was in partnership with Microsoft. In fact almost all their funding was coming from MS. They were writing a video game, but having a lot of trouble with the recently released DirectX. They were getting ready for a demo at a big game convention and the last thing they had to do was an installer. The wrote it the night before the convention. (cue ominous music) and then flew out there with the install CD.
So the convention starts and my buddy's game is the center piece of the Microsoft booth. Their game is supposed to be running on a giant 16 foot screen over the booth.
So they try to install it on the Microsoft booth machines and....it does not work.
The company owner is there. The Microsoft VP in charge of the project is there. Crowds are now entering the convention hall. The Microsoft tech guys running the booth are helping trouble shoot. They think maybe its the drivers, maybe it is the version of the OS. no. no. They open the registry with regedit. Sure enough there was the problem. The variable BILL_GATES_IS_AN_******* was incorrectly defined by the install program.
Right on the 16 foot screen in regedit.
Microsoft was not amused.
When I started working at my present company in April 2000, one of my first tasks was to take over the maintenance of an ancient Java applet that performed financial calculations, updating a pie graph and other goodies in response to user input. The applet consisted in principle of two classes, one of which painted the GUI, the other performed the financial calculations. The painting class had countless instance variables with names like x13, x37, y4, y15. The various components of the applet were positioned according to these variables, the values of which were constantly changing. It took me hours to figure out which variables were connected to which components. Making it worse was the fact that some of the variables weren't ever used!
I was glad when we dropped that applet a few months later! -- JohnWebber
(ancient Java applet? What would you call 15 year old C code I have to maintain???)
On a related note, I recently had to fix some bugs in some legacy Java code that was notorious for scattered and interconnected sections of code that were never used. It was the definition of SpaghettiCode. There was no way I would have been able to make the fixes without first wasting a lot of time trying to understand the code. I used a my favourite Java IDE (in my case IntellijIdea) which was great at finding unused methods and variables, as well as doing automated refactorings (such as changing bad names and removing unused parameters from method signatures). What a life-saver. It only took a couple of days to clean up the code and then making the fixes was pretty straightforward.
I worked on a COBOL program that manipulated a date from mm/dd/yyyy to yy/mm/dd and yyddd and several other formats. The variable names were DATE, DAYT, DAIT, DEIGHT ...
For a while I worked at a company using BorlandDelphi. One of the programmers would never rename components created by the VCL. In one form, he had variables for checkbox1, checkbox2, ... checkbox28.
At another company I worked for, one of the previous employees had a habit of naming his nouns after places and people. So you'd have variables like texas, newyork, ... Then he'd name the method names stuff like "sucks" so the code would read "texas.sucks()"
It was a great.
Another story: String str1 = "ACCOUNT"; String str2 = "USER"; String str3 = "AMOUNT"; .... String str18 = "ITEMS"; String value; value = getFromDB(str0); callMethod(value); value = getFromDB(str1); callMethod(value); .... value = getFromDB(str18); callMethod(value);str0 to str18 are used only once. -- AndreasSchweikardt
That looks a bit like something that certain automated tools for i18n or string externalization would generate.
On the other hand, things can go to far.... The system headers for VxworksOs? contain (or contained; maybe newer versions of vxWorks have fixed the following bit of BrainDeath?) the following macro definitions for boolean values (this is C code):
#define TRUE 1 #define FALSE 0Nothing unusual or nasty about that. However, when our application #included another header, which did the following (which is less acceptable; it was from a locally-developed PinkyAndTheBrain library):
typedef int Bool; #ifdef FALSE # undef FALSE #endif #define FALSE ((Bool)0) #ifdef TRUE # undef TRUE #endif #define TRUE ((Bool)(!FALSE))or something like that. When we built our app, though, all hell broke loose. As it turned out, not because any incompatibility between the two definitions of TRUE and FALSE, which happened to be true (!0 is equal to 1 in our environment, though C doesn't guarantee that in general). The same header files from WindRiverSystems also featured this nonsense, to conditionally include/exclude code.
#if FALSE /* excluded code */ #endifWith FALSE redefinied to be the text "((Bool)0)", this caused the preprocessor to puke.
The lessons learned:
This page mirrored in WikiPagesAboutRefactoring as of July 17, 2004