代码书写规范总纲
# 代码书写规范总纲
作者:JeremyJone
版本:v1
版权:Jz
良好的规范,促进高质量的代码。 --与君共勉
# 前言
本《规范》旨在帮助编写更加清晰工整的代码,它是一种认为的,作为约束那些不在编译错误范围内的不良习惯。
在一开始编写代码,会有很多不良习惯,有的是为了方便图省事,有的是确实不知道有什么更好的方式方法,时间久了,造成了一种不良的编写习惯,不仅再次翻阅时头痛,也会增加维护成本,有甚者会失去一些工作机会等。
为了避免和规范代码,特制定本《规范》,它适用于大多数情况,如有特例,必要时应使用注释等方式进行显式注明其作用。
# 通用规则
有一些规范是不依赖任何语言的,当然有些语言对这些规则也有一些独特的规范化提案,我们应当在遵循这些提案的情况下,适配本《规范》,它的优先级更低。
# 使用多文件
在项目中,应当使用多个文件和文件夹,以区分每一个文件的功能,而需要将功能类似的文件放在同一个文件夹中,进一步加以区分项目的整体结构。
不同功能应当区分
创建的每一个类都应当是单独的文件
文件和文件夹的名称应当具有显式的意义
这个在不同语言中的要求不尽相同,但是更多的是在设计阶段,就应该为整个项目设计好整体的目录结构,分成不同模块,分工协作开发。
# 使用缩进
不同的代码块作用域,应当使用不同量的缩进予以对应,这样看上去具有更加清晰的层级,方便编写和检查。
每一级缩进应当使用 4 个 space,而不是一个 tab
在同一个项目中,应当使用相同 space 的缩进量
作用域的大括号(如果有),只要括号不与代码同行,都应当与代码左对齐
在书写大括号时,应当每次直接书写完整的括号,然后在其内部编写代码
一个不好的例子:
#include <stdio.h>
int main() {
int i, j;
for(i=0;i<10;i++) {
for(j=0;j<10;j++) {
printf("%d - %d", i, j);
}
}
return 0;
}
2
3
4
5
6
7
8
9
10
一个好的例子:
#include <stdio.h>
int main() {
int i, j;
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
printf("%d - %d", i, j);
}
}
return 0;
}
2
3
4
5
6
7
8
9
10
11
12
不难看出,前者很难看出区别,而后者结构清晰,可以一眼看出结构格式甚至逻辑。
# 使用空行
空行起到分隔段落的作用,使得整个程序结构更加清晰。
定义变量后需要空一行
每个函数定义结束后需要空至少一行
类之间需要空至少两行(原则上每个类都应该不同文件)
在同一个作用域中,不同的逻辑内容需要使用空行分开,加以区分其功能的不同性。
示例:
int main() {
int i;
for (i = 0; i < 10; i++) {
// ...
}
return 0;
}
2
3
4
5
6
7
8
9
# 使用空格
空格可以使同行内的代码结构变得更加清晰明了。
行尾不要有空格
函数名之后不要有空格
一般情况下,不要在同一行出现多个表达式,否则使用一个空格分开
关键字之后需要有一个空格。比如
if
、for
、while
等赋值运算符、关系运算符、算术运算符、逻辑运算符、位运算符等都需要左右使用一个空格
单目运算符等前后不加空格
示例:
for (i = 0; i < 10; i++) {
// ...
}
2
3
# 有效的名称
在代码中,所有变量、函数、类都具有一个名称,它方便了程序员编写代码。很多时候,一个有效的名称可以减少大量的不必要工作和时间。
一个简单的例子:
int a = 18;
int age = 18;
2
很明显,使用第二行的 age
可以更加清晰的表述这个数字的具体含义,这为之后的引用或修改提供了帮助。
# 变量名
每一个变量名都应当具有其显式的意义,任何违背此原则的变量名,都属于一个不好的名称。
使用具名含义的名词,如 age、size、width 等
使用特殊含义的词语,来限定其特殊意义,如 is、can、has 等
用来衡量
是不是
的含义的,使用is
开头 + 本体词语用来衡量
行不行
的含义的,使用can
开头 + 本体词语用来衡量
有没有
的含义的,使用has
开头 + 本体词语C++的成员变量通常需要加上
m
前缀,表示其为成员变量变量通常使用 小驼峰格式 或 全小写 + 下划线
_
的格式常量应当使用全大写 + 下划线
_
的格式
同时,一些含义模糊的名称应当避免使用。比如:
// wrong
int number = 1; // 这是什么数字?
bool flag = true; // 这是哪个标志位?
// right
int resNum = 1; // 结果的数字,result 简写为 res 是可以的,它是通用的
bool okFlag = true; // 成功的标志位,意味着成功会是 ok 的,不需要再去翻阅上下文查看 flag 的含义
2
3
4
5
6
7
# 函数名
函数名称应当显式的给出其作用、返回值等信息,不应当使用无意义的 fn
等。
通常,函数名应当使用一个 动词 + 名词 的结构格式来命名。
常用的函数前缀包括:
前缀 | 功能 |
---|---|
get | 获取某个值 |
set | 赋值 |
handle | 操作功能 |
例如:
public String getName() {
return name;
}
public void setName(String n) {
name = n;
}
2
3
4
5
6
7
# 有用的注释
注释通常是给程序员使用,方便记录下当前写下此处代码的逻辑想法,为了以后再次查看或修改时使用。
当然,在逻辑结构中,99%的逻辑代码都可以使用 有用的变量名称 替代。
例如:
// wrong
function getWidth() {
// 默认宽度的最小值
const size = 10;
// 这里需要判断是否小于最小值,如果小于,返回最小值
if (this.width < size) {
return size;
}
return this.width;
}
// right
function getWidth() {
const defaultMinWidth = 10;
if (this.width < defaultMinWidth) {
return defaultMinWidth;
}
return this.width;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
上例中,明显下面的正确方式不再需要任何注释,并且可以确保每一行都能看得明白。
所以,上面的错误示例中,第3行和第6行的注释,就属于无用的注释,它们完全可以被更加精良的代码所替代。
# 具体的语言
每种语言都有自己独特的使用方式。所以《规范》应当针对不同语言具有不同的内容。请记住,任何情况下,具体语言的规范优先级都应该高于通用规范。