zoukankan      html  css  js  c++  java
  • 【重要】代码规范

    Coding Style Conventions

    From CG & CAD

    Jump to: navigationsearch

    Contents

    1 Instruction

    2 File Templates

    3 Naming Rules

        3.1 Generic Naming Rules

        3.2 Specific Naming Rules

    4 Indentation

    5 Braces

    6 White Space

        6.1 Declarations

        6.2 Control Statements

        6.3 Expressions

        6.4 Arrays

        6.5 Parameterized Types and Type Casts

    7 Line Breaks

        7.1 Blank Lines

        7.2 New Lines

        7.3 New Lines in Array Initialization

    8 Line Wrapping

    9 Miscellaneous

    10 Comments

        10.1 Block comments

        10.2 Line comments

    11 Documentation Comments

        11.1 @a parameter-name

        11.2 @c word

        11.3 @deprecated description

        11.4 @dot dotsources @enddot

        11.5 @f$ formula @f$

        11.6 @f[ formula @f]

        11.7 @param parameter-name parameter-description

        11.8 @return description-of-the-return-value

        11.9 @see references

        11.10 @since text

    1. Instruction

    Note that there are two kinds of counterexample codes in the following rules: "NOT" and "BETTER THAN". The former describes specific rules that you must follow, while the latter is much like a suggestion, which you can violate if you have strong personal objections against it.

    2. File Templates

    Always use "class.sh ClassName" to generate your class skeleton. In order to use "class.sh", you have to put a text file named ".PROJECT_INFO" at the top directory of your project, in this format:

    product="Your Project Name" startyear="2007"

    3. Naming Rules

    Generic Naming Rules

    Principle: Make names of different types (classes, variables, methods, enum, etc.) self-distinguishable as far as possible.

    • All names should be written in English. (类名必须由英文单词构成,而不是拼音)

       class Light; // NOT: class GuangYuan;                            

    • File names should be all lower case without underscores.  (文件名必须全部小写,不含下划线)

      mainrenderloop.cpp // NOT: MainRenderLoop.cpp

      brdfedit.h // NOT: BRDF_edit.h

    • A class should be declared in a header file and defined in a source file where the name of the files match the name of the class.(类名与文件名相同)

     camera.cpp, camera.h // NOT: camera.cpp, cameraheader.h

    • Names representing types(such as a class)  must be in mixed case starting with upper case.

     TriangleMesh, Line // NOT: triangle_mesh, line

    • Variable names must be in mixed case starting with lower case.

      triangleMesh, line // NOT: triangle_mesh, m_line

    • Named constants (including enumeration values) must be all uppercase using underscore to separate words.

      MAX_DEPTH, PI

    • Names representing methods or functions must be verbs and written in mixed case starting with lower case.

      getValue(), computeTotalWidth() // NOT: GetValue(), compute_total_width()

    • Names representing namespaces should be all lowercase.

       io::iomanager, comman::math::geometry

    • Abbreviations(缩写词) and acronyms must not be uppercase when used as name.

       exportXmlSource(); // NOT: exportXMLSource(); openDvdPlayer(); // NOT: openDVDPlayer();

    • Global variables should always be referred to using the :: operator.

      ::mainWindow.open(), ::applicationContext.getName()

    In general, the use of global variables should be avoided. Consider using singleton objects instead.

    • Private class variables should have underscore suffix.

    class RayTracer 

    {

    public:

        getDepth();

    private:

        depth_; 

    }; 

    // NOT:  

    class RayTracer 

    {

    public:

        getDepth();

    private:

        m_depth;

    }; 

    • Generic variables should have the same name as their type.

    void setTopic( Topic* topic ) // BETTER THAN: void setTopic(Topic* value)

                                            // BETTER THAN: void setTopic(Topic* aTopic)

                                            // BETTER THAN: void setTopic(Topic* t)

    void connect( Database* database ) // BETTER THAN: void connect(Database* db)

                                                        // BETTER THAN: void connect (Database* oracleDB)

    • 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".

    • The name of the object is implicit, and should be avoided in a method name.

      line.getLength(); // NOT: line.getLineLength();

    Specific Naming Rules

    Principle: Increase readablity and avoid dual meaning.

    • Codes in MFC mudules can just follow the MFC's naming principle, such as CamelWord, m_member, etc.
    • Names representing template types should be a single uppercase letter, or as short as possible.

    template<class T> // NOT: template<class t>

    class MyClass

    {

        // ...

    };

    template<class T, class Ite> // NOT: template<class Object, class Iterator>

    class MyClass

    {

        // ...

    }

    • Plural form should be used on names representing a collection of objects.

    vector<Point> points;  // BETTER THAN: vector<Point> point;

    int values[];               // BETTER THAN: int value[];

    • The prefix "n" should be used for variables representing a number of objects.

    nPoints = getPointNumber();

    setLineNumber(nLines);

    • The suffix "No" should be used for variables representing an entity number.

    tableNo, employeeNo

    • Index variables should be called i, j, k, etc.

    for ( int i = 0; i < nTables; i++ )

    {

        ...

    }

    • But for Iterator variables, should be called itr_name.

    for ( vector<MyClass>::iterator itr_myList = myList.begin(); itr_myList != myList.end(); itr_myList++ )

    {

         Element element = *itr_myList;

         ...

    }

    • The prefix "is" should be used for boolean variables and methods.

       bool isSet, isVisible, isFound, isOpen;

       bool isFinished();

    • The prefix "get/set" should be used for direct access of class data members.

    int getValue();

    void setCenter( float x, float y, float z );

    • Complement names must be used for complement operations

    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.

    • Abbreviations(缩写词) in names should be avoided.

      computeAverage(); // BETTER THAN: compAvg();

      command, copy, point // BETTER THAN: cmd, cp, pt

      compute, initialize // BETTER THAN: comp, init

    • Naming pointers specifically should be avoided.

    Line* line; // NOT: Line* pLine;

                   // NOT: Line* linePtr;

    • Negated(否定的) boolean variable names must be avoided.

     bool isError; // NOT: isNoError

     bool isFound; // NOT: isNotFound

    • Enumeration constants can be prefixed by a common type name.

    enum Grade                // BETTER THAN:   enum Grade

    {                                                         {

       GRADE_HIGH,                                         HIGH,

       GRADE_MIDDLE,                                      MIDDLE,

        GRADE_LOW                                          LOW

    };                                                        };

    • Exception classes should be suffixed with "Exception".

    class AccessException

    {

        ...

    };

    • Interface classes should be suffixed with "Interface".

    class MaterialInterface

    {

    public:

        virtual void destroy( void ) = 0;

    }

    • Namespace.

    1. Namespace names are all lower-case, and based on project names and possibly their directory structure:

       thu_conap_visualization

    2. Do not declare anything in namespace std, not even forward declarations of standard library classes. Declaring entities in namespace std is undefined behavior, i.e., not portable. To declare entities from the standard library, include the appropriate header file.

    3. You may not use a using-directive to make all names from a namespace available. for example:

    using namespace foo;// Forbidden -- This pollutes the namespace.

    4. You may use a using-declaration anywhere in a .cc file, and in functions, methods or classes in .h files.

    // OK in .cc files.

    // Must be in a function, method or class in .h files.

    using ::foo::bar;

    5. Namespace aliases are allowed anywhere in a .cc file, and in functions and methods in .h files.

    // OK in .cc files.

    // Must be in a function or method in .h files.

    namespace fbz = ::foo::bar::baz;

    4. Indentation(缩进)

    • TAB size: 4; Note that: just use 4 spaces instead of using the TAB.
    • Do not use aligment for definitions.

    int line = 5;     // NOT: int line=5; (操作符( +、-、*、\、= 、// 等)前后要各放一个空格),后要放一个空格

    int is = 7;                   int        is = 7;

    double a = 3.2;           double a    = 3.2;

    float test = 2.3;           float test =      2.3;

    • Indent statements within method / function body.
    • Don't indent "public", "protected", "private".(不要缩进)
    • Indent declarations within class body.
    • Indent declarations within enum constants.

    class MyTest

    {

    public:

        enum MyMode

        {

             MODE_STATE_1,

             MODE_STATE_2

        };

         myTest( void )

        {

              data_ = 0;

        }

    private:

        int data_;

    };

    • Indent statements within blocks.
    • Don't indent statement within "switch".
    • Indent statement within "case" body.
    • Indent "break" statement.
    • Indent 4 space at a time; do not use tab.

    switch( mode )

    {

        case 0:

            solve(data);

            mode = 1;

            break;

        case 1:

             stop();

             mode = 0;

             break;

        default:

            failure();

    }

    • Don't indent empty lines.
    • Indent the array initializing if not in the same line.

    int a[] =

        {

            1, 2, 3, 4, 5

        };

    5.Braces

    • Put all short enough braces pair in the same line.
    • Put all the other braces to the next line, without indent.

    int shortEnough( void ) { return 5; }

    int longFunction( void )

    {

        int result = 0;

        for(int i = 0; i < 10; ++i)

         {

             result += i;

         }

        return result;

    }

    • For all the statements, for example: "if" ,"while", "for"......, can not emit brackets in the statement.

    if ( 0 == a )

    {

         oneLine();

    }

    else

    {

        onlyOneLine();

    }

    for( int i = 0; i < nNumber; i++ )

    {

        doSomething();

    }

    6. White Space

    Principle: Readability and consistence(风格一致).

    6.1 Declarations

    • Using a space before or after an opening parenthesis.
    • No space before an closing parenthesis.
    • If in the same line, space before and after opening brace, and space before closing brace.

    int testFunction( int a, int b, int c ) { return a + b + c; }

    • No space before * or & (Pointers or References only).
    • Space after * and & (Pointers or References only).

    float* x; // NOT: float *x;

    int& y; // NOT: int &y;

    • Don not define several pointers in one line.

    Light* light1;  // NOT: Light *light1, *light2, *light3;

    Light* light2;

    Light* light3;

    For labels, no space before colon.

    6.2 Control Statements

    • No space between "if", "else", "for", "switch", "while", "catch" and the following parenthesis.

    while( true )             // NOT: while  (true)

    {                          {

        // ...                     // ...

    }                          }

    • If in the same line, no space before the open parenthesis, and a space after the open parenthesis.
    • If in the same line, space before the close parenthesis.
    • In "for" statement, no space before the semicolon.
    • In "for" statement, space after the semicolon.

    for( int i = 0; i < nLines; ++i )

    {

        if( isFileOpen() ){ parseFile(); }

        ...

    }

    • Space between "return" and returned data.
    • No space after empty "return" statement.
    • Space between "throw" and the thrown data.
    • No space after "throw" statement.

    void processLineNo( void )

    { if( nLines > MAX_LINE_NO )

        {

            throw LineNoException;

        }

        else if ( nLines == MAX_LINE_NO )

        {

            return ;

        }

        else

         {

            ...

        }

    }

    6.3 Expressions

    • No space after the function name.
    • Spaces around the binary operators.
    • No space around the unary operators.
    • No space around parenthesis.
    • No space before comma.
    • Space after comma.

    int result = ( 1 + 2 + -3.0 * --value ) * 9.7 / myFunction( 7.2 );

    In conditionals, spaces around question mark and colon.

    return p == 0 ? 2 : 3;

    No space before and after "->".

    Light* light; light->setPosition( newPosition ); // NOT: light -> setPosition(newPosition);

    No space between "delete" operator and "[]".

    In "delete[]", space after "[]".

    char* data = new char[20]; delete[] data; // NOT: delete []data; // NOT: delete [] data;

    6.4 Arrays

    • No space before the opening bracket.
    • No space between empty brackets.
    • Space before opening brace.

    Space after opening brace.

    Space before closing brace.

    int data[] = { 1, 2, 3 }; int data2[5];

    6.5 Parameterized Types and Type Casts

    No space before opening angle bracket.

    No space after opening angle bracket.

    No space before comma.

    Space after comma.

    No space before closing angle bracket.

    Space after closing angle bracket in type declarations.

    std::map<std::string, std::int> employeeAndNo;

    No space after closing angle bracket in type casts.

    int intValue = static_cast<int>( doubleValue );

    Space after closing parenthesis in type casts.

    int intValue = (int) floatValue; // Not allowed in C++

    C-style type casting not allowed in C++

    Line Breaks

    Principle: Readability.

    Blank Lines

    Blank line after file comments.

    Blank line after include statements.

    Blank line between multi-line functions.

    No blank line between single-line inline functions.

    The number of empty lines to preserve is only 1.

    New Lines

    No new line in empty class body.

    No new line in empty method body.

    No new line in empty block.

    Must have a new line at end of file.

    Keep "else if" in one line.

    if ( 1 == a ) { doSomethingOne(); } else if ( 2 == a ) { doSomethingTwo(); } else { doSomethingElse(); }

    New Lines in Array Initialization

    If short enough, no new line before opening brace.

    If short enough, no new line after opening brace.

    If short enough, no new line before closing brace.

    If not short enough, new line before opening brace.

    If not enough, new line after opening brace.

    If not short enough, new line before closing brace.

    int shortEnough[] = { 1, 2, 3, 4, 5 }; int notShortEnough[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };

    Line Wrapping

    Principle: only wrap when necessary.

    Line 80. (Header guard can exceed this limitation)

    Indent 4 spaces for wrapped lines.

    Wrap the parameters of functions when necessary.

    AVeryLongReturnType MyClass::aVeryLongFunctionName( Light* light, Camera* camera, Scene* scene, Texture* texture ) { initializeScene() // ... }

    If a function is in a so deep indent level that even one parameter of it cannot be written in the same line, wrap parameters after parenthesis to a new line, and increase one indent level. The same rule can apply to type casts.

    AVeryLongFunction( parameterA, AnotherLongFunction( parameterAA, YetAnotherLongFunction(), parameterAB ), parameterB, parameterC ); for ( int i = 0; i < size; ++i ) { switch( static_cast<MyVeryLongClassType>( inputParameterToBeCasted) ) { // case TypeA: ... } }

    Try your best to wrap after semicolon if conditions of a control statement are very long.

    for( int a = 0, b = 1, c = 2, d = 3; thisIsAVeryLongConditionFunction(); anotherLongConditionFunction() ) { doSomething(); }

    Wrap conditions of control statements when necessary; If a condition is too long, wrap it to the beginning of a new line, and increase one indent level;

    for( int a = 0, b = 1, c = 2, d = 3, e = 4, f = 5, g = 6, h = 7; thisIsAVeryLongConditionFunction(); anotherLongConditionFunctionThatNeedsParams( paramA, paramB, paramC ) ) { doSomething(); }

    If necessary, wrap colon to the beginning of the next line when defining constructors.

    ShortClass::ShortClass(void) : member_( 5.2 ) { doSomething(); }

    LongClass::LongClass( int a, int b, int c )  : memberA_( 1 ), memberB_( 2 ), memberC_( 3 ), memberD_( 4 ), memberE_( 5 ) { doSomething(); }

    When defining enums, one element per line - wrap every element.

    enum Color { COLOR_RED, COLOR_GREEN, COLOR_BLUE };

    When initializing arrays, (if wrap,) wrap the opening bracket and the closing bracket, too. And increase one indent level for brackets, increase another indent level for elements.

    int shortEnough[] = { 1, 2, 3 }; int longArray[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, };

    When wrapping expressions, wrap binary operators to the beginning of the next line; Don't wrap the assignment operator to the beginning of the next line; Increase one indent level with respect to the former "(" for the following lines.

    bool result = aVeryLongStatement && anotherStatement || aMethodReturnsBool() && anotherMethodReturnsBool() || variableA >= variableB;

    double foo( void ) { return variableA * variableB + func( varialbeC ) - anotherFunc() / variableD + longFunction( varialbeE * variableF ) / variableG; }

    if( conditionA() && conditionB() // NOT: if (conditionA() && conditionB() && && conditionC() && conditionD conditionC() && conditionD || || conditionE ) conditionE) { { doSomething(a + b + c * ++d * e / f doSomething(a + b + c * ++d * e / f + + (g + h) * i / j - k * l); (g + h) * i / j - k * l); int aLongLongVariable = int aLongLongVariable a + b + c + d; = a + b + c + d; } }

    When wrapping string constant, put nonspace characters at the beginning of the next line.

    const char* data = "The quick brown " // NOT: const char* data = "The quick brown" "for jumps over a lazy dog."; " for jumps over a lazy dog.";

    Miscellaneous

    Type conversions must always be done explicitly. Always use "static_cast", "dynamic_cast", "const_cast" and "reinterpret_cast". Never rely on implicit type conversion.

    floatValue = static_cast<float>(intValue); // NOT: floatValue = intValue; // NOT: floatValue = (float) intValue;

    Variables should always be initialized where they are declared.

    int x = 0, y = 0, z = 0; float centerX = 0.0, centerY = 0.0, centerZ = 0.0; getCenter( &centerX, &centerY, &centerZ );

    Use of global variables should be minimized.

    Class variables should never be declared public, unless you have very strong reasons; Or you can use "struct" instead.

    Implicit test for 0 should not be used other than for boolean variables and pointers.

    if( nLines != 0 ) // NOT: if (nLines) if( value != 0.0 ) // NOT: if (value)

    Complex conditional expressions should be avoided. Introduce temporary boolean variables instead.

    bool isFinished = ( elementNo < 0 ) || ( elementNo > maxElement ); bool isRepeatedEntry = ( elementNo == lastElement ); if ( isFinished || isRepeatedEntry ) { // ... }

    // BETTER THAN: if ( ( elementNo < 0 ) || ( elementNo > maxElement )|| elementNo == lastElement ) { ... }

    Executable statements in conditionals should be avoided.

    File* fileHandle = open( fileName, "w" ); if( !fileHandle ) { // ... }

    // BETTER THAN: if (!(fileHandle = open(fileName, "w"))) { // ... }

    The use of magic numbers in the code should be avoided. Numbers other than 0 and 1 should be considered declared as named constants instead.

    const int MAX_DEPTH = 3; rayTracing(scene, light, camera, MAX_DEPTH);

    // NOT: rayTracing(scene, light, camera, 3);

    Floating point constants should always be written with decimal point and at least one decimal.

    double total = 0.0; // NOT: double total = 0; double speed = 3.0e8; // NOT: double speed = 3e8;

    double sum; sum = ( a + b ) * 10.0;

    "goto" should never be used.

    Always use "NULL" instead of "0" as an empty pointer.

    MyClass* classA = NULL; // NOT: MyClass* classA = 0; createMyClass( classA );

    if( classA == NULL ) // NOT: if (classA == 0) { doSomething(); }

    Never emit the "void" for functions take no parameter.

    int MyClass::getValue( void ) // NOT: int MyClass::getValue() { { // ... // ... } }

    When used as the whole expression, use "++i" instead of "i++". (Although they have the same meaning, we'd better have one single form in our project.)

    while( isFinished() ) // NOT: while (isFinished()) { { processLineNo(); processLineNo(); ++lineNo; lineNo++; } }

    for( int i = 0; i < MAX_DEPTH; ++i ) // NOT: for (int i = 0; i < MAX_DEPTH; i++) { { // ... // ... } }

    When used as function input parameters, classes, structs and other types should always be called in "const references" way instead of pointers. Pointers can only be used when you want to change the value of a parameter inside the fuction.

    void myFunction(const MyType& inputParameterA, // NOT: void myFunction(MyType inputParameterA, const MyType& inputParameterB, // NOT: MyType* inputParameterB, MyType* outputParameter) { MyType tempA = inputParameterA; MyType tempB = inputParameterB; *outputParameter = computeOutput( tempA, tempB ); }

    Comments

    Block comments

    Not recommended to use. Always use line comments "//".

    Line comments

    Space after double-slashes.

    If the comment and the code are in the same line, must be a space before double-slashes.

    Documentation Comments

    Don't use Doxygen tags and HTML tags not listed in this guide except for very special cases;

    Prefer natural formatting (indents, spaces, blank lines, "-" bulletins, etc.) to tags;

    Use Javadoc style (/** ... */ and @tags);

    Summary required. Blank line between summary and details is optional;

    Use doxygen not only in .h files, but also in .cpp files;

    Summaries and descriptions should be all full sentences, starting with a capital letter and ending with a period;

    Don't indent wrapped lines except in @param and @return;

    Take advantage of "Automatic link generation" as much as possible (see http://www.stack.nl/~dimitri/doxygen/autolink.html);

    Use () to indicate functions/methods in descriptions;

    We use JAVADOC_AUTOBRIEF, so the first sentence of a description is treated as the brief introduction, no matter whether there is a line break;

    Don't omit template arguments when (partially) specializing a template, otherwise doxygen can't correctly generate doc for the (partial) specialized template.

    Warnings reported by doxygen should be eliminated as many as possible.

    If short enough to put in one line, space after the beginning of the comment.

    If short enough to put in one line, space before the end of the comment.

    Sample code:

    /** This function intend to be a sample. */ int sampleCode(void);

    If long enough, no comments body in the first line and the last line.

    If long enough, every line must begin with a space and an asterisk.

    Must be a "blank" line before "@param".

    Sample code:

    /** * This is another sample of the documentation * comments. This comment is long enough so * we have to wrap it into mutiple lines. * @param sample sample data. * @return the sample data plus one. */ int addOne(int sample) { return ++sample; }

    @a parameter-name

    Used in descriptions for methods or functions to indicate the following word is a parameter.

    @c word

    The following word is display using a typewriter font to indicate the word is from source code. Use <code>...</code> for multiple words or multiple lines or to separate the 's' in plural forms.

    <code>source-code</code>

    See @c.

    @deprecated description

    @dot dotsources @enddot

    @f$ formula @f$

    @f[ formula @f]

    @param parameter-name parameter-description

    Use [out] to indicate this parameter is an out parameter;

    Use [in,out] to incidate this parameter is both in and out;

    Don't use [in] for normal in parameters;

    The first character of the parameter description is not capitalized;

    If longer than 1 line, indent the following lines 4 characters;

    All or none for a function;

    Don't align the descriptions for multiple @param's;

    @return description-of-the-return-value

    The first character of the description is not capitalized;

    If longer than 1 line, indent the following lines 4 characters;

    @see references

    Creates a link to other identifiers. The paragraph need not be ended with a period.

    @since text

    An example:

    /** * Resizes the image to specified @a width and @a height via reduced resolution. * The above sentence will be treated as brief. Here are some more details. These * sentences are treated as in one paragraph. * * And more details requiring a new paragraph. * @param width no need to comment about a parameter if its name is descriptive * enough. Indent 4 characters if a param line wraps. * @param height parameters should be documented all or none. If you document one * parameter, you must document all the others (leave the description blank * if nothing to say), to let doxygen check the consistency of docs. * @param[out] an output parameter. @c 0 if ... * @return @c true if succeeds. */ bool SetSrcSize(size_t width, size_t height, int* output);

    Another example

    /** * Usage of lists: * - Starting with a '-' and indent 2 characters to create a bulletin item; * - Another item; * - Indent more to create sub items; * - Another sub item; * -# Numbered sub item; * -# Another numbered sub item; * - Long lines in lists should be * aligned if wrapped; * - The last one. */

  • 相关阅读:
    一次“半面试”——汉得
    检查随机序列重复[Java]
    设计模式 工厂方法(Factory Method Pattern)转载
    sprintf用法详解
    MFC ComboBox的使用
    Visual Studio 2008 中程序路径配置 .
    Visual Studio 2008 、 Windows 环境变量介绍 和 如何在文件中引用环境变量 .
    MFC总结之CListCtrl用法及技巧(二) .
    C/C++中Sqlite使用简介
    getenv、setenv函数 获取和设置系统环境变量
  • 原文地址:https://www.cnblogs.com/wenshanzh/p/2760330.html
Copyright © 2011-2022 走看看