编程规范_编程规范和范例 - CSDN
精华内容
参与话题
  • C/C++编程规范整理

    万次阅读 多人点赞 2018-11-22 09:43:10
    一、基本准备工作 1、设计工程目录结构 (1)基本原则: 【1】工程本身的文件、项目编译生成的中间文件放一个文件夹; 【2】最终生成的目标文件单独放一个文件夹;...【3】如果有工程依赖的库文件等单独放一个...

    一、基本准备工作

    1、设计工程目录结构

    (1)基本原则:

    【1】工程本身的文件、项目编译生成的中间文件放一个文件夹;

    【2】最终生成的目标文件单独放一个文件夹;

    【3】如果有工程依赖的库文件等单独放一个文件夹;

    【4】用户代码文件放单独一个文件夹,或者将头文件和源文件单独分开放置;

    【5】用户代码文件里面如果有比较重要的功能模块单独放一个文件夹,如陀螺仪,气压计,光感,音乐,灯效,图片,字库等。

    【6】重要的项目资料单独放一个文件夹保存,如硬件原理图,软件框架图,通信协议,复杂重要功能的说明等等。

    【7】必须维护一个软件版本升级记录文档,也可以在某个主要的代码文件内维护(不推荐)。

    【8】可以为一些代码阅读工具需要的生成文件开一个文件夹,如SourceInsight。

    (2)举例

    【1】linux

    【2】arm9

    【3】stm32

    2、版权和版本的申明

    (1)基本原则:

    位置:位于说明文件或者源文件头部,或者源文件和头文件都加上版本声明。

    内容:版权、文件名,概要;版本号-作者-日期+代码更新信息,备注信息;

    (2)举例:

    【1】

    @头文件注释带上函数功能的简要说明,但如果在头文件有对外接口的函数声明,则在函数声明上进行函数功能的注释。

    【2】源文件,说明此模块功能,主要函数,被其他函数调用的接口

    【3】源文件和头文件都加上版本声明

    STM32F10x_FWLib/stm32f10x_adc.h
    /********************************************************************************
      * @file    stm32f10x_adc.h
      * @author  MCD Application Team
      * @version V3.5.0
      * @date    11-March-2011
      * @brief   This file contains all the functions prototypes for the ADC firmware 
      *          library.
      ******************************************************************************
      * @attention
      * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
      ******************************************************************************
      */STM32F10x_FWLib/stm32f10x_adc.c   
    /**  ******************************************************************************
      * @file    stm32f10x_adc.c
      * @author  MCD Application Team
      * @version V3.5.0
      * @date    11-March-2011
      * @brief   This file provides all the ADC firmware functions.
      ******************************************************************************
      * @attention
      * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
      ******************************************************************************  */

    3、头文件的结构和作用

    (1)头文件开头处的版权和版本声明。

    (2)预处理块。

    #ifndef/#def/#endif  防止头文件被重复引用。

    (3)其他头文件、函数和类结构声明等。

    [1]#include <filename.h> :引用标准库的头文件,编译器将从标准库目录开始搜索。

    #include “filename.h”:引用非标准库的头文件,编译器从用户的工作目录开始搜索。

    [2]变量和函数,头文件只存声明,不存定义。

     

    二、排版和代码行基本规则

    目的:使代码布局整齐清晰,便于阅读和理解。

    1、起始代码的缩进:

          函数或过程的开始、结构的定义及循环、判断等语句中的代码都要采用缩进风格, case语句下的情况处理语句也要遵从语句缩进要求。

    2、缩进规则:

    【1】缩进风格:程序块要采用缩进编写,缩进的空格数一般为4个。

    【2】不用TAB用空格:以免用不同的编辑器阅读程序时,因 TAB 键所设置的空格数目不同而造成程序布局不整齐。

    3、程序块大括号对齐:

    【1】WIN和嵌入式底层:程序分界符" {"和“ }”:应该独占一行并且两者位于同一列,同时与引用他们的语句左对齐;

    【2】linux:‘{’位于上一行的行末,此时‘}’与‘{’所在行的行首对齐,‘{’前至少有一个空格。

    for (...) { //多在linux底层和linux应用编程,单片机嵌入式未见此种用法。

    ... // program code

    }  

    ===

    for (...) //windows一般统一用下面这个格式。。。

    {

    ... // program code

    }

    4、空行:

          每个函数定义结束后,相对独立的程序块之间(逻辑密切除外)、变量说明和程序块中间之后必须加空行。

    5、标志符语句独占一行:

          if、 for、 do、 while、 case、 switch、 default等语句自占一行,不论语句的执行语句部分无论多少都要加括号{}。

    6、长句拆分:

    (1)单行单语句,一行不超过一个语句:

          不允许把多个短语句写在一行中,即一行只写一条语句。

    (2)语句的拆分:

          代码长度最好控制在70-80个字符以内,较长的语句( >80字符)要分成多行书写。

          函数或过程中的参数较长,循环、判断等语句中有较长的表达式或语句,要进行适应的划分,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读。

    【1】report_or_not_flag = ((taskno < MAX_ACT_TASK_NUMBER)

                                                && (n7stat_stat_item_valid (stat_item))

                                                && (act_task_table[taskno].result_data != 0));

    【2】for (i = 0, j = 0; (i < BufferKeyword[word_index].word_length)

                                      && (j < NewKeyword.word_length); i++, j++)

    【3】 CANx->sTxMailBox[transmit_mailbox].TDLR = (((uint32_t)TxMessage->Data[3] << 24) |

                                                                                           ((uint32_t)TxMessage->Data[2] << 16) |

                                                                                           ((uint32_t)TxMessage->Data[1] << 8) |

                                                                                            ((uint32_t)TxMessage->Data[0]));

    7、代码行内的空格和修饰符、括号等:

    【1】关键字后留空格:C语言的32个关键字,如if/while/do/case ();

    if (NewState != DISABLE)

    【2】函数名后不留空格:紧跟括号( , 区别关键字.

    void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number);

    【3】紧跟:(号向后紧跟, )和,和;向前紧跟,不留空格;   int a, b, c;

    【4】二元操作符:前后加空格;==对等操作

    【5】一元操作符:前后不加空格;如"[ ]"和" . "和"->"这类操作符前后不加空格.==关系密切的立即操作符

    【6】对于表达式比较长的for语句和if语句,为了紧凑起见可以适当地去掉一些空格:

               if ((a>=b) && (c<=d))           // 良好的风格

               for (i=0; i<10; i++)            // 良好的风格

               x = a<b ? a:b;               // 良好的风格

    ==

    【7】修饰符紧靠变量名:不会被误认: int *x, y;

    ==

    【8】注意运算符的优先级,并用括号明确表达式的操作顺序:

            if ((a | b) < (c & d))

            if ((a>=b) && (c<=d))           // 良好的风格

     

    三、注释  

    目的:增加代码的可读性,帮助更好的理解程序。

    1、必要性

        在代码的功能、意图层次上注释,解释代码的目的、功能和采用的方法,提供代码外的信息,帮助理解,已经清楚的语句就不要重复注释。

    2、自注释

        通过对函数或过程、变量、结构等正确的命名以及合理地组织代码的结构。

    3、及时性和准确性

        边写代码边注释,改了代码也要改注释,不用的注释要删除。

    4、注释的量

        一般源程序有效注释量必须在20%以上。必须是有助于对程序的理解,准确易懂、清楚无二义性、简洁明了

    5、注释格式和语言尽量统一

    【1】格式尽量统一用/* */。

    【2】格式如果不能非常留意准确用英文表达,则统一用中文,不要中英文混用。

    6、注释所在位置和排版

    【1】注释放在语句上方或者右方不放在下方,注释放在上方时必须和上面的代码用空行隔开。

    【2】注释应该与所描述内容进行同样缩排保持整齐,方便阅读。

    7、注释文件

    【1】如开头部分所说,基本说明性文件,.h文件、.inc文件、编译说明文件等。注释的内容类似头文件注释格式。

    【2】如开头部分所说,重要的源文件,注释内容除写上版权这些以外,注明模块功能,主要实现函数,对外接口函数,修改记录等等。

    8、注释函数

    一般包含 函数功能,输入参数,输出参数,返回值,备注信息,调用列表等。

     

    @实例:

    /**

    * @brief /Description: Returns the frequencies of different on chip clocks.

    * @param RCC_Clocks: pointer to a RCC_ClocksTypeDef structure which will hold

    * the clocks frequencies.

    * @note The result of this function could be not correct when using

    * fractional value for HSE crystal.

    * @retval None

    */

    void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks)

    @返回值:

    [1] Returns negative errno, else the number of messages executed.

    [2]* Returns negative errno, or else the number of bytes read/written.

    9、代码主要注释内容

    【1】有实际意义的常量、变量、宏:除非其自注释,不然都加上注释。

    【2】结构体声明(含数组、结构体、类、枚举等):其注释在上方,结构体中的域在其右方注释。

    /* sccp interface with sccp user primitive message name */

    enum SCCP_USER_PRIMITIVE

    {

        N_UNITDATA_IND, /* sccp notify sccp user unit data come */

    }

    【3】分支语句(条件、循环、switch):每一功能的注释。

    【4】大程序块结束:加上注释,便于阅读,如if,while,for这些语句的多层嵌套。

    【5】全局变量:要有比较详细的注释,包含其功能、取值范围、调用者和注释事项等。

    四、标识符命名

    标识shi符就是程序员自己规定的具有特定含义的词,比如类名称,属性名称,变量名和函数名等。标识符由字母、数字、下划线“_”组成,关键字不能作为标识符。

    1、基本规则

    (1)含义精确:标识符应该 直观且易读,望文知意。要使用准确的英文字符.。

    如:CurrentValue不写成NowValue

    (2)长度精简:“ min-length && max-information”--最精确精简的词。---长但不要太长

    @缩写:可用大家基本可用理解的缩写。temp=>tmp; message=>msg;

    (3)变量名组成:使用"名词"或者“形容词+名词”;

    @建议除了有具体含义外,还要能表明变量类型:——下面讲的匈牙利命名规则

    int iwidth; // i表明该变量为int型,width指明是宽度

    (4)函数名组成:全局函数的名字应当使用“动词”或者“动词+名词”(动宾词组)。类的成员函数应当只使用“动词”,被省略掉的名词就是对象本身。

    DrawBox();                           // 全局函数

    box->Draw();                        // 类的成员函数

    @嵌入式中,如果是相关的模块驱动,前面加上模块名。

    void BCT3286_SPI_Init(void);

    (5)常量:全用大写的字母,用下划线分割单词。

         const int MAX       = 100;

         const int MAX_LENGTH   = 100;

         #define MAX_ARRAY    100

         #define SHOW_DTDATA  (WM_USER+0x101) //记得带上括号

    (6)特殊软件库前缀:为了防止某一软件库中的一些标识符和其它软件库中的冲突,可以为各种标识符加上能反映软件性质的前缀。例如三维图形标准OpenGL的所有库函数均以gl开头,所有常量(或宏定义)均以GL开头。

    (7)不要出现:

    [1]仅靠大小写区分的相识标识符。

    [2]相同命名的局部和全局变量。

    [3]尽量避免名字中出现数字编号,如Value1,Value2等,除非逻辑上的确需要编号。

    (8)切合操作系统: 命名要切合操作系统与开发工具的风格

    @Windows和stm32:

    [1]变量:标识符采用首字母小写的“大小写”混排addChild;

    [2]类名和函数:所有首字母大写的大小写混合,AddChild;

    ==widows中:

    [1]变量和参数用小写字母开头的单词组合而成。

       BOOL flag;

       int drawMode;

    [2]类名和函数名用大写字母开头的单词组合而成。

    class LeafNode;              // 类名

    void SetValue(int value);  // 函数名

    ==stm32中:同windows,差别在如果是底层驱动函数要加上模块名。

    ---------

    @linux应用程序和ARM9嵌入式:

    函数和变量这些标识符采用全小写加下划线add_child。

    1)变量名必须意义准确

    例如有一个变量用于保存图书的数目,可以命名为number_of_book或者num_of_book。不建议使用i,因为它没有意义。也不建议使用number或book,因为意义不准确。

    2)不建议大小写混用

    如定义一个计数变量,int nCount;这在Windows中是一个很好的变量名,其中nCount的首字母n用来说明这个变量的类型是int。但在Linux下不建议大小写混合使用,一般标识符只由小写字母,数字和下划线构成。

    3)在失去意义的情况下,尽量使用较短的变量名

    例如有一个变量,用于暂时存储一个计数值,把变量命名为tmp_count显然要比this_is_a_temperary_counter好。

    4)不采用匈牙利命名法表示变量的类型

    如int nCount;n用于说明变量的类型,在Linux中不建议这样命名变量。

    5)函数名应该以动词开头

    因为函数是一组具有特定功能的语句块。比如一个函数,它用于取得外部输入的数值,则可以命名为get_input_number。

    IIS_pin_init();

    set_IIS_for_record();

    start_IIS();

    6)尽量避免使用全局变量

    (8)不要出现:

    [1]仅靠大小写区分的相识标识符。

    [2]相同命名的局部和全局变量。

    [3]尽量避免名字中出现数字编号,如Value1,Value2等,除非逻辑上的确需要编号。

     

    2、匈牙利命名法(多用在上位机语言):

    在变量名和函数名中加入前缀,以增进人们对程序的理解。

    基本原则是:变量名=属性+类型+对象描述,其中每一对象的名称都要求有明确含义,可以取对象名字全称或名字的一部分。

    (1)变量属性,前缀

    g_  全局变量(表示global)

    s_   静态变量 (表示static) static int s_initValue;  

    c_  常量

    m_ c++类成员变量(表示member)这样可以避免数据成员与成员函数的参数同名。

    void Object::SetValue(int width, int height)

    {

         m_width = width;

    m_height = height;

    (2)类型部分:

    数组 a

    指针 p

    函数 fn

    无效 v

    句柄 h

    长整型 l

    布尔 b

    浮点型(有时也指文件) f

    双字  dw

    字符串  sz

    短整型  n

    双精度浮点 d

    计数 c(通常用cnt)

    字符 ch(通常用c)

    整型 i(通常用n)

    字节 by

    字 w

    实型 r

    无符号 u

    (3)描述部分:

    最大 Max

    最小 Min

    初始化 Init

    临时变量 T(或Temp)

    源对象 Src

    目的对象 Dest

    (4)举例:

    hwnd : h 是类型描述,表示句柄, wnd 是变量对象描述,表示窗口,所以 hwnd 表示窗口句柄;

    pfnEatApple : pfn 是类型描述,表示指向函数的指针, EatApple 是变量对象描述,所以它表示指向 EatApple 函数的函数指针变量。

    g_cch : g_ 是属性描述,表示全局变量,c 和 ch 分别是计数类型和字符类型,一起表示变量类型,这里忽略了对象描述,所以它表示一个对字符进行计数的全局变量。

     

    五、宏、全局变量和其他注意

    1、宏的使用+定义规范:

    (1)由来:不易理解的数字和常量则用有意义的枚举或者宏来替代:

    #define BUFF_SIZE          1024

    input_data = (char *)malloc(BUFF_SIZE);

    (2)宏定义规范

    【1】括号:宏定义表达,需要完整的括号。

    #define GET_AREA(a,b)     ((a) * (b))

    【2】大括号:宏中有多条语句,应将语句放在一对大括号中。

    #define INTI_RECT_VALUE( a, b ) {\

                a = 0;\

                b = 0;\

    }

    2、全局变量:

    【1】避免使用: 尽量避免使用,它占用程序空间,同时增大了模块间的耦合性,不利于软件维护。

    【2】规范:应明确其含义、作用、取值范围。明确全局变量与操作此变量的函数的关系,如创建、访问、修改。

    3、其他原则

    [1]专一:一行代码只做一件事情,如只定义一个变量,或只写一条语句。---易阅读和注释。

    [2]就近原则:尽可能在定义变量的同时初始化该变量。

    [3]数据大小端统一:通信协议中数据的大小端要和整个团队形成统一。

    六、函数和类:

    ====函数

    【1】函数名:应能准确描述函数功能,一般以动词加宾语的形式;print_record

    【2】参数个数:不宜过多,1-3个为好;

    【3】返回值:清楚、明了,让调用者不易忽视错误情况。每种错误的返回值要清晰、明确,防止调用者误用;

    @linux中函数的返回值:正常的时候返回0,错误的时候返回-1或者小于零的错误码。

    @WINDOWS和stm32函数返回值:

    如果GetCommState()函数调用成功,则返回值大于零。若函数调用失败,则返回值为零,如果想得到进一步的错误信息,可以调用GetLastError()函数来获取。

    【4】输入参数:检查其有效性,如指针型参数判断是否为空,数组成员是否越界等等;

    【5】规模:限制在200行以内(不含空行和注释行);

    【6】功能专一:一个函数完成一个特定功能;

    【7】功能可预测:输入数据相同,能得到可预期的输出;

    【8】代码重用:多段代码重复做一件事,考虑将重复功能实现成一个函数;

    【9】独立性:减少与其他函数的联系,提高可读性、维护性和效率。

    避免函数本身和函数间的递归调用,递归影响可读性和系统资源如栈空间。

    ====类的版式

    类可以将数据和函数封装在一起,其中函数表示了类的行为(或称服务)。类提供关键字public、protected和private,分别用于声明哪些数据和函数是公有的、受保护的或者是私有的。

    主张提倡的书写方式:将public类型的函数写在前面,而将private类型的数据写在后面,这种版式的程序员主张类的设计“以行为为中心”,重点关注的是类应该提供什么样的接口(或服务)。即首先考虑类应该提供什么样的函数。“这样做不仅让自己在设计类时思路清晰,而且方便别人阅读。因为用户最关心的是接口,谁愿意先看到一堆私有数据成员!”

    class A

    {

     public:

      void Func1(void);

      void Func2(void);

      …

     private:

    int   i, j;

    float  x, y;

        …

    }

     

     

     

    展开全文
  • 编程规范

    千次阅读 2019-08-11 11:19:36
    一:命名风格 代码中代码严禁拼音和英文混合的方式,更不允许直接用纯中文标识 在POJO类中布尔类型的变量不要加is前缀。例如isDeleted变量,RPC框架在反向解析的时候以为属性是delect 禁止POJO类属性xxx同时出现...

    一:命名风格

    • 代码中代码严禁拼音和英文混合的方式,更不允许直接用纯中文标识
    • 在POJO类中布尔类型的变量不要加is前缀。例如isDeleted变量,RPC框架在反向解析的时候以为属性是delect
    • 禁止POJO类属性xxx同时出现isXxx()和getXxx()方法。因为框架在属性方法提取时并不能保证哪个方法被优先调用得到
    • 接口类中的方法和属性不要添加任何修饰符号,保持代码的间接性
      1. 接口方法签名:void commit();
      2. 接口基础常量:String COMPANY = “dafang”;
    • 代码格式
    public static void main(String[] args) {
    		// 缩进4个空格(注释//后必须加一个空格)
    		String say = "hello";
    		// 运算的左右必须有一个空格
    		int flag = 0;
    		// 关键词if与括号之间必须有1个空格,括号内的f与左括号、0与右括号之间不需要空格
    		if (flag == 0) {
    			System.out.println(say);
    		}
    		// 左大括号前加空格且不换行;左大括号后换行
    		if (flag == 1) {
    			System.out.println("word");
    		// 左大括号前换行,右大括号后有else,不用换行
    		}else {
    			System.out.println("ok");
    		// 在右大括号后直接结束,则必须换行
    		}
    	}
    
    • 所有的覆写方法,必须加@Override
    • 基本数据和包装数据类型的使用标准
      1. 所有的POJO类属性必须使用包装数据类型
      2. RPC(Remote Promote Call)方法的返回值和参数必须使用包装数据类型
      3. 所有的局部变量使用基本数据类型

      说明: 数据库的查询结果可能是null,因为自动拆箱,所有用基本数据类型接收有NPE(NullPointerException)

    • 构造方法里禁止加入任何业务逻辑,如果有初始化逻辑,请放在init方法中
    • 在setter/getter方法中,参数名称和类成员变量名称一致。不要增加业务逻辑,否则会增加排查问题的难度
      错误示例
      public Integer getData() {
      		if (condition) {
      			return this.data + 100;
      		}else {
      			return this.data - 100;
      		}
      	}
      
    • 集合操作中需要注意的几点
      1. 在foreach循环里进行元素的remove/add操作,会报ClassCastException
      2. 使用迭代器Iterator遍历时使用集合自带的自带的remove()会报ClassCastException,可以使用迭代器自带的remove() 案例
      3. jdk7后对于数据排序需要返回等于0的情况,之后版本排序可以看之前的博客java8让排序更加优雅
      4. 集合初始化时需要给定初始值大小initiaCapacity = (需要存储的元素个数/负载因子)+1

        假设HashMap 需要放置1024个元素,因为没有设置初始大小。元素的增加导致容量被迫扩大7次,resize需要重建hash表,这严重影响性能


    二:控制语句

    • 在switch块中每个case要么通过break/return等来终止,要么注释说明程序将执行到哪一个case为止。每个块内必须包含一个default,哪怕它什么代码也没有。除非使用jdk12

      //新特性
      switch (day) {
          case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
          case TUESDAY                -> System.out.println(7);
          case THURSDAY, SATURDAY     -> System.out.println(8);
          case WEDNESDAY              -> System.out.println(9);
      }
      //以及在表达式返回值
      int numLetters = switch (day) {
          case MONDAY, FRIDAY, SUNDAY -> 6;
          case TUESDAY                -> 7;
          case THURSDAY, SATURDAY     -> 8;
          case WEDNESDAY              -> 9;
      };
      
    • 在if / else / for /while /do语句中必须使用大括号,哪怕只有一行代码

    • 在高并发场景中,避免使用“等于”来作为中断条件。例如判断奖品等于0终止发放,但是由于并发处理会导致数量瞬间变为负数,这样的话活动就无法截至

    • 不要在条件判断中执行其他复杂的语句,可以将复杂的逻辑判断的结果赋值给一个有意义的布尔变量名,可以提高可读性

      		// 正例
      		final boolean existed = (file.open(name,"w")!=null) && (...) || (...);
      		if (existed) {
      			
      		}
      		// 反例
      		if ( (file.open(name,"w")!=null) && (...) || (...)) {
      			
      		}
      
    • 避免采用取反逻辑运算符

      说明 取反逻辑不利于快速理解,并且去反逻辑写法必然存在对应的正向逻辑写法
      正例:使用if (x < 628)来表达x小于628
      反例:使用if (!(x >= 628))来表达x小于628

    三:控制语句

    • 线程资源必须通过线程池提供,不允许在应用中自行的显示创建线程

      说明 使用线程池的好处减少在创建和销毁线程上所消耗的时间及系统资源,解决资源不足的问题。如果不使用线程池,可能会造成大量同类线程二导致消耗完内存或者“过度切换”的问题

    • 必须回收自定义的ThreadLocal变量,尤其在线程池场景下
    • 在高并发场景中,同步调用应该去考量锁的性能损耗。能用无锁结构就不要用锁。能用锁区块,就不要用整个方法体。能用对象锁,就不要用类锁。使加锁的代码块工作量尽可能小
    • HashMap在容量不够进行resize时,由于高并发可能出现死锁,导致cpu占用率飙升,在开发中可以使用其他数据结构(几种线程安全的map)或者加锁来规避此风险。

    四:注释规约

    • 类、类属性、类方法的注释必须使用Javadoc规范,使用/*内容/格式,不得使用//xxx方式
    • 所有的抽象方法(包括接口中的方法)必须使用javadoc注释,除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现了什么功能

      说明 对子类的实现要求,或者调用注意事项,轻一并说明

    • 所有的类必须添加创建者和创建时间
    • 如果使用的是ecplise的话需要注意,每次格式化的时候。可能会将注释代码也格式化,为了不改变注释风格需要设置Preferences->java->Code style->Formatter点击new。然后点击Edit->Comments再将下面两个选框√去掉
      在这里插入图片描述
    • 在修改代码的同时要对注释进行相应的修改,尤其是参数、返回值、异常、核心的逻辑

      说明 代码与注释更新不同步,就像网络与导航软件更新不同步。如果导航软件更新严重滞后,就失去了导航的意义

    • 及时清理不在使用的代码段或配置信息。避免程序过度臃肿,代码冗余。
    • 谨慎注释掉代码,要在上方详细说明,而不是简单地注释掉,如果无用则删除
      1. 如果后续要恢复此段逻辑代码,没有备注信息,难以知晓注释动机。无用则删掉,如果要查阅历史代码,查看代码仓库(svn git)看历史版本即可
      2. 对于暂时注释掉后续会恢复使用的代码片段,在注释代码上方,统一规定使用三个斜杠///来说明注释代码的理由
    展开全文
  • Google C++编程规范 (中文版)

    万次阅读 多人点赞 2018-09-04 16:40:35
    点击下面的超级链接即可: Google 开源项目风格指南  C++ 风格指南 - 内容目录 0. 扉页 0.1 译者前言 0.2 背景 1. 头文件 1.1.... 1.2.... 1.3.... 1.4.... 1.5.... 译者 (YuleFox) 笔...

    点击下面的超级链接即可:

    展开全文
  • 软件开发编程规范及原则

    万次阅读 2019-03-08 11:37:15
    推荐 分享一个大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到人工智能的队伍中来!http://www.captainbed.net/strongerhuang 我的网站:https://www.strongerhuang.com ...不...

    推荐

    分享一个大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到人工智能的队伍中来!http://www.captainbed.net/strongerhuang

     

    我的网站:https://www.strongerhuang.com

    我的知乎:https://www.zhihu.com/people/strongerHuang.com

     

    、写在前面

    不知道大家有没有这样的感受:看到不规范(杂乱差)的代码,瞬间就没有看下去的欲望了。

     

    相信大家看到标题都应该能明白编程的规范及原则对于每一个软件开发的工程师来说是多么重要。

     

    初学者编写测试程序、小的模块程序也许不能感受它的重要性;但有经验及大型项目开发的人就知道程序的规范性对他们来说是有多么的重要。

     

    Ⅱ、关于编程规范及原则

    编程规范也就是编写出简洁、可维护、可靠、可测试、高效、可移植的代码,提高产品代码的质量。

    本文针对嵌入式,主要结合C语言编程的规范给大家讲述。

     

    1.头文件

    对于C语言来说,头文件的设计体现了大部分的系统设计,不合理的头文件布局是编译时间过长的原因

     

    有很多人将工程中所有的头文件包含在一个include.h文件中,然后在每一个.c源代码文件中包含include.h头文件,这样做可以让代码看上去简洁,但实际忽视了编译效率问题,而且代码的可移植性也不好。

     

    原则

    A.头文件中适合放置接口的声明,不适合放置实现;

    B.头文件应当职责单一;

    C.头文件应向稳定的方向包含。

     

    规则:

    A.每一个.c文件应有一个同名.h文件,用于声明需要对外公开的接口;

    B.禁止头文件循环依赖;

    C..c/.h文件禁止包含用不到的头文件;

    D.头文件应当自包含;

    E.总是编写内部#include保护符( #define 保护);

    F.禁止在头文件中定义变量;

    G.只能通过包含头文件的方式使用其他.c提供的接口,禁止在.c中通过extern的方式使用外部函数接口、变量;

    H.禁止在extern "C"中包含头文件。

     

    建议:

    A.一个模块通常包含多个.c文件,建议放在同一个目录下,目录名即为模块名。为方便外部使用者,建议每一个模块提供一个.h,文件名为目录名;

    B.如果一个模块包含多个子模块,则建议每一个子模块提供一个对外的.h,文件名为子模块名(降低接口使用者的编写难度);

    C.头文件不要使用非习惯用法的扩展名,如.inc;

    D.同一产品统一包含头文件排列方式。

     

    2.函数

    函数设计的要点:编写整洁的函数,同时把代码有效组织起来

    函数整洁的要求:代码简单直接、不隐藏设计者的意图、用干净利落的抽象和直截了当的控制语句将函数有机组织起来。

     

    原则:

    A.一个函数仅完成一件功能;

    B.重复代码应该尽可能提炼成函数.

     

    规则:

    A.避免函数过长,新增函数不超过100行(非空非注释行);

    B.避免函数的代码块嵌套过深,新增函数的代码块嵌套不超过4层;

    C.可重入函数应避免使用共享变量;若需要使用,则应通过互斥手段(关中断、信号量)对其加以保护;

    D.对参数的合法性检查,由调用者负责还是由接口函数负责,应在项目组/模块内应统一规定;

    E.对函数的错误返回码要全面处理;

    F.设计高扇入,合理扇出(小于7)的函数;

    G.废弃代码(没有被调用的函数和变量)要及时清除。

     

    建议:

    A.函数不变参数使用const;

    B.函数应避免使用全局变量、静态局部变量和I/O操作,不可避免的地方应集中使用;

    C.检查函数所有非参数输入的有效性,如数据文件、公共变量等;

    D.函数的参数个数不超过5个;

    E.除打印类函数外,不要使用可变长参函数;

    F.在源文件范围内声明和定义的所有函数,除非外部可见,否则应该增加static关键字。

     

    3.标识符命名与定义

    程序命名是一个关键,如果命名不规范,自己写的代码,时间长了恐怕连自己都不知道是什么意思了。

     

    3.1通用命名规则

    常见命名风格:

    A.用下划线„_‟分割,如text_mutex;

    B.大小写字母混用,如ReadRFCText。

     

    规则:

    A.标识符的命名要清晰、明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避免使人产生误解;

    B.除了常见的通用缩写以外,不使用单词缩写,不得使用汉语拼音;

    C.产品/项目组内部应保持统一的命名风格.

     

    建议:

    A.用正确的反义词组命名具有互斥意义的变量或相反动作的函数等;

    B.尽量避免名字中出现数字编号,除非逻辑上的确需要编号;

    C.标识符前不应添加模块、项目、产品、部门的名称作为前缀;

    D.平台/驱动等适配代码的标识符命名风格保持和平台/驱动一致;

    E.重构/修改部分代码时,应保持和原有代码的命名风格一致。

     

    3.2 文件命名规则

    因为不同系统对文件名大小写处理会不同,建议文件命名统一采用小写字符。

     

    3.3 变量命名规则

    首先,全局变量十分危险,通过前缀使得全局变量更加醒目, 促使开发人员对这些变量的使用更加小心。

    其次,从根本上说,应当尽量不使用全局变量,增加g_和s_前缀,会使得全局变量的名字显得很丑陋,从而促使开发人员尽量少使用全局变量。

     

    规则:

    A.全局变量增加“g_”前缀,静态变量增加“s_”前缀;

    B.禁止使用单字节命名变量,但允许定义i、 j、 k作为局部循环变量;

    C.使用名词或者形容词+名词方式命名变量。

     

    3.4 函数命名规则

    A.函数命名应以函数要执行的动作命名,一般采用动词或者动词+名词的结构;

    B.函数指针除了前缀,其他按照函数的命名规则命名。

     

    3.5 宏的命名规则

    A.对于数值或者字符串等等常量的定义,建议采用全大写字母,单词之间加下划线„_‟的方式命名(枚举同样建议使用此方式定义);

    B.除了头文件或编译开关等特殊标识定义,宏定义不能使用下划线„_‟开头和结尾。

     

    4.变量

    原则:

    A.一个变量只有一个功能,不能把一个变量用作多种用途;

    B.结构功能单一;不要设计面面俱到的数据结构;

    C.不用或者少用全局变量。

     

    规则:

    A.防止局部变量与全局变量同名;

    B.通讯过程中使用的结构,必须注意字节序;

    C.严禁使用未经初始化的变量作为右值;

     

    建议:

    A.构造仅有一个模块或函数可以修改、创建,而其余有关模块或函数只访问的全局变量,防止多个不同模块或函数都可以修改、创建同一全局变量的现象;

    B.使用面向接口编程思想,通过API访问数据:如果本模块的数据需要对外部模块开放,应提供接口函数来设置、获取,同时注意全局数据的访问互斥;

    C.在首次使用前初始化变量,初始化的地方离使用的地方越近越好;

    D.明确全局变量的初始化顺序,避免跨模块的初始化依赖;

    E.尽量减少没有必要的数据类型默认转换与强制转换。

     

    5.宏、常量

    因为宏只是简单的代码替换,不会像函数一样先将参数计算后,再传递。

     

    规则:

    A.用宏定义表达式时,要使用完备的括号;

    不规范:#define RECTANGLE_AREA(a, b) a * b

    规范:#define RECTANGLE_AREA(a, b) ((a) * (b))

     

    B.将宏所定义的多条表达式放在大括号中;

    C.使用宏时,不允许参数发生变化;

    #define SQUARE(a) ((a) * (a))

    int a = 5;

    int b;

    不规范:

    b = SQUARE(a++);

     

    规范:

    b = SQUARE(a);

    a++;

     

    建议:

    A.除非必要,应尽可能使用函数代替宏;

    B.常量建议使用const定义代替宏;

    C.宏定义中尽量不使用return、 goto、 continue、 break等改变程序流程的语句。

     

    6.注释

    原则:

    A.优秀的代码可以自我解释,不通过注释即可轻易读懂;

    B.注释的内容要清楚、明了,含义准确,防止注释二义性;

    C.在代码的功能、意图层次上进行注释,即注释解释代码难以直接表达的意图,而不是重复描述代码。

     

    规则:

    A.修改代码时,维护代码周边的所有注释,以保证注释与代码的一致性。不再有用的注释要删;

    B.文件头部应进行注释,注释必须列出:版权说明、版本号、生成日期、作者姓名、工号、内容、功能说明、与其它文件的关系、修改日志等,头文件的注释中还应有函数功能简要说明;

    C.函数声明处注释描述函数功能、性能及用法,包括输入和输出参数、函数返回值、可重入的要求等;定义处详细描述函数功能和实现要点,如实现的简要步骤、实现的理由、 设计约束等;

    D.全局变量要有较详细的注释,包括对其功能、取值范围以及存取时注意事项等的说明;

    E.注释应放在其代码上方相邻位置或右方,不可放在下面。 如放于上方则需与其上面的代码用空行隔开,且与下方代码缩进相同;

    F.避免在注释中使用缩写,除非是业界通用或子系统内标准化的缩写;

    G.同一产品或项目组统一注释风格。

     

    建议:

    A.避免在一行代码或表达式的中间插入注释;

    B.文件头、函数头、全局常量变量、类型定义的注释格式采用工具可识别的格式。

     

    7.排版与格式

    规则:

    A.程序块采用缩进风格编写, 每级缩进为4个空格;

    B.相对独立的程序块之间、变量说明之后必须加空行;

    C.一条语句不能过长,如不能拆分需要分行写。一行到底多少字符换行比较合适,产品可以自行确定;

    D.多个短语句(包括赋值语句)不允许写在同一行内,即一行只写一条语句;

    E.if、 for、 do、 while、 case、 switch、 default等语句独占一行;

    F.在两个以上的关键字、变量、常量进行对等操作时,它们之间的操作符之前、之后或者前后要加空格; 进行非对等操作时,如果是关系密切的立即操作符(如->),后不应加空格;

    G.注释符(包括„/*‟„//‟„*/‟)与注释内容之间要用一个空格进行分隔。

     

    Ⅲ、说明

    关于编程规范、原则等相关的文章在国外很多优秀的工程师都总结的有:

    http://www.artima.com/weblogs/viewpost.jsp?thread=331531

     

    良好的编程习惯是需要日积月累的,如果你处于学习阶段,请你时刻要注意这些细节问题。

     

    Ⅳ、最后

    我的网站:https://www.strongerhuang.com

    我的微信公众号(ID:strongerHuang)还在分享STM8、STM32、Keil、IAR、FreeRTOS、UCOS、RT-Thread、CANOpen、Modbus…等更多精彩内容,如果想查看更多内容,可以关注我的微信公众号。

    微信公众号

     

    展开全文
  • Java编程规范

    万次阅读 多人点赞 2017-12-18 22:13:22
    Java编程规范
  • C++编程规范中文版,提供专业的C++编程规范资料,欢迎下载
  • 阿里编程规范

    千次阅读 2017-11-06 17:12:15
    GitHub:https://github.com/alibaba/p3c 使用链接:点击打开链接
  • 牛客网在线编程规范实例

    万次阅读 2020-05-22 15:23:56
    牛客网华为笔试题通过案例,注意要引入包和输出: import java.util.Scanner; public class Main { public static int getIntFromDouble(double a){ return (int)(a+0.5); } ... public static void main(String...
  • 需要静下来用心读的----程序语言编程规范

    万次阅读 热门讨论 2012-07-28 05:42:02
    总结一下常用的编程规范:  (1)VC编程规范---程序员都应该这样写代码  (2)Google C++编程风格指南  (3)华为软件编程规范和范例  (4)高质量C++/C编程指南  (5)微软一站式示例代码库  (6)代码...
  • 一张图总结Google C++编程规范(Google C++ Style Guide)

    万次阅读 多人点赞 2014-08-02 14:53:20
    Google C++ Style Guide是一份不错的C++编码指南,我制作了一张比较全面的说明图,可以在短时间内快速掌握规范的重点内容。不过规范毕竟是人定的,记得活学活用。看图前别忘了阅读下面两条重要建议: 1 保持一致也...
  • 之前博客《谷歌C++编程规范笔记》整理了一些关于C++ Style方面的东西,看的是中文版本的。但是今天翻阅英文版本的,在最后,发现了 Google C++ Style 关于windows的。Windows programmers have developed their own ...
  • 【数据库】编程规范与安全

    万次阅读 热门讨论 2019-03-23 11:28:44
    关于编程规范,我是知道的,命名规范等等,但是实际开发中想法上会有些慢半拍,有时候就会造成sql注入,好的编程习惯对于企业和个人的发展都是必不可少的。最近一段时间参加了一个偏向后台开发的项目。聊一聊开发...
  • Python编程语言PEP8规范

    千次阅读 2020-05-17 23:47:33
    1. 分号: - 不要在行尾加分号, 也不要用分号将两条命令放在同一行。 2....每行不超过80个字符(长的导入模块语句和注释里的URL除外) ...Python会将圆括号, 中括号和花括号中的行隐式的连接起来 : ...
  • 1 . 匈牙利命名: 开头字母用变量类型的缩写,其余部分用变量的英文或英文的缩写,要求单词第一个字母大写。 ex: int iMyAge; “i”是int类型的缩写; char cMyName[10]; “c”是char类型的缩写;...
  • 学习华为C/C++编程规范(最新版)的一点心得体会缘起深入华为的进击我的感受全面务实高效后续 缘起 第一次接触编程规范,是在我十多年前刚参加工作的第一家公司,虽然规模不大,只有十几个程序员,但是大家终于无法...
  • 程序员修炼之道

    千次阅读 2005-02-05 12:41:00
    1.从一门语言开始初学编程...2.规范的代码程序员与程序员之间的交流主要还是靠源程序,所以代码一定要规范(命名规范,注释规范,编写规范等等)。这样不仅便于你程序的改进,也便于向他人请教!"编程易精"的程序代码
  • Python编程规范

    千人学习 2020-08-20 19:08:55
    本课程主要是围绕着如何编写整洁的Python代码,如何提高代码的易用性与效率,使用合适的编码规范合理规避隐藏的BUG提高安全性能,教你如何统一代码风格使代码的可读性得以提高。依照规范来编写本来就是一个习惯问题...
  • 编程规范入门篇 空格和tab的区别

    万次阅读 2017-03-21 19:03:42
    使用空格进行缩进,不要在代码中使用tabs
  • 三种编程命名规范

    千次阅读 2017-12-19 14:07:39
    在开发中,我们需要给变量,常量,函数,类起名字,什么样的名字才是合乎规范的呢,下面我们将介绍三种常用编程命名规范 匈牙利命名法驼峰式命名法帕斯卡命名法 命名法说明 匈牙利命名 开头字母用变量...
  • 规范-阿里代码规范设置

    万次阅读 2018-03-07 23:23:06
    阿里代码规范设置1. 阿里代码规范地址https://github.com/alibaba/p3c2. 安装eclipse规范文件2.1. 导入代码格式文件https://github.com/alibaba/p3c/tree/master/p3c-formatter2.2. 导入代码格式化样式3. 安装...
1 2 3 4 5 ... 20
收藏数 410,875
精华内容 164,350
关键字:

编程规范