那些良好的编程习惯
那些良好的编程习惯
良好的编程习惯对于编写可读、可维护和可扩展的代码至关重要。特别是对于一些大型的项目, 良好的编程习惯可以规避许多不必要的错误, 缩短改正错误的时间, 降低维护成本, 提高开发效率.
1. 写注释
如果你不想第二天一起床就看不懂前一天写的代码, 那么请写注释. 代码的可读性是非常重要的, 你不可能记得住每一行代码的原理, 但是你可以通过注释来帮助你理解一个代码块的作用. 试想如果一个上千行的代码一行注释都没有, 维护起来内有多麻烦.
2. 命名规范
我的习惯是起长名字, 例如:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50template<typename T>
WeightedGraph<T> primAlgorithm(const WeightedGraph<T>& graph) {
// 无向图节点的数量
int verticesCount = graph.numberVertices();
// 父节点数组用于存储每个节点的父节点
std::vector<int> parent(verticesCount, -1);
// key值,用于选取具有最小权值的边
std::vector<T> key(verticesCount, std::numeric_limits<T>::max());
// 最小优先级队列,用于选取具有最小权值的边
std::priority_queue<std::pair<T, int>, std::vector<std::pair<T, int>>, std::greater<>> priorityQueue;
// 从第一个节点开始,它的key值为0
key[0] = 0;
priorityQueue.push({0, 0});
// 标记数组,如果节点i被标记,标记[i]将为true
std::vector<bool> inMST(verticesCount, false);
while (!priorityQueue.empty()) {
// 选取具有最小权值的边
int minVertex = priorityQueue.top().second;
priorityQueue.pop();
// 将该节点添加到MST中
inMST[minVertex] = true;
// 遍历所有相邻的节点
for (const auto& edge : graph.matrix[minVertex]) {
int v = edge.linked_vertex;
T weight = edge.weight;
// 如果v不在MST中,并且权值小于key[v]
if (!inMST[v] && key[v] > weight) {
// 更新key值为权值
key[v] = weight;
priorityQueue.push({key[v], v});
parent[v] = minVertex;
}
}
}
// 创建最小生成树
WeightedGraph<T> mst(verticesCount);
for (int i = 1; i < verticesCount; ++i)
mst.insertEdge(parent[i], {i, key[i]});
return mst;
}
宁可变量名长, 也不要短的让人不知道他是干嘛的, 特别是现在的IDE都有自动补全功能, 完全不用担心变量名太长导致开发效率低的问题.
另外, 较长的变量名可以非常有效的避免命名冲突
3. 代码缩进
不论你是喜欢2格缩进还是4格缩进, 请在需要的地方缩进, 把所有东西全部都弄在一行非常不利于维护与阅读, 这个比较灵活, 只要能看得懂你可以有自己的代码风格, 但是尽量保持一致
比如我就喜欢把初始化参数列表也换行缩进, 特别是变量比较多的时候, 例如:1
2
3
4
5template<typename T>
WeightedGraph<T>::WeightedGraph(int verticesCount) :
matrix(verticesCount) {
//...
}
4. 电脑配置
- 两套输入法, 如果你不想因为中英文标点符号搞错浪费时间, 请多使用英文输入法, 人生苦短, 尽量避免低级错误
- 文件默认显示后缀名, 显示隐藏文件
- 删除360, 腾讯管家等垃圾软件
- 使用google chrome浏览器
5. 杜绝多重嵌套
如果你不想你的代码长成这个样子:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19def find_value():
target_value = 42
found = False
arr = [[[1, 2, 42, 3], [4, 5, 6], [7, 8, 9]], [[10, 11, 12], [13, 14, 15], [16, 17, 18]], [[19, 20, 21], [22, 23, 24], [25, 26, 27]]]
for i in range(len(arr)):
for j in range(len(arr[i])):
for k in range(len(arr[i][j])):
if arr[i][j][k] == target_value:
print('Found the target value at position:', i, j, k)
found = True
break
if found:
break
if found:
break
if not found:
print('Value not found.')
find_value()
或者这个样子:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19def find():
target = 42;arr = [[[1,2,42],[4,5,6]],[[7,8,9],[10,11,12]]];found=False
for i in range(len(arr)):
if found==False:
for j in range(len(arr[i])):
if found==False:
for k in range(len(arr[i][j])):
if found==False:
if arr[i][j][k] == target:
print('Found:',i,j,k);found=True;break
else:
if k==len(arr[i][j])-1 and j==len(arr[i])-1 and i==len(arr)-1:
print('Not found')
elif k==len(arr[i][j])-1 and j==len(arr[i])-1:
print('Not found');break
elif k==len(arr[i][j])-1:
print('Not found');break
else:
print('Not found')
请不要多层嵌套, 大多数程序员可以忍受的极限是: 3层嵌套, 但是能不用尽量不用, 因为嵌太套了, 非常占用阅读者的大脑内存, 不利于阅读
6. 代码复用
如果你的代码中有一段代码需要重复使用, 请把它封装成类或者函数
7. 考虑异常
给自己留条后路, 一个简单的if判断加perror, 可以大大降低查错成本, 例如:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27//创建用于监听的socket
m_sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(m_sockfd < 0){
perror("socket creat error\n");
return -1;
}
std::cout << "socket create successfully" << std::endl;
//绑定本地的ip和端口
m_addr.sin_family = AF_INET;
m_addr.sin_addr.s_addr = htonl(INADDR_ANY);
m_addr.sin_port = htons(m_port);
m_ret = bind(m_sockfd, (struct sockaddr*)&m_addr, sizeof(m_addr));
if(m_ret < 0){
perror("bind error\n");
return -1;
}
std::cout << "bind successfully" << std::endl;
//监听Client
listen(m_sockfd, MAX_CONNECT);
if(m_ret < 0){
perror("listen error\n");
return -1;
}
std::cout << "listen successfully" << std::endl;
8. 多做笔记
尝试多做笔记, 写一个文档记录自己的错误, bug, 新学到的技术
同时可以分享给社区, 不要只做社区的搬运工, 也要做社区的贡献者