《代码大全》读书笔记
1. 用错误处理代码来处理预期会发生的状况,用断言来处理绝不应该发生的状况。
2. 隔栏:以防御式编程为目的而进行隔离的一种办法,就是把某些接口选定为“安全”的区域边界,对穿越安全边界的数据进行合法性的校验,并当数据非法时做出敏锐的反映。
3. 隔栏的使用让断言和错误处理有了清晰的区分,隔栏外部的程序应使用错误处理技术,在那里对数据做的任何假定都是不安全的。在隔栏内部的程序就应该使用断言技术,因为传进来的数据应该在通过隔栏时就已经被清理过了。如果隔栏内部的某个子程序检测到了错误的数据,那么应该是程序里的错误而不是数据里的错误。
4. 用预处理器来选择性的编译代码,可以让调试代码不备被译。调试的时候如果要兼顾到性能,可以生成方法存根,让这个方法快速的返回一个值。
5. 在设计一个类时,检查每一个公共程序,看是否需要一个互补的操作。
6. 类的接口应该实现一致的抽象层次。每一个类都要实现一个ADT,而且仅实现这个ADT。
7. 把不相干的信息转移到其它类中,如果你发现某一个类的一半子程序使用一半数据,而另一半子程序却使用了另一半数据,那么这其实是两个类,应该分开它们。、
8. 尽可能让接口可编程,而不是表达语义。每一个接口都有可编程部分和语义表达部分。语义表达部分说明该接口如何被使用,可以写成注释的方式,但最好是转换成编程接口的方式,比如用断言。
9. 预防在修改类时破坏类原有的抽象。在对类进行修改的过程当中,可能会增加一些额外的功能,这些功能并不十分适用于原有的接口(违反了实现一个ADT的原则)。
10. 不要添加与抽象接口不一致的公共成员,这样会破坏该类抽象的完整性。
11. 抽象通过一个让你忽略实现细节的模型来管理复杂度,而封装则强制阻止你看到的细节(即便你想这么做)。
12. 不要暴露数据成员,这样会破坏封装性,如果暴露的是Get或者Set这些成员的方法,那么它们的封装行还是完好的。
13. 如果你仅仅只是想使用这个类的实现,那么就使用包含而不要考虑继承。
14. 为未来要做的工作进行准备的最好办法,并非是创建几个绝非必要的继承结构,而是使目前的结构尽可能的简单,清晰,直接。
15. 如果多个类共享数据而非行为,应该创建这些类可以包含的共用对象;如果多个类共享行为而非数据,应该让它们从共同的基类继承而来,并在基类中定义公用的子程序。如果多个类共享行为同时共享数据,应该让它们从共同的基类继承而来,并在基类中定义公用的子程序和成员数据。当你想从基类控制接口时,使用继承,当你想自己控制接口时,使用包含。
16. 与直接使用全局数据相比,直接使用访问器子程序来操作全局数据有很多好处。你可以改变数据结构而无需修改程序本身。你可以监视对这些数据的访问。“使用访问器子程序”这条纪律还可以促使你思考有关数据是否就应该是全局的。
17. 把代码放到精心分解的一组类中,比起把代码全部塞进某个更大的类里面,前者更容易在其它程序中重用。如果有一部分代码,它们只是在程序的某一个地方调用到,只要它可以被理解为一个较大类的一部分,而且这部分代码可能会在其他程序中用到,就可以把它提出来形成一个单独的类。
18. 子程序最好是有单一目的,实现单一功能。
19. 子程序内聚性分类:
第一, 功能上的内聚性:是最强也是最好的内聚性,也就是说让一个子程序只执行一项操作。
第二, 第二,顺序上的内聚性:是指子程序上包含有需要按特定顺序执行的操作,这些步骤需要共享数据,而且只有在全部执行完毕后才完成了一项完整的功能。这样的程序应该分别写成几个子程序然后在其它子程序里调用。
第三, 通信上的内聚性,是指一个子程序中不同的操作使用了同样的数据,但不存在其它的任何联系。这种情况应该将这个子程序进一步拆分成几个子程序,然后在原本具有通信内聚性子程序的更高层子程序嗲用这两个子程序。
第四, 临时内聚性是指含有一些因为需要同时执行才放到一起操作的子程序。如:startup(),CompleteEmployee(),shutdown()。这是可以把临时子程序看成是一系列事件的组织者,应该让原本那个具有临时内聚性的子程序去调用其它俄子程序,有这些子程序来完成特定的操作,而不是有它直接执行所有的操作。
20. 对于每个子程序都要考虑到错误处理,如果有输入,那就可以用错误的输入数值,或者从其它子程序返回无效数值来检验。