Here are some suggestions for a naming convention. These help identify the variables' usage and type and thus reduce coding errors. This is an abridged Hungarian notation:
[<scope>_]<type><name>
Prefix |
Variable scope |
m |
Instance class members |
c |
Static class member (including constants) |
g |
Global static variable |
<empty> |
local variable or struct or public class member |
<type>
Prefix |
Data Type |
b |
Boolean |
by |
byte or unsigned char |
cx/cy |
short used as size |
d |
double |
dw |
DWORD, double word or unsigned long |
f |
float |
fn |
function |
h |
handle |
i |
int (integer) |
ip |
smart pointer |
l |
long |
p |
a pointer |
s |
string |
sz |
ASCIIZ null-terminated string |
w |
WORD unsigned int |
x,y |
short used a coordinates |
<name> describes how the variable is used or what it contains. The <scope> and <type> portions should always be lowercase, and the <name> should use mixed case:
Variable Name |
Description |
m_hWnd |
a handle to HWND |
ipEnvelope |
a smart pointer to a COM interface |
m_pUnkOuter |
a pointer to an object |
c_isLoaded |
a static class member |
g_pWindowList |
a global pointer to an object |
Type Names
All type names (class, struct, enum, and typedef) begin with an uppercase letter and use mixed case for the rest of the name:
class Foo : public CObject { . . .};
struct Bar { . . .};
enum ShapeType { . . . };
typedef int* FooInt;
struct Bar { . . .};
enum ShapeType { . . . };
typedef int* FooInt;
Typedefs for function pointers (callbacks) append Proc to the end of their names.
typedef void (*FooProgressProc)(int step);
Enumeration values all begin with a lowercase string that identifies the project; in the case of ArcObjects, this is esri, and each string occurs on a separate line:
typedef enum esriQuuxness
{
esriQLow,
esriQMedium,
esriQHigh
} esriQuuxness;
{
esriQLow,
esriQMedium,
esriQHigh
} esriQuuxness;
Function Names
Name functions using the following conventions:
For simple accessor and mutator functions, use Get<Property> and Set<Property>:
int GetSize();
void SetSize(int size);
void SetSize(int size);
If the client is providing storage for the result, use Query<Property>:
void QuerySize(int& size);
For state functions, use Set<State>, and Is<State> or Can<State>:
bool IsFileDirty();
void SetFileDirty(bool dirty);
bool CanConnect();
void SetFileDirty(bool dirty);
bool CanConnect();
Where the semantics of an operation are obvious from the types of arguments, leave type names out of the function names.
Instead of
AddDatabase(Database& db);
consider using
Add(Database& db);
Instead of
ConvertFoo2Bar(Foo* foo, Bar* bar);
consider using
Convert(Foo* foo, Bar* bar)
If a client relinquishes ownership of some data to an object, use Give<Property>. If an object relinquishes ownership of some data to a client, use Take<Property>:
void GiveGraphic(Graphic* graphic);
Graphic* TakeGraphic(int itemNum);
Graphic* TakeGraphic(int itemNum);
Use function overloading when a particular operation works with different argument types:
void Append(const CString& text);
void Append(int number);
void Append(int number);
Argument names
Use descriptive argument names in function declarations. The argument name should clearly indicate what purpose the argument serves:
bool Send(int messageID, const char* address, const char* message);