Always, always, always use good, unabbreviated, correctly-spelled meaningful names.
Rationale
It's clearer, easier to read. Avoids local idioms in the language by using the language itself. You aren't forced to remember the exact spelling of a symbol because you always know it is spelt correctly and thus consistently. It's also easier to search for with an editor's search function - try searching or grepping for all occurrences of the variable "i" within a function, without also picking up every instance of "void", "int", "printf", etc. You can do it with
RegularExpressions, but not all editors have regex searches.
A
MeaningfulName gives you the ability to understand code two years after it is written.
Unless you are using Fortran or an archaic C compiler and have to worry about the six-character limit on external symbols, there is no reason to use abbreviations.
Disambiguation: See also a paper by the same name at
http://tottinge.blogsome.com/meaningfulnames/
Arguments
"This is a mere platitude"
The rule does not help me choose between reasonable alternatives, it only tells me not to write bad, abbreviated, incorrectly-spelled meaningless names. Apart from the abbreviated or not question, why would I choose to do the other?
"I don't like typing that much!"
You're really just admitting that you don't know how to type, which is really not acceptable these days. Good editors help. Copy and paste if you have to. It's not really that much to do. Typically, in a narrow system, a given symbol won't be referenced more than 20 times anyway.
"It's difficult to come up with meaningful names!"
Agreed. Anonymous functions are nice but aren't always available. Perhaps you can use something more generic, or maybe you can scope a name. Usually, though, if you can't come up with a good name for a thing, you probably don't have a good idea what the thing is supposed to do.
Disagree. If you have a good understanding of the problem domain, producing meaningful names becomes easy.
"Our simple, meaningful names tend to collide with third parties."
Use namespaces, scoped names, name mangling, or a large club to beat them with.
"I speak not good English and nobody in the my team does good. So we call method like getChilds() and getConcreteHead()"
"Short names make it easier to see the overall pattern of what is going on!"
Long names LoseSignalInNoise
?.
(Being discussed below.)
Exceptions
Common mathematical functions like min, max, sin, cos, abs; although mathematics is a horror story in itself.
This is just a special case of another rule: Use term from the domain where appropriate. If your customer understands what an ni_rim is, use that.
CASE-tool generated muck like CFooApp and CFooDlg by the
AppWizard (note it's not called Application
Wizard).
Name mangling prefixes, but those really aren't part of the name, are they?
RelationalDatabaseFieldNames can benefit from some selective abbreviation.
- They can? Does it make the queries run faster?
Examples
"Sch" does not mean "Schedule". It means someone was too lazy to type the extra five characters and that probably means the rest of the code is equally as lax.
It is contentious whether or not "i" is the same as "count". "count" is probably just as bad as "i". "iStringPosition" may be better, but symbols that long tend to
decrease readability of string parsing algorithms and simple iterations.
- Count can have a domain-specific meaning whereas "i" is meaningful across all domains. You know it is always the index inside a for loop. Since it cannot have any real meaning, assigning it any name would detract and take an extra step of information processing to the code reader.
On the other hand, functional programming (C++'s STL supports this, although STL isn't necessarily supported by your compiler yet), removes even this case.
NomenEstOmen
is Latin for "the name says it all" or maybe "take the name as a sign"
My english is too bad for coining a good phrase here --
DierkKoenig
For OO programming that means that a class "Manager" is likely to not doing something productive.
See:
DoesWhatItSaysOnTheTin,
RonsealPattern
But
Abbreviations are used everywhere, even by those that argue for unabbreviated names. It is then said that they come from mathematics (like "Max") or are acronyms (like "Url"). But the real reason we accept these abbreviations, is that programmers are used to them and don't misunderstand them. So it is (like all language) a matter of habits.
Abbreviations are bad, but much better than omitting information totally. So a function "copy" (unabbreviated word) is unacceptable compared to "F
ileCpyUrl" (abbreviated words). Omitting a word should be considered identical to abbreviating it to length zero.
See also:
LanguageOrientedProgramming,
ThelopLanguage,
ThelopDictionary
--
HelmutLeitner
"F
ileCpyUrl" is still a
terrible name, hardly better than "copy" at all. Does it copy data from a file to a URL, or copy data from a URL into a local file? And why "Cpy" not "Copy". Is
one character going to make that much difference?
Examples of
MeaningfulNames are:
- AccountNumber
- SpeedOfLight
- Radius
Some not so meaningful names for the above would be:
- ActNo - Activity Number, Account Number?
- C - The programming language, a well known constant?
- R - Rate of Return, Radius?
--Kris Wenzel
In practice I have found that FullySpellingOutAllWordsInCompoundVariableNames
? can easily lead to excessively long names, such that even simple expressions, like "x = y + 1" won't fit in an 80-character line (after a few 4-character indents).
Yes, refactoring things into micro-modules helps, but (to some extent) it trades one form of complexity for another.
--
JeffGrigg
Excessively long lines are a CodeSmell. Assign state to variables in such a way that the contents of each variable may be described more succinctly.
The principle here should be that the length of a name must vary proportionately to its scope. I don't think that "i" is so bad in a list comp, or a loop counter inside a small method, but it is entirely wrong for a parameter name of a public function (or a private one, for that matter). Perhaps this is a matter of "dealing with a matter where the matter matters". I tend to use better variable names outside of list comps, where they can be seen, but in an anonymous or inner-nested function it is sometimes of little consequence.
That being said, long lines are a code smell as are confusing names.
--
TimOttinger
Meaningful to whom?
activateModem, initializeModem, makeModemReadyForUse, prepareModem, modemPrep, setupModem, setInitialModemState, executeModemPreparationSequence, ad nauseum ... none of these says more to me than modemInit.
The programmer making up the names may see things through very different eyes from those of the later programmers. Passive voice as opposed to active voice. Odd choices of adjectives.
And when one of the guys is from Thailand and creates function names like settingAllModemInsideRegisterForBeginValue and variables like wasStatusForToDialFinal (and, really, I'm not doing him justice -- some of his names were truly breathtaking) you can become a poster child for asprin.
Wait, wait, it gets better ... how about module name prefixing: customerModuleRetrieveFirstFitSpaceRecordSet among a set of functions that all begin with customerModuleRetrieve ... oh, man. You know, I was okay until I started to recall that nightmare. Andy, wherever you are, I hope you've opened a restaurant or something.
Keep names short. Code to a convention. Yes, make them meaningful. No, dontTryToWriteWholeSentencesWithYourStinkingFunctionName!
Let's make an exception to that rule for testing. TestThatTheParserDealsWithExtraneousLeadingWhitespace?() is not a problem. It's a solution. --
TimOttinger
I wonder if the tendency for South Asian cultures to have long names (both in individual parts and number of parts) was part of this Thai programmers motivation? Probably.
CulturalAssumptions have a huge effect on name choices. Grammar probably also plays a large part; Thai does not have a rich, specific vocabulary for technical concepts. As a result, it tends (like German) to use a lot of highly verbose language to describe fairly commonplace technical things. Since culture plays such a huge part in such tendencies, it can be extremely difficult for programmers to conform to a Western/American methodology.
But it's statistically shown that using longer names leads to shorter debugging times, according to
201 Principles of Software Design. --
SteveWainstead
The longer the better? How about 10,000 character names, then? No? Then diminishing returns is at work, and there is some optimal peak to the curve.
Principles
How about some principles?
- Use complete names where an object is referenced from more than one place.
- Abbreviate for local scope only (eg Enumeration e = getEnumeration())
- Add the pattern name into the object noun-name (eg imageFactory, networkFacade)
I find this an anti-pattern. The pattern name is an implementation attribute. If I want to invoke, from a consumer, a method on the client-side proxy of the service, I want to invoke the methods of something like "Registry", "RegistryService", etc. If I decide to change the client-side implementation from a Facade to an Adapter or an Interface, I do not want to be forced to change client code. I would therefore offer a different principle:
3 Choose a name that describes WHAT the object does, not how it does it.
-- TomStambaugh
Pattern names are becoming increasingly meaningless as the march of time, money and academic repute progress. I wouldn't mandate their use in naming. Besides, WindowComposite seems excessive.
I find that if I'm struggling to name something (be it local variable, object, pattern, ...) it is a sure sign I don't
really understand what's going on.
I also tend to think that bad names help to highlight areas where the
CodeSmells.
NonMeaningfulNames
? can also be a sign of OverAbstraction
?, or the fact that you, the reader, aren't literate in the program's
ProblemDomain.
I would add checking a prospective employee's naming conventions to the
GuerrillaGuideToInterviewing as an easy way to immediately flag someone as a
NoHire.
--
DanGreen
I added "but short names make it easier to see the pattern of what is going on."
I have a general rule: The more frequently a name is used, the shorter it should be.
Codified in CodeComplete, by the way -- JeffBay
"index" is so common, and frequently so semantically unimportant, it can be abbreviated to "i" and make code easier to read.
for(int i=0;i<SOME_LIMIT;i++)
doSomethingImportant(withThis[i]);
Notice that the focus of this expression is on SOME_LIMIT, do_something_important, and with_this.
By increasing the length of "i", it starts to occupy much more cognitive space:
for(int index=0;index<SOME_LIMIT;index++)
doSomethingImportant(withThis[index]);
SOME_LIMIT is almost invisible. I don't want to think about indexes; I want to think about SOME_LIMIT, and doSomethingImportant, and withThis.
Frequently, I'll make a pointer to something with a very long name, because I'm using it a lot in a block of code. That's the right thing to do, in that situation.
--
LionKimbro
I'd argue that typing anything short of index is wrong. For one, index is important, it tells you it's not count, i.e. it starts at 0 rather than 1 and this prevents common fencepost errors. It also reads better; read it out loud and you'll see; words are better than letters. The world isn't running out of words, don't abbreviate, it only adds to the confusion. --
RamonLeon
Of course it's not a count. If it was a count, it would be "n", not "i". My naming convention for short temporary names:
- a through f - floating point values
- g and h - haven't used those much
- i through k - indices
- l - looks too much like "1"
- m and n - counts
- o - looks too much like "0"
- p through s - pointers
- t - temporary of appropriate type
- u through z - integer or float as needed (usually in graphics code)
--
StefanVorkoetter.
It reads much better with i than index. i=0 gives a pretty clear indication that it starts at 0.
Hardly, "i" could mean anything, depending on context, "index" means "index", look at that, the power of language. Use words, not abbreviations. Abbreviations are bad form, and always make things difficult for the maintenance programmer later.
The operational phrase here is "depending on context". In the context of a loop, i means index.
[Using "i" for a simple loop index in C/C++ and several other languages is an extremely common language idiom, and as such is well-established to be actually preferred over e.g. "index", even though longer names are indeed
generally preferable. Learn and use the idioms of the language at hand; departure from the common idioms often flags a mistake, and at best, distracts maintainers of the code.]
If the maintenance programmer has difficulty with that "i" in there later on, there's something
seriously f**ked up with that maintenance programmer. They should
not be maintaining programs.
If that "i" confuses you, and you are a programmer, then I am amazed.
The popular comic Foxtrot actually put code in a panel. It's pseudo-codish, but it's still funny to the average reader since browser_type is much more meaningful than m_strBt. Bearing in mind that Foxtrot is not just a webcomic, but syndicated in several newspapers, I suggest the following idea "Write code as if 60 year old aunties were going to read it in the sunday papers."

[
BrokenLink]
Please don't do that. You've fallen into the COBOL error of trying to write in English. Instead, write code as if it were a
MessageInaBottle to the maintenance programmer who will come after you. --
DavidConrad
One module I had to call into had a function that returned the raw, unprocessed count from an analog-to-digital converter. The function was named
rawanal.
When Ken Thompson and Dennis Ritchie received the 1983 Turing Award, after their respective acceptance speeches, someone in the audience asked Ken what he would do differently with Unix if he were to do it all over again. He said, "I'd spell 'creat' with an 'e'."
- ("creat" is the Unix system call to create a new file. Unix was originally developed on a 16K byte minicomputer, using 110 bit/second Teletypes that required a foot-pound of pressure to press a key on the keyboard, which gave multiple incentives to use highly abbreviated names for everything, such as "ls" instead of "list", "cp" instead of "copy" -- but even so, it was widely considered absurd to leave out just the "e" in "creat", so it was funny for him to acknowledge that.)
Here's another instance where the symbols are far clearer than the words.
First, with descriptive words:
// iterators
HKEY profiles_key;
int profiles_index;
HKEY single_profile_key;
int single_profile_index;
HKEY long_number_key;
int long_number_index;
HKEY numbered_account_key;
profiles_key = open_registry_key(HKEY_CURRENT_USER, profiles_keyname);
if (profiles_key == NULL)
return false;
for (profiles_index = 0;
(single_profile_key = enum_registry_subkey(profiles_key, profiles_index)) != NULL;
profiles_index++)
for (single_profile_index = 0;
(long_number_key = enum_registry_subkey(single_profile_key, single_profile_index)) != NULL;
single_profile_index++)
for (long_number_index = 0;
(numbered_account_key = enum_registry_subkey(long_number_key, long_number_index)) != NULL;
long_number_index++) {
output_registry_values(numbered_account_key);
found_one = true;
}
You can see that it's hard to tell just what's going on, for all the word-mass.
It's also hard to tell if it's correct. That's because your eye has to read across full strings, and the mind has to fill it's short term memory with many syllables, in order to perform comparison properly.
Now again, with symbols:
// iterators
HKEY L1_key; // the profiles directory ("Profiles")
int L1_index;
HKEY L2_key; // single profiles (ex: "Profiles\le", "Profiles\Outlook", "Profiles\lion")
int L2_index;
HKEY L3_key; // looooong numbers (ex: "Profiles\le\13dbb0c8aa05101a9bb000aa002fc45a")
int L3_index;
HKEY L4_key; // accounts (ex: "Profiles\le\9375CFF0413111d3B88A00104B2A6676\00000001")
L1_key = open_registry_key(HKEY_CURRENT_USER, L1_keyname);
if (L1_key == NULL)
return false;
for (L1_index = 0;
(L2_key = enum_registry_subkey(L1_key, L1_index)) != NULL;
L1_index++)
for (L2_index = 0;
(L3_key = enum_registry_subkey(L2_key, L2_index)) != NULL;
L2_index++)
for (L3_index = 0;
(L4_key = enum_registry_subkey(L3_key, L3_index)) != NULL;
L3_index++) {
output_registry_values(L4_key);
found_one = true;
}
Much easier this time, and much easier to verify that it's correct: You can glance and check that numbers fit the pattern appropriately.
This is another instance where using short symbols, rather than meaningful words, gets the idea across more economically, and makes it easier to debug.
Not to this reader. The bodies of those for loops should be extracted to their own methods (each with meaningful names) and the variables scoped accordingly. -- EricHodges
KarlKnechtel would do it by recursion. Assuming C++ (as 'true' and 'false' suggest), something like:
// Strings together depth + 2 registry-key-path components
// (since at depth == 0, the start_key is combined with the immediate subkeys)
bool get_registry_values_rec(HKEY start_key, int depth) {
bool result = false;
if (start_key) { // this check could go in the wrapper instead, but
// it feels safer here - it documents a precondition, sort of
int index = 0;
HKEY next_key;
while ((next_key = enum_registry_subkey(start_key, index++))) {
if (depth) {
// Recurse
result ||= get_registry_values_rec(next_key, depth - 1);
} else {
output_registry_values(next_key);
result = true;
}
}
}
return result;
}
// We need 4 components, so we need a recursion depth of 4 - 2 == 2
bool get_registry_values(const char* keyname) { // assuming that type...
return get_registry_values_rec(open_registry_key(HKEY_CURRENT_USER, L1_keyname), 2);
}
where "rec" is conventionally short for 'recursive'. This kind of abbreviation should matter little because (a) the recursive function is a helper that is not part of the public interface; (b) it's only called into in one place, i.e. the immediate next function (beyond that, it only recurses).
''The problem in the first example "profiles_index" isn't as much the naming as the primitive obsession and the paired variables that are unpaired here. You have a kind of
tuple madness going on here. You can rename the variables to make them look wrong where they're wrong, but the problem remains. --
TimOttinger""
From MeaningfulVariable:
Consider the example:
for ( int i = 0; i < 10; i++ ) {
printf( "%d ", i );
}
Here, it's not too difficult to see what
i
does What if
i were in the middle of a large chunk of code?
Using a
MeaningfulName for each variable will go a long way to enhancing the readability of code. The occasional
MeaningfulComment is nice, too. And so is the avoidance of large chunks of code.
On the other hand, we're not indexing an array. It appears that we're printing the digits zero through nine: "0 1 2 3 4 5 6 7 8 9 " So would it be better to say...
for ( int digit = 0; digit < 10; ++digit ) {
printf( "%d ", digit );
}
i is a meaningful variable name. It is the name of a loop index, probably
because you are iterating over an array. When it is used that way, I never
have any problems with it.
If you have a large chunk of code then you have other problems. You need a
ComposedMethod. Loop bodies should never be more than a few lines long, and
so a loop index should never be part of a large chunk of code.
There are a few single letter variable names with well understood meanings across a wide variety of programming languages. These are ...
- i, j, k -- indices, k varies fastest.
- x, y, z -- coordinates
- p, q, r -- pointers
- t -- time, t0 starting time
Since these meanings are generic, one must be able to quickly find the variable's definition to understand to which index, coordinate, pointer or time the variable refers. They should only be used within small scopes, and within such scopes they are preferred over longer names.
-
- Why are the short names preferred? Especially in a 3 dimensional array, I would prefer to see something like iTable, iRow, and iColumn rather than try to figure out the correlation to i, j, and k.
-
- Long names can add noise and make things harder to read. For example, some find it much easier to read the i form of the loop at the top of the page than the digit form. It would be even worse if someone chose the name nextDigitToPrint or such. But it is true that if one has multiple variables within a scope, then descriptive names help to tell them apart.
Even these single letter names are rarely used in Smalltalk because most indices, coordinates, pointers and times are encapsulated within higher level abstractions.
There is also the argument from
EgolessProgramming,
which says that we should eschew possessive variable names like
i
in favor of the more inclusive
we
or
us.
--
DaveSmith
- If i were to have semantic meaning in code, would it not represent the current scope of the current process thread? I wonder if we or us would consequently mean the current thread's state all the way back up the stack? --PeterLynch
Sorry, I don't have the time to read all this now... A presentation should be structured towards the intended audience, but this is sometimes underestimated. Language, vocabulary, jargon, definitions, abbreviations and symbols depend on the topic discussed. --
GeraldLindsly
See
SystemOfNames,
BadVariableNames,
RoleSuggestingVariable,
ComplementaryNames,
UnderscoreVersusCapitalAndLowerCaseVariableNaming,
GoodVariableNames,
UsingGoodNamingToDetectBadCode,
RonsealPattern,
MethodsWithNounNames,
SelfDocumentingCode,
AreLongAndDescriptiveRelated,
AbbreviationsAreEvil.
CategoryCodingIssues CategoryNaming