c++代码整洁之道

409次阅读  |  发布于4年以前

整洁的代码在团队中无疑是很受欢迎的,可以高效地被其它成员理解和维护,本文参考《C++代码整洁之道》和《Google C++编码规范》,结合自己的一些想法整理如下:

C++本身作为面向对象语言,首先介绍下面向对象一般涉及到的开发原则。

面向对象开发原则

  1. 依赖倒置原则:针对接口编程,依赖于抽象而不依赖于具体,抽象(稳定)不应依赖于实现细节(变化),实现细节应该依赖于抽象,因为稳定态如果依赖于变化态则会变成不稳定态。
  2. 开放封闭原则:对扩展开放,对修改关闭,业务需求是不断变化的,当程序需要扩展的时候,不要去修改原来的代码,而要灵活使用抽象和继承,增加程序的扩展性,使易于维护和升级,类、模块、函数等都是可以扩展的,但是不可修改。
  3. 单一职责原则:一个类只做一件事,一个类应该仅有一个引起它变化的原因,并且变化的方向隐含着类的责任。
  4. 里氏替换原则:子类必须能够替换父类,任何引用基类的地方必须能透明的使用其子类的对象,开放关闭原则的具体实现手段之一。
  5. 接口隔离原则:接口最小化且完备,尽量少public来减少对外交互,只把外部需要的方法暴露出来。
  6. 最少知道原则:一个实体应该尽可能少的与其他实体发生相互作用。
  7. 将变化的点进行封装,做好分界,保持一侧变化,一侧稳定,调用侧永远稳定,被调用侧内部可以变化。
  8. 优先使用组合而非继承,继承为白箱操作,而组合为黑箱,继承某种程度上破坏了封装性,而且父类与子类之间耦合度比较高。
  9. 针对接口编程,而非针对实现编程,强调接口标准化

C++开发原则

通过上述面向对象开发原则的理解可以细化到具体C++开发原则。

注重单元测试

重要性就不多说了,防患于未然,构建大型系统尤其需要进行单元测试,保证代码质量,可以防患于未然。一般都讲究测试驱动开发,开发一个功能首先要想好怎么测试,先把测试代码写好,再去开发对应的需求。通过单元测试也有利于开发者更好的进行接口的设计,主要说下良好的单元测试的原则。

单元测试的原则

良好的命名

无论是什么语言,函数和变量的良好命名都是很有必要的,通过函数的名字我们就可以知道这个函数里代码的作用,而不是通过写注释,个人一直倾向于用代码自解释。

文件命名

文件名字要全部小写,中间用_相连,后缀名为.cc和.h

类型命名

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

变量命名

不要将变量的类型在名字中体现,这样以后变量类型改变的话还需要去改动变量名,充分利用IDE的功能,变量 (包括函数参数) 和数据成员名一律小写, 单词之间用下划线连接. 类的成员变量以下划线结尾, 但结构体的就不用, 如: a_local_variable, a_struct_data_member, a_class_data_member_.

class TableInfo {
...
private:
string table_name_; // 好 - 后加下划线.
string tablename_;   // 好.
static Pool<TableInfo>* pool_; // 好.
int i_table; // 不好,不要将变量的类型在名字中体现
};

常量命名

声明为 constexpr 或 const 的变量, 或在程序运行期间其值始终保持不变的, 命名时以 “k” 开头, 大小写混合

const int kDaysInAWeek = 7;

函数命名

常规函数使用大小写混合, 取值和设值函数则要求与变量名匹配: MyExcitingFunction(), MyExcitingMethod(), my_exciting_member_variable(), set_my_exciting_member_variable().

枚举命名

和常量一致

enum UrlTableErrors {
  kOK = 0,
  kErrorOutOfMemory,
  kErrorMalformedInput,
};

Tip:

除非像swap函数里tmp那种一目了然,否则不要搞无意义的命名,函数名变量名字宁可特别长也要写清楚究竟是什么意思,不要用缩写,一个变量尽量在临近使用前才定义,可读性强也可更好利用cpu cache。

编辑器

团队可以统一使用相同的编辑器,个人目前使用的是VS Code编辑器,同时每个项目使用统一的.clang_format文件,统一规范代码格式,所有的换行符都要用LF格式,不要用CRLF格式,在右下角可以设置

个人的.clang-format文件如下,是在google风格的基础上做了些修改:

BasedOnStyle: Google
IndentWidth: 4
ColumnLimit: 120
SortIncludes: true
MaxEmptyLinesToKeep: 2

C++编码规范要点小总结

命名格式 <PROJECT>_<PATH>_<FILE>_H_

#ifndef FOO_BAR_BAZ_H_
#define FOO_BAR_BAZ_H_
...
#endif // FOO_BAR_BAZ_H_

或使用#pragma once,而#define方式更通用

附:本文介绍较为主观,可能和很多人想法有所冲突,各位可以结合自己的经历经验酌情参考。

参考资料

《C++代码整洁之道》

https://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/contents/

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8