Seven Naming Habits and One Golden Rule for Better Code
A good name is rarely just a naming choice. In real projects, it affects how quickly other people understand the code, how safely they review it, and how much time you spend later on debugging, refactoring, and maintenance.
1. Make variable names as self-explanatory as possible
Avoid the kind of abstract, textbook-style names that only make sense in a classroom example.
- Good names:
daysDateRange,flightNumber,carColor - Bad names:
days,dRange,temp,data,aux
Many developers still prefer short names simply because they are used to them. That habit often comes from university examples, where variables are named in a very generic way to keep the lesson simple. The problem is that this influence stays with us for years.
Saving a few keystrokes is not worth the cost. In software, maintenance is far more expensive than writing the code in the first place. If a variable name is vague, then code review becomes harder, bug fixing slows down, refactoring gets riskier, and maintenance can turn into guesswork. A readable codebase depends heavily on names that make sense at a glance.
2. Keep names short, but not at the expense of meaning
Simple and short names are easier to read because they sit inside longer program statements. If every variable name is long and heavy, even a small expression can look bloated.
But there is a real tension here: a name can be short, or it can be rich in meaning, and sometimes it is hard to be both. That is where judgment matters. If you can find a compact word that still carries the right meaning, that is ideal. If you cannot, then meaning should win.
- Bad names:
howLonDoesItTakeToOpenTheDoor,howBigIsTheMaterial - Good names:
timeToOpenTheDoor,MaterialSize
3. Abbreviations are acceptable, but use them carefully
Sometimes abbreviations are useful: usr for user, gp for group, conf for configuration, cwd for current working directory, ptr for pointer, and so on.
The key is not to abbreviate just for the sake of shortening a word. A shorthand should still be understandable to the people reading the code. When in doubt, a comment can make the intent clearer and reduce the chance of confusion.
A convention only helps when people actually recognize it. If an abbreviation is obscure, it stops being a shortcut and starts becoming a puzzle.
4. Use Hungarian notation when it serves a real purpose
Hungarian notation is a naming style that adds a prefix to show a variable’s type or, in some cases, the role of a function. The basic idea is:
variable name = attribute + type + object description
Examples of type-oriented prefixes include:
pfor pointerfnfor functionlfor longbfor booleanffor float, and sometimes filedwfor double wordszfor zero-terminated stringnfor short integerdfor doubleufor unsigned
This approach has an obvious downside: if a variable changes from an integer to a floating-point value, the name has to change too. That can be tedious. In some cases, the prefix itself can make code harder to read instead of easier. And once classes are involved, especially in C++, the style becomes less convenient to apply consistently.
So the important part is not blindly following the prefix itself, but understanding the thinking behind it and using it where it truly helps.
For project-wide global variables, it is common to use g_ as a prefix; class members often use m_; and in larger functions, local variables may also be marked in a way that makes their scope obvious.
Prefix Type Example
g_ global variable g_Servers
C class/struct CDocument, CPrintInfo
m_ member variable m_pDoc, m_nCustomers
5. Avoid negative naming
- Good name:
IsEnabled - Bad name:
IsNotEnabled
Readers naturally prefer positive logic. The same idea applies not only to names, but also to conditions. Negative expressions are harder to scan and reason about.
For example, this kind of condition is not very friendly to the eye:
if (! (isAdmin || isUser))
A clearer version is:
if (!isAdmin && !isUser)
The second form matches how people usually read code: direct, explicit, and without unnecessary mental detours.
6. Stay consistent
There is no single naming convention that is perfect for every team or every project. What matters more is consistency.
A codebase should use the same naming rules throughout. Even if a convention is not ideal in every detail, a consistent convention is still better than a mix of incompatible habits. Once a team agrees on a style, everyone benefits from the predictability.
7. Fit the language of the domain
Words do not mean the same thing in every field.
Take order, for example. In one context it may mean sequence. In another, it may mean a purchase order. Elsewhere it could mean a command or a rule.
That is why names should match the terminology of the domain you are working in. A word that feels natural in one business area can be misleading in another. Good naming is not just about language in the abstract; it is about using the language of the problem domain.
The golden rule: think before you commit to a name
When you choose a variable name or a function name, do not rush into using it. Pause for a moment and ask whether it is really the best choice.
Maybe the name is too vague. Maybe there is a clearer one. Maybe the tradeoff deserves a quick discussion with a colleague. Naming is not a mechanical step; it is part of design.
In the end, variable naming is one of the first steps in programming. If the first step is done well, the rest of the work becomes much easier. Good names make coding lighter not only for you, but also for everyone who has to read and maintain the code later.
Appendix 1: Common abbreviations
<table> <thead> <tr> <th>Full word</th> <th>Abbreviation</th> </tr> </thead> <tbody> <tr> <td>average</td> <td>avg</td> </tr> <tr> <td>back</td> <td>bk</td> </tr> <tr> <td>background</td> <td>bg</td> </tr> <tr> <td>break</td> <td>brk</td> </tr> <tr> <td>buffer</td> <td>buf</td> </tr> <tr> <td>color</td> <td>cr, clr</td> </tr> <tr> <td>control</td> <td>ctrl</td> </tr> <tr> <td>data</td> <td>dat</td> </tr> <tr> <td>delete</td> <td>del</td> </tr> <tr> <td>document</td> <td>doc</td> </tr> <tr> <td>edit</td> <td>edt</td> </tr> <tr> <td>error</td> <td>err</td> </tr> <tr> <td>escape</td> <td>esc</td> </tr> <tr> <td>flag</td> <td>flg</td> </tr> <tr> <td>form</td> <td>frm</td> </tr> <tr> <td>grid</td> <td>grd</td> </tr> <tr> <td>increment</td> <td>inc</td> </tr> <tr> <td>information</td> <td>info</td> </tr> <tr> <td>initial</td> <td>init</td> </tr> <tr> <td>insert</td> <td>ins</td> </tr> <tr> <td>image</td> <td>img</td> </tr> <tr> <td>label</td> <td>lab</td> </tr> <tr> <td>length</td> <td>len</td> </tr> <tr> <td>list</td> <td>lst</td> </tr> <tr> <td>library</td> <td>lib</td> </tr> <tr> <td>manager</td> <td>mgr, mngr</td> </tr> <tr> <td>message</td> <td>msg</td> </tr> <tr> <td>Oracle</td> <td>Ora</td> </tr> <tr> <td>panorama</td> <td>pano</td> </tr> <tr> <td>password</td> <td>pwd</td> </tr> <tr> <td>picture</td> <td>pic</td> </tr> <tr> <td>point</td> <td>pt</td> </tr> <tr> <td>position</td> <td>pos</td> </tr> <tr> <td>print</td> <td>prn</td> </tr> <tr> <td>program</td> <td>prg</td> </tr> <tr> <td>server</td> <td>srv</td> </tr> <tr> <td>source</td> <td>src</td> </tr> <tr> <td>statistic</td> <td>stat</td> </tr> <tr> <td>string</td> <td>str</td> </tr> <tr> <td>Sybase</td> <td>Syb</td> </tr> <tr> <td>temp</td> <td>tmp</td> </tr> <tr> <td>text</td> <td>txt</td> </tr> <tr> <td>user</td> <td>usr</td> </tr> <tr> <td>window</td> <td>win, wnd</td> </tr> </tbody> </table>Appendix 2: Hungarian notation
a Array array
b BOOL (int) boolean (integer)
by Unsigned Char (Byte) unsigned char (byte)
c Char character (byte)
cb Count of bytes number of bytes
cr Color reference value color reference value
cx Count of x (Short) count of x (short integer)
dw DWORD (unsigned long) double word (unsigned long)
f Flags flags (usually a multi-bit value)
fn Function function
g_ global global
h Handle handle
i Integer integer
l Long long integer
lp Long pointer long pointer
m_ Data member of a class class data member
n Short int short integer
p Pointer pointer
s String string
sz Zero terminated String zero-terminated string
tm Text metric text metric
u Unsigned int unsigned integer
ul Unsigned long (ULONG) unsigned long integer
w WORD (unsigned short) unsigned short integer
x,y x, y coordinates (short) coordinate values / short integers
v void void
For global project variables, use g_ at the beginning. For class members, use m_. If a local variable appears inside a large function, l_ can be used to make its scope obvious.
Prefix Type Example
g_ global variable g_Servers
C class/struct CDocument, CPrintInfo
m_ member variable m_pDoc, m_nCustomers
Common VC prefixes
Prefix Type Description Example
ch char 8-bit character chGrade
ch TCHAR 16-bit UNICODE character chName
b BOOL boolean variable bEnabled
n int integer nLength
n UINT unsigned integer nLength
w WORD 16-bit unsigned integer wPos
l LONG 32-bit signed integer lOffset
dw DWORD 32-bit unsigned integer dwRange
p * memory pointer pDoc
lp FAR* long pointer lpDoc
lpsz LPSTR 32-bit string pointer lpszName
lpsz LPCSTR 32-bit const string pointer lpszName
lpsz LPCTSTR 32-bit UNICODE const ptr lpszName
h handle Windows object handle hWnd
lpfn (*fn)() callback function pointer lpfnAbort
Windows object name abbreviations
Windows object Example variable MFC class Example object
HWND hWnd; CWnd* pWnd;
HDLG hDlg; CDialog* pDlg;
HDC hDC; CDC* pDC;
HGDIOBJ hGdiObj; CGdiObject* pGdiObj;
HPEN hPen; CPen* pPen;
HBRUSH hBrush; CBrush* pBrush;
HFONT hFont; CFont* pFont;
HBITMAP hBitmap; CBitmap* pBitmap;
HPALETTE hPalette; CPalette* pPalette;
HRGN hRgn; CRgn* pRgn;
HMENU hMenu; CMenu* pMenu;
HWND hCtl; CStatic* pStatic;
HWND hCtl; CButton* pBtn;
HWND hCtl; CEdit* pEdit;
HWND hCtl; CListBox* pListBox;
HWND hCtl; CComboBox* pComboBox;