Any fool can write code that a computer can understand. Good
programmers write code that humans can understand. Martin Fowler,
2008.
People are afraid of renaming things for fear that some other
developers will object. But we should be grateful when names
change(for the better). As we most of the time don't remember the
names and relay on our IDE to deal with the details like that, we
can focus on whether the code reads like paragraphs and sentences,
or at least like tables and data structures.
The programmers goal as an author is using the popular paper
back model whereby the author is responsible for making himself
clear and not the academic model where it is the scholar's job to
dig the meaning out of the paper. Therefore here we will discuss
some of the rules of naming as naming convention or standards.
Better naming helps the reader to understand the code better
without needing to read other documents or comments!
This naming convention is collected from a number of
sources, individual experience, local requirements/needs, as well
as suggestions given in the references. Main reason for introducing
a new guideline rather that just referring to those one is
reviewing the existing style and using the new IDEs features to
make code readability the most. Each recommendation is numbered to
make it easier to refer to during code reviews.
Using Intention-Revealing Names
If a name requires a comment, then the name does not reveal the
intent. The name of a variable, function or class, should
answer all the big questions. It should tell us why it exists, what
it does, and how it is used.
int d; //elapsed time in days
should be written as :
int elapsedTimeInDay;
Avoid Disinformation
- Don't refer to a group of accounts as an accountList
unless it's actually a List. The word List means
something specific to programmers. If the container holding the
accounts is not actually a List, it may lead to a false
conclusions. accountGroup, bunchOfAccounts or
just the accounts would be better. ( Even if the container
is a list , it's probability better not to encode the container
type into the names.)
- Just use similar names for similar concepts So with the helps
of code completion in IDE similar concepts sort together
alphabetically for the name and avoid using names that vary very
small in different concepts, like using
XYZControllerForEfficientHandlingOfString in one module
and XYZControllerForEfficientStorageOfStrings somewhere else!
- Don't use the lower case L or Uppercase O as variable
names:
int a=l;
if(O==l)
{
a=O1;
}
else
{
l=01;
}
Make Meaningful Distinctions
- Don't change one name in an arbitrary way or misspelling it
because you can not use that name(because it is a keyword) or you
already used the same name in that scope for another variable. e.x
using klass just because class is a keyword.
number series (a1, a2, a3,...) are disimformative (non
informative)
- Don't add Noise words to your variable names. for example
having a Product class and making new classes with the name
ProductData or ProductInfo that has difference in shape but no
difference in meaning because Data and Info are noise words. Other
examples are the word variable(should never appear in variable
names), table (should never appear in table names). Likewise
moneyAmount and money, customerInfo and customer, accountData and
account, theMessage and message are not distinguishable(without
having a documented convention) and should be avoided.
Use pronounceable Names
- If you can not pronounce it you can not discuss it without
sounding like an idiot!
private Date genymdhms;
is a bad name for generation date, year, month, day, hour,minute
and second. it could be :
private Date generationTimestamp;
Use Searchable Names
- Single letter names and numeric constants are not easy to
locate across a body of text.
- Single letter names can Only be used as local variables inside
short methods. The length of a name should correspond to the size
of its scope. If a variable or constant might be seen or used in
multiple places in a body of code, it is imperative to give it a
search friendly name. ex if we use constant 5 as work days in week
and it should be used in code it is better to name it
WORK_DAYS_PER_WEEK instead of using 5 everywhere in code.
- Variables with a large scope should have long names;
variables with a small scope can have short names. Scratch
variables used for temporary storage or indices are best kept
short. A programmer reading such variables should be able to assume
that its value is not used outside a few lines of code. Common
scratch variables for integers are i, j, k, m, n and for characters
c and d.
Avoid Encoding
- Hungarian Notation (HN) was considered to be
pretty important in the Windows C API when everything was an
Integer handle or a long pointer or a void pointer or one of
several implementations of string. The compiler did not check types
in those days, so the programmers needed a crunch to help them
remember types. Nowadays we have richer type systems and the
compilers remember and enforce the types. so using HN or other
types of encoding are simply impediments. They make it hard to
change the name or type of a variable, function or class. They make
it harder to read the code. And they create the possibility that
the encoding system mislead the reader.
PhoneNumber phoneString; //Name not changed when type
changed!
Member Prefixes
private String m_dsc;
IDEs highlights or colorized members to make them distinct. So
the prefixes become unseen clutter and marker of older code.
Interfaces and Implementations
Sometimes you have an interface that should be implemented by a
concrete class. for example IShapeFactory and ShapeFactory. One of
the best practices is to encode the implementation and leaving the
interface name be the meaningful name without I. Calling it
ShapeFactoryImpl or even the CShapeFactory is preferable to
encoding the interface as IShapeFactory. It makes that the users
will not know that is handling with an Interface.
Avoid Mental Mapping
Readers should not have to mentally translate your names into
other names they already know. Single letter names is a poor
choice; it's a place holder that reader must mentally map the
actual concept. There can be no worse reason for using the name c
because a and b were already taken. Single letter names are
traditional for loop counters. it may be named i,j or k(but never
l) if its scope is very small and no other names can conflict with
it.
Class Names
classes and objects should have noun or noun phrase names like
Customer, Account and AddressParser. Avoid words like Manager,
Processor, Data or Info in the name of a class. A class should not
be a verb.
- Names representing types must be nouns and written in
mixed case starting with upper case.
- Line, AudioSystem
Variable Names
Variable names must be in mixed case starting with lower
case.
line, audioSystem
Makes variables easy to distinguish from types, and effectively
resolves potential naming collision as in the declaration
line;
Method Names
- Methods should have verb or verb phrase names like postPayment,
deletePage or save. Accessiors, mutators and predicates should be
named for their value and prefixed with get, set and is.
string name = eployee.getName();
customer.setName("mike");
if(paycheck.isPosted())...
- when constructors are overloaded, its better to use static
factory methods with names that describe the arguments.
complex fulcrumPoint=Complex.FromRealNumber(23.0) is better
than
complex fulcrumPoint=New Complex(23.0)
enforcing their use by making the corresponding constructor
private.
- use short names for public methods seen from outside and large
names for private internal methods.(the opposite rule for variable
naming: short names for short scope and large name for larger
scopes)
Names representing methods must be verbs and written in
mixed case starting with lower case.
getName() , computeTotalWidth()
. This is identical to variable names, but methods in Java are
already
distinguishable from variables by their specific form.
- The terms get/set must be used where an attribute is accessed
directly.
employee.getName();
employee.setName(name);
matrix.getElement(2, 4);
matrix.setElement(2, 4, value);
- Is prefix should be used for Boolean variables and
methods.
isSet, isVisible, isFinished, isFound, isOpen
Using the is prefix solves a common problem of choosing bad
Boolean names like status or flag.
isStatus or isFlag simply doesn't fit, and the programmer is
forced to choose more meaningful names. Setter methods for
boolean variables must have set prefix as in:
void setFound(boolean isFound);
There are a few alternatives to the is prefix that fits better
in some situations. These are has, can and should
prefixes:
boolean hasLicense();
boolean canEvaluate();
boolean shouldAbort = false;
Don't be Cute
Do't tel little culture dependent jokes for naming
functions. Say what you mean. Mean what you say.
Pick One Word per Concept
Pick one word for one abstract concept and stick with it. it's
confusing to have fetch, retrieve and get as equivalent methods of
different classes. Also its confusing to have a controller, manager
and driver in the same code base using fr the same type of object.
what is the essential difference between a DeviceManager and a
ProtocolController
The name lead you to expect two objects that have very different
type as well as having different classes.
A consistent lexicon is a great boon to the programmers who must
use your code.
- The term compute can be used in methods where something is
computed.
valueSet.computeAverage();
matrix.computeInverse();
Give the reader the immediate clue that this is a potential time
consuming operation, and if used repeatedly, he might consider
caching the result. Consistent use of the term enhances
readability.
- The term find can be used in methods where something is looked
up.
vertex.findNearestVertex();
matrix.findSmallestElement();
node.findShortestPath(Node destinationNode);
Give the reader the immediate clue that this is a simple look up
method with a minimum of computations involved. Consistent use of
the term enhances readability.
- The term initialize can be used where an object or a
concept is established.
printer.initializeFontSet();
The American initialize should be preferred over the English
initialize. Abbreviation init must be avoided.
- Complement names must be used for complement
entities.
get/set, add/remove, create/destroy, start/stop,
insert/delete,
increment/decrement, old/new, begin/end, first/last, up/down,
min/max, next/previous,
old/new, open/close, show/hide, suspend/resume, etc.
Reduce complexity by symmetry.
Don't Pun
Avoid using the same word for two purposes. Using the same term
for two different ideas is essentially a pun.
For example when in a context the method add is used for
creating a new value by adding or concatenating two existing values
using the name add for a method that puts a value in a collection
is a pun. its better to name it insert or append in this
context.
Use Solution Domain Names
Use computer science terms, algorithm names, pattern names, math
terms, so forth. don't draw every name from the problem domain,
that makes coworkers to run back and forth to the customer asking
what every name means. AccountVisitor or JobQueue are good names
that have a great deal to the programmers who know the visitor
pattern or the Queue concepts.
Use Problem Domain Names
When there is no programmer-eese for what you are doing choose
the name from the problem domain. At least the programmer who
maintain the code can ask a domain expert what is it! Separating
solution domain and problem domain concepts is part of the job of a
good programmer or designer. The code that has more to do with
problem domain concepts should have names drawn from the problem
domain.
Add meaningful context
Imagine you have variables name firstName, lastName, street,
houseNumber, city, state and zipcode. Taken together it is pretty
clear that they form an address. But if you just saw a state
variable being used alone in a method? You can add context using
prefixes: addrFirstName,addrLastName,addrState. At least readers
will understand tht these variables are part of a larger structure.
Of course a better solution is to create a class named
Address. Then even the compiler knows that the variables belong to
a bigger concept.
Exception classes should be suffixed with Exception.
class AccessException extends Exception
{
// :
}
Don't add Gratuitous Context
In an application context with the abbreviation GSD is a bad
idea to prefix every class with GSD. When typing G and pressing the
code completion key in IDE you are rewarded with a mile long list
of every class in the system.
Shorter names are better than larger ones, so long as they are
clear. Add no more context to a name than is necessary.
The name of the object is implicit, and should be avoided in a
method name.
line.getLength(); // NOT:
line.getLineLength();
The latter might seem natural in the class declaration, but
proves superfluous in use, as shown in the example.
Names representing packages should be in all lower
case.
mypackage
com.company.applicatio.ui
The initial package name representing the domain name must be in
lower case.
Names representing constants (final variables) must be all
uppercase using underscore to separate words.
MAX_ITERATIONS, COLOR_RED
Abbreviations and acronyms should not be uppercase when used as
name.
exportHtmlSource(); // NOT: exportHTMLSource();
openDvdPlayer(); // NOT:
openDVDPlayer();
Using all uppercase for the base name will give conflicts with
the naming conventions given above. A variable of this type would
have to be named dVD, hTML etc. which obviously is not very
readable. Another problem is illustrated in the examples above;
when the name is connected to another, the readability is seriously
reduced; the word following the acronym does not stand out as it
should.
All names should be written in English
English is the preferred language for international
development.
GUI variables should be suffixed by the element
type.
widthScale, nameTextField, leftScrollbar, mainPanel, fileToggle,
minLabel,
printerDialog
Enhances readability since the name gives the user an immediate
clue of the type of the variable and thereby the available
resources of the object.
People will tell you that using prefixes is bad, because
that is Hungarian notation and nowadays, Hungarian notation is
considered a big no-no in programming. whereas Hungarian notation
should definitely be avoided in non-GUI programming, when doing
GUIs it's a very good practice.
Consider, for example, a simple form with a textbox which is
to be used to enter the user's name. In front of this textbox
should be a label prompting the user to enter his name in the
textbox. Now, how are you going to name the textbox? 'Name'? What
about the label? A good practice should be prefixing the textbox
with txt, and label with label, which is what Hungarian notation is
all about. Thus, the textbox is now named 'txtName' and the
corresponding label is named 'lblName'. This gives you the
additional benefit of easily accessing your textboxes, combo boxes
and other widgets when in your IDE's editor. For example, typing
'txt' and pressing CTRL+Space in Eclipse opens up a context menu
listing all of your textboxes, if you follow this
notation.
The usual way to define what three letters you should use
for a prefix is to remove all the vowels from the widget's name and
also all repeating consonants. If there are more then three
consonants left, they should be ignored. Therefore, a textbox (or
TextField) becomes 'txt', a label 'lbl', a combo box 'cmb', a table
'tbl' and so on.
Sometimes it smacks of Hungarian notation. I don't like the idea
of embedding the type in the name of the variable, because if you
change types it shouldn't mandate changing all the variable names.
But in the case of Swing, I guess it's acceptable.
Plural form should be used on names representing a collection
of objects.
List<Point> points;
List<Integer> values;
Collection<Point> points;
int[] values;
Enhances readability since the name gives the user an immediate
clue of the type of the variable and the operations that can be
performed on its elements.
Iterator variables should be called i, j, k etc.
for (Iterator i = Point.iterator(); i.hasNext();)
{
// :
}
for (int i = 0; i < nTables; i++)
{
// :
}
The notation is taken from mathematics where it is an
established convention for indicating iterators.
Variables named j, k etc. should be used for nested loops
only.
Abbreviations in names should be avoided.
computeAverage(); // NOT: compAvg();
ActionEvent event; // NOT: ActionEvent e;
Catch(Exception exception) // NOT: catch(Exception
e){
There are two types of words to consider. First are the common
words listed in a language dictionary.These must never be
abbreviated. Never write:
cmd instead of command
comp instead of compute
cp instead of copy
e instead of exception
init instead of initialize
pt instead of point
etc.
Then there are domain specific phrases that are more naturally
known through their acronym or abbreviations. These phrases should
be kept abbreviated. Never write:
HypertextMarkupLanguage instead of html
CentralProcessingUnit instead of cpu
PriceEarningRatio instead of pe
etc.
Negated boolean variable names must be avoided.
bool isError; // NOT: isNoError
bool isFound; // NOT: isNoFound
The problem arise when the logical not operator is used and
double negative arises. It is not immediately apparent what!
isNotError means.
References
- Clean Code : Robert C. Martin
- http://geosoft.no/development/javastyle.html
- http://wiki.eclipse.org/Recommenders/CodingConventions