《代码整洁之道》笔记——第六章:对象和数据结构
1、我们不想其他人依赖的变量应该都声明为私有变量(private),并且不要公开这些私有变量,如加公共访问器或者改值器。
2、尽力去避免曝露代码的实现细节,而应该只对外界提供抽象接口。
3、对象与数据结构之间的差异:对象把数据隐藏于抽象之后,曝露操作数据的函数。数据结构曝露其数据,没有提供有意义的函数。
4、过程式代码(使用数据结构的代码)难以添加新数椐结构,因为必须修改所有函数。面向对象代码难以添加新函 数,因为必须修改所有类。如下:
(1)过程式代码。形状类中没有方法,所有的方法都在geometry类中。这样的话,每次添加新函数只需要在geometry了中添加一次就好,但每次添加新的形状类都要改动几乎全部geometry类中涉及到形状的函数。
(2)面向对象式代码。面向对象式代码中,area()方法是多态的,不需要有Ceometry类。所以,如果添加一个新形状,现有的函数一个也不会受到影响,但当添加新函数时所有的形状都得做修改。
这两种形式的代码并没有优劣之分,应该根据具体情形选择适当的形式。
5、得墨忒耳定律也叫做“最少了解原理”,是一种软件设计原理,尤其是应用到面向对象的程序设计中,基本原理为:
- 每个对象对其他对象只能有最少的了解:只有总体才能接近个别对象;
- 每个对象只能和自己的朋友对话:不要和陌生人说话;
- 只和自己最亲密的朋友对话。
函数的得墨忒耳法则规定,某个对象的任何方法都应该只调用属于以下情形的方法:
class Demeter
{
public:
void example(B &b);
private:
A *a;
int func(){}
}
void Demeter::example(B &b)
{
C c;
int f = func(); <------------------1. 它自身
b.invert(); <----------------------2. 传入该方法的任何参数
a = new A();
a->setActive(); <------------------3. 它创建的任何对象
c.print(); <-----------------------4. 任何直接持有的组件对象
}
得墨忒耳法则缩小了调用类中的响应集的规模,结果以这种方式设计的类的错误也往往更少。
6、应该把链式调用做切分,如:
//把 final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath(); //切分为: Options opts = ctxt.getOptions(); File scratchDir = opts.getScratchDir(); final String outputDir = scratchDir.getAbsolutePath();
final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();//是违反得墨忒耳法则的。 //那么如果变成: Options opts = ctxt.getOptions(); File scratchDir = opts.getScratchDir(); final String outputDir = scratchDir.getAbsolutePath(); //是否会违反呢?
//这取决于ctxt、Options和ScratchDir是对象还是数据结构。如果是对象,则它们的内部结构应当隐藏而不曝露,而有关其内部细节的知识就明显违反了得墨忒耳律。如果ctxt、Options和ScratchDir只是数据结构,没有任何行为,则它们自然会曝露其内部结构,得墨忒耳律也就不适用了。
//如果它们是对象,我们又必须要拿到这些信息怎么办?可以探索这些变量的用途是什么?假设它的用途是用于创建文件,那么可以直接让ctxt来做这件事(ctxt.createScratchFileStream())。这就不会违反德墨忒尔法则了。
7、最为精练的数据结构,是一个只有公共变量、没有函数的类。这种数据结构有时被称为数据传送对象,或DTO。
8、Active Record是一种特殊的DTO形式。它们是拥有公共(或可豆式访问的)变量的数据结构,但通常也会拥有类似save和find这样的可浏览方法。但注意不要把业务规则方法塞进这类数据结构中,因为这导致了数据结构和对象的混杂体。