首页 > 代码库 > 构建之法学习(4)
构建之法学习(4)
本周学习的内容是两人合作
计算机只关心编译生成的机器码,你的程序采用哪种缩进风格,变量名有无统一的规范等,与机器码的执行无关。但是,做一个有商业价值的项目,或者在团队里工作,代码规范相当重要。“代码规范”可以分成两个部分:
1. 代码风格规范。主要是文字上的规定,看似表面文章,实际上非常重要。
2. 代码设计规范。牵涉到程序设计、模块之间的关系、设计模式等方方面面的通用原则。
代码风格的原则是:简明,易读,无二义性。提示:这里谈的风格是一家之言,如遇争执,关键是要本着“保持简明,让代码更容易读”的原则,看看争执中的代码规范能否让程序员们更好地理解和维护程序。
复杂的注释应该放在函数头,很多函数头的注释都用来解释参数的类型等,如果程序正文已经能够说明参数的类型in/out,就不要重复!注释也要随着程序的修改而不断更新,一个误导的(Misleading)注释往往比没有注释更糟糕。另外,注释(包括所有源代码)应该只用ASCII字符,不要用中文或其他特殊字符,否则会极大地影响程序的可移植性。在现代编程环境中,程序编辑器可以设置各种美观得体的字体,我们可以使用不同的显示风格来表示程序的不同部分。
代码设计规范不光是程序书写的格式问题,而且牵涉到程序设计、模块之间的关系、设计模式等方方面面,这里又有不少内容与具体程序设计语言息息相关(如C、C++、Java、C#),但是也有通用的原则,这里主要讨论通用的原则。如果你只想为了“爽”而写程序,那么可以忽略下面的原则;如果你写的程序会被很多人使用,并且你得加班调试自己的程序,那最好还是遵守下面的规定。
注意,除了关于异常(Exception)的部分,大部分其他原则对C#也适用。
1. 类
1)使用类来封装面向对象的概念和多态(Poly-morphism)。
2)避免传递类型实体的值,应该用指针传递。换句话说,对于简单的数据类型,没有必要用类来实现。
3)对于有显式的构造和析构函数的类,不要建立全局的实体,因为你不知道它们在何时创建和消除。
4)仅在必要时,才使用“类”。
2. class vs. struct如果只是数据的封装,用struct即可。
3. 公共/保护/私有成员(public、protected和private)按照这样的次序来说明类中的成员:public、pro-tected、private。
4. 数据成员
1)数据类型的成员用m_name说明。
2)不要使用公共的数据成员,要用inline访问函数,这样可兼顾封装和效率。
5. 虚函数(Virtual Function)
1)使用虚函数来实现多态(Polymorphism)。
2)仅在很有必要时,才使用虚函数。
3)如果一个类型要实现多态,在基类(Base Class)中的析构函数应该是虚函数。
6. 构造函数(Constructors)
1)不要在构造函数中做复杂的操作,简单初始化所有数据成员即可。
2)构造函数不应该返回错误(事实上也无法返回)。把可能出错的操作放到HrInit()或FInit()中。
7. 析构函数(Destructor)
1)把所有的清理工作都放在析构函数中。如果有些资源在析构函数之前就释放了,记住要重置这些成员为0或NULL。
2)析构函数也不应该出错。
8. new和delete
1)如果可能,实现自己的new/delete,这样可以方便地加上自己的跟踪和管理机制。自己的new/delete可以包装系统提供的new/delete。
2)检查new的返回值。new不一定都成功。
3)释放指针时不用检查NULL。
9. 运算符(Operators)
1)在理想状态下,我们定义的类不需要自定义操作符。确有必要时,才会自定义操作符。
2)运算符不要做标准语义之外的任何动作。例如,“==”的判断不能改变被比较实体的状态。
3)运算符的实现必须非常有效率,如果有复杂的操作,应定义一个单独的函数。
4)当你拿不定主意的时候,用成员函数,不要用运算符。
10. 异常(Exceptions)
1)异常是在“异乎寻常”的情况下出现的,它的设置和处理都要花费“异乎寻常”的开销,所以不要用异常作为逻辑控制来处理程序的主要流程。
2)了解异常及处理异常的花销,在C++语言中,这是不可忽视的开销。
3)当使用异常时,要注意在什么地方清理数据。
4)异常不能跨过DLL或进程的边界来传递信息,所以异常不是万能的。
11. 类型继承(Class Inheritance)
1)仅在必要时,才使用类型继承。
2)用const标注只读的参数(参数指向的数据是只读的,而不是参数本身)。
3)用const标注不改变数据的函数。
软件工程中最基本的复审手段,就是同伴复审。
1. 谁来做代码复审?即最有经验、熟悉这一部分代码的人。对于至关重要的代码,我们要请不止一个人来做代码复审。
1)代码复审的目的在于:
2)找出代码的错误,比如:
2. 编码错误,比如一些碰巧骗过了编译器的错误
3. 不符合团队代码规范的地方
4. 发现逻辑错误,程序可以编译通过,但是代码的逻辑是错的
5. 发现算法错误,比如使用的算法不够优化,边界条件没有处理好等
6. 发现潜在的错误和回归性错误—当前的修改导致以前修复的缺陷又重新出现
7. 发现可能需要改进的地方
8. 教育(互相教育)开发人员,传授经验,让更多的成员熟悉项目各部分的代码,同时熟悉和应用领域相关的实际知识
构建之法学习(4)