Naming Patterns
Name the variable is a big issue when you're coding. A good variable name should meet the following requirements
- Easy to understand what it does
- Easy to know how to operate it
The naming issues
class Person()
{
public:
Person(str::string name, unsigned int age, Person* dad, Person* mom)
: name(name)
, age(age)
, dad()
, mom()
{
}
std::string Name()
{
return name;
}
private:
std::string name;
unsigned int age;
Person* dad;
Person* mom;
};
name(name)
and age(age)
will make readers confused.
Using Prefix
One solution for making the variables clearer is to use prefix
(discussion about why using prefix).
Suppose we use m
as the prefix for member variable,
then name(name)
should be changed to mName(name)
.
Such changing will make the code clearer for the readers.
How about using this
You may argue that you can use this->
to avoid
the ambiguous naming problem.
Nevertheless, this->
can't be used for static members
in some languages(e.g., C++).
What's worse is that you no longer can use g++ -Wshadow
warnings.
Common prefix
- a : argument
- c, k: constant
- e : events
- g : global
- i : indexes and iterators
- m : member
- p : pointer (and pp for pointer to pointer)
- s : static member (e.g. sPrefChecked)
- v : volatile
Private member prefix
How to distinguish a member variable is public or private? Using underscore '_' may be helpful.
- private member:
[PREFIX] + _ + [NAME]
m_age
m_phone
- public member:
[PREFIX] + [NAME]
mName
Using underscores may be risky
If you use underscore as first character, it might be risky.
A leading underscore before a capital letter in a word is reserved.
For example, _Foo
is reserved, while _foo
is not.
However, there are other situation may make
leading underscore before a lowercase infeasible.
The rules which did not change in C++11 from the 2003 C++ Standard:
- Reserved in any scope, including for use as implementation macros:
- identifiers beginning with an underscore followed immediately by an uppercase letter
- identifiers containing adjacent underscores (or "double underscore")
- Reserved in the global namespace:
- identifiers beginning with an underscore
- Also, everything in the std namespace is reserved. (You are allowed to add template specializations, though.)
See more here: underscore rules in C++ identifier.
Pros
- No confusion between member and parameter
- e.g.,
mName(name)
instead ofname(name)
- e.g.,
- Type is clearer then you can code faster and leave less comments
- You don't waste time searching the variable's type and scope
- You can distinguish the variable is global, local, static, pointer or not at a glance
- Easy to guess how to use the variable:
- e.g., No need to check what data type the
dad
is and try to figure out how to use it to get the dad's name. If we usepDad
instead ofdad
, then we can easily knowpDad->Name()
is the answer.
- e.g., No need to check what data type the
- Avoid generic(vague) names for usage:
- e.g.,
iItem
definitely shows it's the index/iterator foritem
counter toindex
orcount
.
- e.g.,
- Show less candidates in auto-complete lists with typing prefix
Cons
Need to think more here.....
Without Prefix
How to overcome the drawbacks mentioned above if we don't use prefix? Need to think more here.....