代码风格(1)——命名约定

一、命名约定

最重要的一致性规则是命名管理。命名的风格能让我们在不需要去查找类型声明的条件下快速地了解某个名字代表的含义:类型,变量,函数,常量,宏等等,甚至我们大脑中的模式匹配引擎非常依赖这些命名规则。

命名规则具有一定随意性,但相比按个人喜好命名,一致性更重要,所以无论你认为它们是否重要,规则总归是规则。

二、通用命名规则

2.1 总述

函数命名,变量命名,文件命名要有描述性;少用缩写
以达到“望文生义”,看其名,知其意。

2.2 说明

尽可能使用描述性的命名,别心疼空间,毕竟相比之下让代码易于新读者理解更重要。不要用只有项目开发者能理解的缩写,也不要通过砍掉几个字母来缩写单词。

规范命名:

int price_count_reader;    // 无缩写
int num_errors;            // "num" 是一个常见的写法
int num_dns_connections;   // 人人都知道 "DNS" 是什么

不规范命名:

int n;                     // 毫无意义
int nerr;                  // 含糊不清的缩写
int n_comp_conns;          // 含糊不清的缩写
int wgc_connections;       // 只有贵团队知道是什么意思
int pc_reader;             // "pc" 有太多可能的解释了
int cstmr_id;              // 删减了若干字母

注意,一些特定的广为人知的缩写是允许的,例如用 i 表示迭代变量和用 T 表示模板参数。

三、命名体系

本文推荐3种命名体系,一个项目中只能选用一种,不得混用。

3.1 UNIX like体系

单词用小写字母,每个单词用下划线 ”_” 分割。
举例:

int number_of_bytes;
int success_flag;
int return_value;

3.2 Small-camel-case体系

小驼峰式命名,除第一个单词小写之外,其他单词首字母大写
举例:

int numberOfBytes;
int successFlag;
int returnValue;

3.3 Big-camel-case体系

大驼峰式命名,每个单词首字母大写
举例:

int NumberOfBytes;
int SuccessFlag;
int ReturnValue;

四、文件命名

4.1 总述

文件名要全部小写,可以包含下划线 “_” 或连字符 “-”, 依照项目的约定。如果没有约定,那么 “_” 更好。

4.2 说明

可接受的文件命名示例:

  • my_useful_class.cc
  • my-useful-class.cc
  • myusefulclass.cc
  • myusefulclass_test.cc // _unittest_regtest 已弃用

原则上,一个 .c 文件须有一个名称相同的 .h 文件相对应。

C++ 文件要以 .cc 结尾,头文件以 .h 结尾,定义类时文件名一般成对出现, 如 foo_bar.hfoo_bar.cc,对应于类 FooBar
内联函数必须放在 .h 文件中。如果内联函数比较短,就直接放在 .h 中。

通常应尽量让文件名更加明确。http_server_logs.h 就比 logs.h 要好。

五、类型命名

5.1 总述

类型名称的每个单词首字母均大写,不包含下划线: MyExcitingClassMyExcitingEnum

5.2 说明

所有类型命名——类,结构体,类型定义(typedef),枚举,类型模板参数——均使用相同约定,即以大写字母开始,每个单词首字母均大写,不包含下划线。

类名和对象名应该是名词或名词短语。

举例:

// 类和结构体
class UrlTable { ...
class UrlTableTester { ...
struct UrlTableProperties { ...

// 类型定义
typedef hash_map<UrlTableProperties_t *, string> PropertiesMap;

// using 别名
using PropertiesMap = hash_map<UrlTableProperties_t *, string>;

// 枚举
enum UrlTableErrors { ...

5.3 类型定义命名

/*
** 基本数据类型的重定义,小写比首字母大写更有利于延长Shift寿命,
** 但也更容易产生命名冲突。
*/
typedef unsigned char byte;
typedef unsigned char byte_t;
typedef unsigned char Byte;
typedef unsigned char Byte_t;

typedef 定义结构体别名时,首字母大写并加后缀 “_t”
举例:

typedef struct  
{
  string name;
  int num_entries;
  static Pool<UrlTableProperties>* pool;
} UrlTableProperties_t;

5.4 类命名

定义一个类以 C 做为类名前缀。

class CMyListCtrl;

六、变量命名

6.1 普通变量命名

  • 变量(包括函数参数)和数据成员名开头字母一律小写,单词之间可用下划线连接。
  • 建议采用Small-camel-case体系
    举例:
string table_name;
string tableName;
char* pTableName;

6.2 静态变量命名

静态变量增加 s_ 作为前缀。
举例:

int s_count;
int s_returnValue;

6.3 全局变量命名

全局变量增加 g_ 作为前缀。
举例:

int g_currentFile;
int g_username;

6.4 类数据成员命名

不管是静态的还是非静态的,类数据成员都可以和普通变量一样,但要接下划线。

class TableInfo 
{
  ...
 private:
  string table_name_;              // 好 - 后加下划线
  string tablename_;               // 好
  static Pool<TableInfo>* pool_;   // 好
};

或者成员变量前加 m_ 作为前缀。
举例:

string m_tableName;

6.5 结构体变量命名

不管是静态的还是非静态的,结构体数据成员都可以和普通变量一样,不用像类那样接下划线。

struct UrlTableProperties 
{
  string name;
  int num_entries;
  static Pool<UrlTableProperties>* pool;
};

6.6 指针变量命名

对一重指针变量的基本原则为:p+变量类型前缀+命名。
举例:

char *pName;

对二重指针变量的基本规则为:pp+变量类型前缀+命名。
对三重指针变量的基本规则为:ppp+变量类型前缀+命名。

七、常量命名

7.1 总述

对于数值或者字符串等等常量的定义,建议采用全大写字母,单词之间加 “_” 的方式命名(枚举同样建议使用此方式定义)
举例:

const float PI_ROUNDED = 3.14;

7.2 说明

常量定义时尽量加 ’const’ 修饰符

八、宏命名

8.1 总述

对于数值或者字符串等等宏的定义,建议采用全大写字母,单词之间加 “_” 的方式命名(枚举同样建议使用此方式定义)
举例:

#define MAX_FILENAME_LENGTH  20
#define PI_ROUNDED 3.0

8.2 说明

  • 宏定义表达式时要用完备的括号,如:
#define RECTANGLE_AREA(a, b)  a * b    
以上定义存在风险,以下定义才正确:
#define RECTANGLE_AREA(a, b)  ((a) *( b))
  • 将宏所定义的多条表达式放在大括号中,如:
#define FOO(x) { \ 
        printf("arg is %s\n", x); \ 
        DoSomethingUseful(x); \ 
}

九、函数命名

9.1 总述

函数命名应以函数要执行的动作命名,一般采用动词或者动词+名词的结构。
举例:

void DrawBox(int point);

9.2 说明

  • 内部或静态函数采用 Small-camel-case体系,如:
void getBoxValue(void);
  • 需要公开的函数(API)采用 Big-camel-case体系,如:
void GetBoxValue(void);
  • 对于首字母缩写的单词,更倾向于将它们视作一个单词进行首字母大写,如:
void StartRpc(void);
而非
void StartRPC(void);

十、命名空间命名

命名空间以小写字母命名。最高级命名空间的名字取决于项目名称。要注意避免嵌套命名空间的名字之间和常见的顶级命名空间的名字之间发生冲突。

顶级命名空间的名称应当是项目名或者是该命名空间中的代码所属的团队的名字。命名空间中的代码,应当存放于和命名空间的名字匹配的文件夹或其子文件夹中。

注意:不使用缩写作为名称的规则同样适用于命名空间。命名空间中的代码极少需要涉及命名空间的名称,因此没有必要在命名空间中使用缩写。

要避免嵌套的命名空间与常见的顶级命名空间发生名称冲突。由于名称查找规则的存在,命名空间之间的冲突完全有可能导致编译失败。尤其是,不要创建嵌套的 std 命名空间。建议使用更独特的项目标识符 (websearch::index, websearch::index_util) 而非常见的极易发生冲突的名称 (比如 websearch::util)。

对于 internal 命名空间,要当心加入到同一 internal 命名空间的代码之间发生冲突 (由于内部维护人员通常来自同一团队,因此常有可能导致冲突)。在这种情况下,请使用文件名以使得内部名称独一无二 (例如对于 frobber.h, 使用 websearch::index::frobber_internal)

十一、枚举命名

11.1 总述

枚举的命名应当和常量一致: kEnumName 或是 ENUM_NAME.

11.2 说明

单独的枚举值应该优先采用常量的命名方式. 但方式的命名也可以接受. 枚举名 UrlTableErrors (以及 AlternateUrlTableErrors) 是类型, 所以要用大小写混合的方式。

enum UrlTableErrors 
{
    kOK = 0,
    kErrorOutOfMemory,
    kErrorMalformedInput,
};
enum AlternateUrlTableErrors 
{
    OK = 0,
    OUT_OF_MEMORY = 1,
    MALFORMED_INPUT = 2,
};

2009 年 1 月之前, 我们一直建议采用的方式命名枚举值. 由于枚举值和宏之间的命名冲突, 直接导致了很多问题. 由此, 这里改为优先选择常量风格的命名方式. 新代码应该尽可能优先使用常量风格. 但是老代码没必要切换到常量风格, 除非宏风格确实会产生编译期问题。


• 由 Leung 写于 2019 年 4 月 18 日

• 参考:Google 开源项目风格指南——7.命名约定
    [逼死强迫症 - C&C++设计风格选择.1] : 命名规范

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,254评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,875评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,682评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,896评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,015评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,152评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,208评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,962评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,388评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,700评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,867评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,551评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,186评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,901评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,689评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,757评论 2 351

推荐阅读更多精彩内容