Skip to content

Commit 3ff7b48

Browse files
committed
编码规范合入
1 parent f846c05 commit 3ff7b48

5 files changed

Lines changed: 478 additions & 1 deletion

File tree

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# 编码规范 - 编程风格
2+
3+
# 类成员函数声明,需要与定义分开。
4+
5+
* 不要直接将类函数定义写在头文件中,一是暴露具体实现,而是导致头文件内容过大。
6+
7+
备注:模板或内联函数或简单逻辑除外
8+
9+
# 禁止接口有多个返回值,需采用闭包、访问者模式实现
10+
11+
```cpp
12+
void queryPathAndResult(string& path,string& res)
13+
```
14+
15+
# 类的声明格式
16+
17+
```cpp
18+
class Test{
19+
//公有函数
20+
public:
21+
22+
//私有函数
23+
private:
24+
25+
//保护成员
26+
protected:
27+
28+
//私有成员
29+
private:
30+
31+
}
32+
33+
```
34+
35+
# 类成员,不超过10个
36+
37+
* Clean Code 角度
38+
39+
# 类方法,不超过30个
40+
41+
* Clean Code 角度
42+
43+
# 不将成员变量,直接作为接口参数
44+
45+
* 不规范
46+
47+
# 宏定义禁止包含复杂判断,以规避复杂度检查
48+
49+
* 避免引入错误
50+
51+
# 非冒号表达式的循环,固定上界保护
52+
53+
```cpp
54+
//正例
55+
for(int i=0;i<maxNum;i++){
56+
...
57+
}
58+
59+
// 反例,无限制导致死循环
60+
for(int i=0; ;i++){
61+
...
62+
}
63+
```
64+
65+
# list容器禁止使用size方法,如果需要用其它容器替换
66+
67+
* list容器的size方法是遍历得到大小,O(N)复杂度

md/method/code-style/code-style-google-c++.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Google C++ Style Guide
1+
# 编码规范 - Google C++ Style Guide
22

33
[[toc]]
44

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# 编码规范 - 头文件包含规范
2+
3+
[[toc]]
4+
5+
# C/C++头文件包含规范
6+
7+
## Self-contained 头文件自包含
8+
9+
* 所有头文件要能够自给自足,即头文件需要包含**本身依赖**的其他头文件。
10+
* 换言之,用户和重构工具不需要为特别场合而包含额外的头文件。
11+
12+
## 头文件中尽量减少对其他头文件的依赖
13+
14+
* 头文件包含另一个头文件的同时会引入一项新的依赖(dependency),这个依赖也会随着该头文件的被包含而扩散出去,从而导致**依赖扩散**
15+
16+
* 只要头文件被修改,代码就要重新编译,如果你的头文件包含了其它头文件,**这些头文件的任何改动都将导致那些包含了你的头文件的代码重新编译**
17+
18+
### 多余的头文件包含
19+
20+
* 头文件包含必须遵循最少必要原则,尽量少包含。
21+
* 能包含小的头文件,不包含大的头文件。
22+
* 及时清理不需要的头文件包含,不能只增不删。
23+
24+
### 可以在source文件包含的,不要包含着头文件中
25+
26+
例如,Test.h头文件以及对应Test.cpp文件。
27+
28+
Test.h只要包含改头文件所依赖的其他头文件,不能将Test.cpp所需要用到的头文件全都放在Test.h中。
29+
30+
### 头文件仅声明,不作实现
31+
32+
如果头文件里包含函数实现,在其他多个源文件中使用include方式包含时,会提示多重定义(multiple definition)
33+
34+
### 头文件是只包含必要的声明
35+
36+
* 不是所有函数实现都需要在头文件中声明,只声明需要发布的函数接口。
37+
38+
* 私有函数不在头文件中声明,从而减少头文件的依赖。例如,某些工具类方法可以声明和实现在.cpp函数的类外。
39+
40+
### define 保护
41+
42+
* 所有头文件都应该使用 #define 来防止头文件被多重包含, 命名格式例如:
43+
44+
```cpp
45+
#ifndef Data_MySQL_MySQLException_INCLUDED
46+
#define Data_MySQL_MySQLException_INCLUDED
47+
```
48+
49+
### 使用前置声明(forward declarations)
50+
51+
* 「前置声明」(forward declaration)是类、函数和模板的纯粹声明,没伴随着其定义.
52+
53+
看法一:
54+
55+
* 尽可能地避免使用前置声明。使用 #include 包含需要的头文件即可。
56+
* 前置声明隐藏了依赖关系,头文件改动时,用户的代码会跳过必要的重新编译过程。
57+
58+
看法二:
59+
60+
* 通过前置声明的方式,减少头文件中依赖的其他头文件。将头文件的包含动作延迟到源文件中去实现。
61+
62+
* 使用场景:头文件只用到对应内容的指针或引用不涉及具体内容。或用到一个结构体声明,但不想包一个很大的头文件将依赖扩散。(struct Foo;在源文件中#include <Foo.h>)
63+
64+
可以参考:[C++前置声明](/md/c++/tips/c++-tips-forward-declaration.md)
65+
66+
## 避免错误依赖和反向依赖
67+
68+
* 包含每个头文件时,需要分析是不是合适的依赖,避免包含错误的头文件,导致其依赖的其他头文件项变多。
69+
70+
```cpp
71+
//log.h
72+
73+
#include<logType.h>
74+
#include<logTime.h>
75+
76+
//不应该包含项
77+
#include<message.h>
78+
#include<httpType.h>
79+
```
80+
81+
## 尽可能将代码拆分成相对独立的,粒度小的单元,放到不同的文件中
82+
83+
* 不能使得一个类代码很臃肿,包含特别多的功能,不方便维护。
84+
85+
* 通过拆分成小的,独立的模块更利于维护。
86+
87+
## 包含头文件顺序
88+
89+
头文件Test.h和源文件Test.cpp,对应的头文件包含顺序都需要满足:
90+
91+
1. Test.h (如果自己定义的头文件有错,编译时会提前暴露自身的错误而不是其他库的。)
92+
2. 本项目内的.h文件
93+
3. 其它库的.h文件
94+
4. C系统文件
95+
5. C++系统文件
96+
97+
没有唯一的标准,都是适合自己的习惯,google C++ 头文件顺序:
98+
99+
1. 主体功能文件(这一条规则保证维护这些文件的人们首先看到构建中止的消息而不是维护其他包的人们。)
100+
2. C系统文件
101+
3. C++系统文件
102+
4. 其它库的.h文件
103+
5. 本项目内的.h文件
104+
105+
## 包含头文件时,使用源码的目录树结构,不使用相对路径
106+
107+
使用源码的目录树结构,而不是相对路径:
108+
109+
* 为保证唯一性, 头文件的命名应该基于所在项目源代码树的全路径
110+
111+
* #include <drogon/orm/Result.h> √
112+
* #include <../../Result.h> ×
113+
114+
## 头文件中不允许使用using namespace XXX·措施
115+
116+
* 头文件使用 `using namespace XXX` 会破坏 namespace 的封装性
117+
* 因为头文件会被包含在其他的头文件和cpp文件中。导致C++编译器将头文件字符串直接拷贝,强制其他的头文件也使用 `using namespace XXX`,从而引起编译错误,或者使用错误的类型,造成麻烦。
118+
119+
```cpp
120+
//正例
121+
namespace HttpProxy{
122+
using Poco::ByteOrder;
123+
using Poco::UInt16;
124+
}
125+
126+
// 反例
127+
128+
namespace HttpProxy{
129+
using namespace Poco;
130+
}
131+
```
132+
133+
134+
# 保证措施
135+
136+
* 代码扫描工具识别多余包含
137+
* Code Review发现头文件包含是否规范
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# 编码规范 - 常用编码命名规则
2+
3+
4+
[[toc]]
5+
6+
# 驼峰命名法
7+
8+
> 最常见的一个命名法,命名方式使用大小写混合的格式来区别各个单词,并且单词之间不使用空格隔开或者连接字符连接的命名方式。
9+
10+
## 大驼峰命名法(CamelCase)
11+
12+
**通常类名需要使用大驼峰命名法**
13+
14+
```cpp
15+
//正例:
16+
ServiceDiscovery、ServiceInstance、LruCacheFactory
17+
//反例:
18+
serviceDiscovery、Serviceinstance、LRUCacheFactory
19+
```
20+
21+
## 小驼峰命名法(lowerCamelCase)
22+
23+
**通常函数方法名、参数名、成员变量、局部变量需要使用小驼峰命名法**
24+
25+
```cpp
26+
//正例:
27+
getUserInfo()、createCustomThreadPool()、setNameFormat(String nameFormat)
28+
Uservice userService;
29+
30+
//反例:
31+
GetUserInfo()、CreateCustomThreadPool()、setNameFormat(String NameFormat)
32+
Uservice user_service
33+
```
34+
35+
# 蛇形命名法(snake_case)
36+
37+
**通常测试方法名、常量、枚举名称需要使用蛇形命名法。**
38+
39+
在蛇形命名法中,各个单词之间通过下划线“_”连接,比如
40+
41+
`should_get_200_status_code_when_request_is_valid、CLIENT_CONNECT_SERVER_FAILURE`
42+
43+
蛇形命名法的优势是命名所需要的单词比较多的时候,比上面通过小驼峰命名法得到的名称易读:
44+
45+
`shouldGet200StatusCodoWhenRequestIsValid`
46+
47+
```cpp
48+
//正例:
49+
@Test
50+
void should_get_200_status_code_when_request_is_valid() {
51+
......
52+
}
53+
54+
//反例:
55+
56+
@Test
57+
void shouldGet200StatusCodoWhenRequestIsValid() {
58+
......
59+
}
60+
```
61+
62+
# 串式命名法(kebab-case)
63+
64+
在串式命名法中,各个单词之间通过下划线“-”连接
65+
66+
**建议项目文件夹名称使用串式命名法**
67+
68+
在Vue中,定义组件名
69+
70+
* kebab-case(短横线命名)
71+
* `Vue.component('my-component-name', { /* ... */ })`
72+
73+
* 使用 大驼峰命令(CamelCase)
74+
* `Vue.component('MyComponentName', { /* ... */ })`
75+
76+
# 匈牙利命名法(Hungarian)
77+
78+
hwnd:h 是类型描述,表示句柄, wnd 是变量对象描述,表示窗口,所以 hwnd 表示窗口句柄。
79+
pfnEatApple:pfn 是类型描述,表示指向函数的指针, EatApple 是变量对象描述,所以它表示指向 EatApple 函数的函数指针变量。
80+
g_cch:g_ 是属性描述,表示全局变量,c 和 ch 分别是计数类型和字符类型,一起表示变量类型,这里忽略了对象描述,所以它表示一个对字符进行计数的全局变量。
81+
82+
**匈牙利命名法基本原则:变量名=属性+类型+对象描述**
83+
84+
* 全局变量用g_开头,如一个全局的长型变量定义为g_lFailCount
85+
* 静态变量用s_开头,如一个静态的指针变量定义为s_plPerv_Inst
86+
* 成员变量用m_开头,如一个长型成员变量定义为m_lCount
87+
* 局部变量用l_开头,如一个整型局部变量定义为l_inum
88+
89+
```
90+
属性部分:
91+
g_ 全局变量
92+
c_  常量
93+
m_  c++类成员变量
94+
s_  静态变量
95+
类型部分:
96+
数组 a
97+
指针 p
98+
函数 fn
99+
无效 v
100+
句柄 h
101+
长整型 l
102+
布尔 b
103+
浮点型(有时也指文件) f
104+
双字  dw
105+
字符串  sz
106+
短整型  n
107+
双精度浮点 d
108+
计数 c(通常用cnt)
109+
字符 ch(通常用c)
110+
整型 i(通常用n)
111+
字节 by
112+
字 w
113+
实型 r
114+
无符号 u
115+
描述部分:
116+
最大 Max
117+
最小 Min
118+
初始化 Init
119+
临时变量 T(或Temp)
120+
源对象 Src
121+
目的对象 Dest
122+
```

0 commit comments

Comments
 (0)