Coding Style Guidelines - USTC



Coding Style Guidelines

Introduction

The purpose of standardizing a coding style for a development team or project is to reduce friction in the development process. What does it matter if we name our variables or indent our braces in one way or another? To the perspective of a modern compiler, it obviously does not matter. But more importantly, the discipline of a shared style increases overall efficiency, in terms of readability and understanding of the source code-- not only to teammates and other individuals that may need to understand, review, and debug and maintain others' works, but the author himself returning a year from now to update a project, would benefit. With the time saved from trying to get past unfamiliar styles to understand the intent of each other's source code, we can make more significant improvements to our programs. Now doesn't that sound more fun and rewarding?

It is the intent of this document to provide a guideline to a shared style for our C++ source code. Some of the guides may seem arbitrary, but it is more important to agree upon a single style rather than finesse from the diverse opinions. As a rule, when modifying code that doesn't fit the guidelines set in this document, please either match the different coding style of the function, or modify the entire function to the correct style. Finally, this document shouldn't be etched in stone. As opinions change and the team develops, this document should be periodically brought out and reviewed for changes in content and guidelines.

Please read and follow our guidelines, you will see the benefit. Thank you for being a good development citizen!

Naming Conventions

General Naming Conventions

| |Prefix |Examples |

|Classes |C |CELEventFrame, CSlide |

|Interfaces |I |IMediaControl |

|Methods | |Invalidate, OnMouseDown |

|Private Functions | |ApplyStyle, Draw |

|Data members |m_ |m_valid, m_idleCounter |

|Static data members |s_ |s_eventPump, s_topOfStack |

|Variables | |curSlp, ghostPat |

|Global variables |g_ |g_fOleInit, g_pTypeLib |

|Constants, Enumerations |Package- prefix_ |GR_STYLEPLAIN, TX_ALIGNLEFT, |

| | |W_PANE_NOERASEBG |

Type Prefix

|p |Pointer to (32-bit is now assumed; thus no need for lp). |

|pp |Pointer to a pointer |

|h |Handle to, aka cookie or abstract pointer (illegal to dereference). |

|ref |Reference to (eg: when passing parameters by reference in C++). |

|rg |Array of (ie: items stored sequentially in memory). Note: rg is often used. |

|z |Terminated array of. |

|sz |CHAR *,String, C type (ie: array of 8-bit characters, null character terminated) or CString |

|wsz |WCHAR *, Unicode string. |

|tsz |TCHAR *, Flexible Unicode/DBCS string. |

|vec |Vector |

|mat |Matrix |

Type Indicator

|s |SHORT |Signed integer, 16-bit. |

|l |LONG |Signed integer, 32-bit. |

|us |USHORT |Unsigned integer, 16-bit. |

|ul |ULONG |Unsigned integer, 32-bit. |

|b |BYTE |Non-counting purposes, 8-bit allocation. |

|w |WORD |Non-counting purposes, 16-bit allocation. |

|dw |DWORD |Non-counting purposes, 32-bit allocation. |

|i |int |Scalable signed integer |

|u |UINT |Scalable unsigned integer |

|fl |float |Floating point, 32-bit, 6-7 significant digits. |

|d |double |Floating point, 64-bit, 15-16 signigicant digits. |

|ch |CHAR |Character, 8-bit. |

|wch |WCHAR |Character, Unicode, 16-bit. |

|tch |TCHAR |Character, flexible Unicode or DBCS. |

|fn |Function |Function: always used with a type prefix (eg: pfn is pointer to function). |

|v |void |Void: always used with a type prefix (eg: pv is pointer to void). |

|f |bool or BOOL |f means flag |

|var |VARIANT or variant_t| |

Certain abbreviations have become standard

|abbreviation |Word |

|src |Source |

|dst |Destination |

|rc |Rectangle |

|quad |Quadrilateral |

|pt |Point |

|tx |Text |

|ptr |Pointer |

|stat |Status or state |

|cmd |Command |

|id |Identifier |

|wnd |Window |

|btn |Button |

|sel |Select or Selection |

Member Function Names

We highly recommend using the following standard prefixes for member function names.

|Function prefix |Type of function |

|F… |Query operations that return a bool |

|Get… |Gets a property. |

|Set… or Put… |Sets a property. |

|Create… |Creates or duplicates a C++ object. Use “Duplicate” for a method that duplicates the object itself. Objects |

|Dup… |returned by these functions must be disposed with delete. |

|On… |Protected notification methods usually overridden by clients. Where both On and After methods are provided, On is |

|After… |called prior to the event, and After is called after. |

|Draw… |Modifier operations (named with active verb phrases). |

|Move… | |

|Swap |Swaps the contents of one object with the contents of another in a way guaranteed to succeed and not throw an |

| |exception. |

Code formatting

Indentation

No Tab character

Make sure all tab character converted to 4 spaces.

Indent level

One indent level is 4 spaces

Indent data declarations and executable statements one level

// Example of function definition

PCOMMSG ComGetMsg( PCOMSERVER pServer,

long lTimeOut)

{

//--- Data indented same level as code

PCOMMSG pMsg;

//--- Code indented one level

pMsg = ComReadMsgFromQueue( pServer, NULL, ComWait_c, lTimeOut );

if ( NULL == pMsg )

{

ErrReport( “Server connection broken” );

}

return pMsg;

}

Indent function and data declarations at least one additional level beyond the public, protected, and private keywords.

class CExample

{

//--- public, protected and private functions indented.

public:

//--- Member function declarations indented at least on additional level

CExample();

~CExample();

private:

#ifdef _DEBUG

void TraceValue( int iValue );

#endif

//--- public, protected and private data members indented.

private:

//--- Data declarations indented one level

int m_iStoreSomething;

};

Indent long function calls

pMsg = ComReadMsgFromQueue( aServer, NULL,

ComWait_c, lTimeOut );

Brace

Use Braces "{}" to mark the beginning and end of all compound statement aligned vertically with their parent block.

while (foo)

{

if (bar)

{

Yabba(dabba);

}

else

{

foo();

}

Xyz(abc);

}

Statements that have bodies should put those bodies on a separate line and braces should always be used – even if the body is only a single line.

for( )

{

}

if ( )

{

}

else if ( )

{

}

else

{

}

White Spaces and line breaks

The maximum line length is 80 characters

Leave at least one space between a binary operator and each of its operands; use extra spaces to align operands if this improves readability:

iA = iB + iC;

iMinimum = -iAmplitude;

cLetter = *pChar;

flY = ( flX * flSlope ) + flY0;

x = ( pEvent->m_iButton == iButtonPress ) && ( 1 == pEvent->m_iButton );

Never end a line with a space or tab.

Have a blank line between variable declarations and code.

BOOL FFoo(void)

{

BAR bar1, bar2;

int cbar; // There is a blank line below.

cbar = Bar(&bar1, &bar2);

return cbar == 0;

}

Spaces are always AVOIDED in the following places:

Between the function name and the left parenthesis, e.g. “Foo (”

Between a pointer and the variable it modifies, e.g. “FOO * pfoo”

Next to arrows, e.g. “a-> b”;

Next to variable/dot combinations, e.g. “a. b”

Spaces are always USED in the following places:

Around keywords, e.g. “if (...)” and never “if(...)”.

Between argument/variable combinations in parentheses, e.g. “(a, b, c)”

Between a type and a pointer, e.g. “FOO *pfoo”

Surrounding equals signs, e.g. “a = b;” and never “a=b;”

In summary, spaces are placed as in English (e.g. space after comma, no space after parentheses, space after keywords, space before and after most operators).

Never have multiple statements on one line like

a = 1; b = 2; // bogus

if (fFoo) Bar(); // bogus

Labels are always on lines by themselves.

LFoo: a = 1; // bogus

Syntax

Common Types

Use the built-in types (short, int, long, etc.).If it requires limit types used, it’s recommend to redefine all types used in a common header file.

Structs

struct POINTD // use this

{

REAL X;

REAL Y;

};

typedef struct tagPOINTD // Do not use this

{

REAL X;

REAL Y;

} POINTD;

Const-correctness

Use const wherever an item won’t be changed.

HRESULT Compress(BYTE *pbOut,

DWORD *pbOutLen,

const BYTE* pbSrc,

const DWORD dwSrcLen);

Type casts

Use explicit typecast force compiler and programmer to more verification.

int *ptr = (int *) malloc(xyz); // DON’T DO THIS

char *device = (char *) 0xf0000123; // DON’T DO THIS

int myInt = (int) myConstInt; // DON’T DO THIS

Use these:

int *ptr = static_cast(malloc(xyz));

char *device = reinterpret_cast(0xf0000123);

int myInt = const_cast(myConstInt);

Function definitions

Must be defined with the return type

VOID RandomObject::DoSomething( INT x, Blob *blob )

{

blob->Glob(x);

}

In function declarations (prototypes), the following is allowed if it fits on one line.

INT ComputeArea(INT x, INT y);

Function calls

If the call fits on one line:

answer = GetAnswer(x, joe, blob);

Otherwise, put each parameter on a separate line, indented one level:

MyFunctionWithLongName(

sqrt(x*x + y*y),

*(ptr + 64) – 30

);

Comments (Clear and necessary)

You can simply copy and paste the following comments before file header and functions to your code.

File headers

/*****************************************************************************\

Zhejiang University

Copyright (c) 2004 Zhejiang University

Module Name:

An unabbreviated name for the module (not the filename)

Abstract:

Description of what this module does

Notes:

[Optional] Additional notes about this module - things that may help

the reader of this code later on. Examples are: algorithm description,

special case conditions, references, etc.

History:

Created on mm/dd/yyyy by email-name

Modified on mm/dd/yyyy by email-name

[Optional] history description

\*****************************************************************************/

Section separators

//-----------------------------------------------------------------------------

… a commented one

//-----------------------------------------------------------------------------

// Buffer manipulation routines

//-----------------------------------------------------------------------------

Function headers

/*****************************************************************************\

Function Description:

Description of what the function does

Arguments:

[ | OUT | IN/OUT] argument-name - description of argument



Return Value:

return-value - description of return value

or NONE

History:

Created on mm/dd/yyyy by email-name

\*****************************************************************************/

Classes definition

Please follow this example:

#define IN // Nothing but a sign show the input/output parameters

#define OUT

class CMyClass

{

public:

DWORD Compress(OUT BYTE *pbDest, // recommend use “IN” and “OUT”

OUT ULONG*puDstLen, // to indicate input and output parameters

IN const BYTE *pbSrc,

IN const ULONG uSrcLen );

// short inline function can be inside class decalration

inline GetByte(const ULONG uIndex) { return m_pBuffer[uIndex]; }

// Recommend use reference parameters to get output instead of pointer

HRESULT GetHeaderInfo( IMAGE_HEADER& refImgHdr );

private:

IMAGE_HEADER m_ImgHdr; // Data members should never be public

public:

virtual HRESULT Display(); // Be careful with virtual functions

// const for function means member data is not modified.

// highly recommended

const VOID Dump();

// Recommend use the two stages initialization

BOOL Init(); // HRESULT can return more status

BOOL Free();

CMyClass();

~CMyClass();

}

Source Code File Structure

Here is the general format of the source code file for a class implementation:

file header

#include directives (private to implementation)

#defines (private to implementation)

typedefs (private to implementation)

global variables

internal functions

exported functions

"methods" implementing messages

class initialization routine

main routine (in an app class)

Here is the general format of the source code file for a non-class implementation:

file header

#include directives (private to implementation)

#defines (private to implementation)

typedefs (private to implementation)

global variables

internal functions

exported functions

Implementation Issues

One time include in header files

Headers should be protected with #ifndef…#define…#endif blocks for inclusion safety.

Sample.h

#ifndef _GDIPLUS_H

#define _GDIPLUS_H





#endif // _GDIPLUS_H

Or you can simply use #pragma once at the beginning of file

Function length

Functions should be fewer than 100 lines long unless structure or performance requires a longer function. In general functions should be even shorter, with sub-functions created as necessary.

Use of NULL as flag

1 - Explicitly put NULL in any value test:

//Don’t do this:

if (pInterface)

{

}

// do this instead

if (NULL != pInterface)

{

}

2 - Always initialize and reset the pointer to NULL. This ensures that you will never be accessing a stale pointer

// don’t do this

if (NULL != pInterface)

{

pInterface->Release();

}

// do this

if (NULL != pInterface)

{

pInterface->Release();

pInterface = NULL;

}

Parameter Validation

Every public interface method must validate input parameters.

HRESULT Foo( PBYTE pbSrc )

{

ASSERT( NULL != pbSrc );

...

}

// TODO & // REVIEW Indicator

// TODO & //REVIEW indicator is a mark in comment to show the work should be done or reviewed later. It’s a good habit remind yourself and other colleagues before shipping in team project. Before shipping, all the // TODO should be removed (the tasks should be done or change // TODO to // REIVIEW)

Format:

// TODO [task owner][(writer)]: Task description

Examples:

// TODO: cleanup



The following is BARNWL tells GANGCH write cleanup code later

// TODO: GANGCH(BARNWL): cleanup

Coding Style Checklist

1           Classes

Declaration

1.1            Declare all class members explicitly as public, protected, or private, in groups in that order.

1.2            Do not declare public data members in classes. Use inline accessor functions for performance.

1.3            Virtual functions have overhead, so don’t use them unless you really should.

1.4            An overridden virtual method is explicitly declared virtual for clarity.

1.5            A destructor in a base class should always be virtual if polymorphism is intended.

1.6            Never hide expensive work behind an operator. If it’s not super efficient then make it an explicit method call.

1.7            Don’t use inheritance just because it will work. Use it sparingly and judiciously.

1.8            Don’t use multiple inheritance.

Constructor and Destructor

1.9            Never declare a global instance of a class that has a constructor.

1.10         Do not do expensive work in a constructor.

1.11         If you do make a constructor, make sure to initialize all data members.

1.12         A constructor should never fail. Do memory allocations and other potential failures in a FInit or Create method.

1.13         A destructor should never fail

2           Other C/C++ Issues

2.1            Avoid allocating class instances on the stack and passing them by value. Use new and delete, and pass them by pointer.

2.2            If resources are freed before destruction, make sure the fields are reset (e.g. set pointers to NULL) to prevent multi-free.

2.3            Use const or enum instead of #define for constants when possible.

2.4            Use const to mark read-only pointer parameters (what the pointer points at, not the pointer itself).

2.5            Don't use default arguments.

2.6            Minimize global variables.

2.7            Use inline functions instead of #define macros when possible

2.8            In functional macros, enclose all argument instances in parentheses “( )” as well as the entire expression if necessary.

2.9            Functions that return pointers but can fail should return a BOOL and return the pointer in a parameter.

2.10         DLL-exported data should be avoided, but must use extern "C" if needed.

2.11         Use the macros defined in OLE’s objbase.h where appropriate for C/C++ declarations, especially COM-style interfaces.

3           Source File Organization

3.1            Filenames use prefix denoting the major feature team (e.g. “tb” for Toolbars), then ................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download