面向对象编程的对象有两种,第一种是现实世界中的对象在软件中的表示(暗含了类间的一部分关系,如包含等),另一种是为了表示现实世界中对象之间相互作用而虚构起来的类(暗含了类间的另一部分关系,如协作等)。面向对象的思维有两种突出表现形式,第一种是专注于对象本身的活动,尽量让对象本身的活动限制在自身,当然那些本来就需要其他对象协助的工作是决不能让一个类自身完全负责的,这种表现形式得到的是高内聚、低内聚性;第二种表现形式是面向契约编程,在第一种表现形式中还要求不能只关注于某个具体类本身的活动,需要的是进行抽象,把那些公共的东西都抽离出来,放到上一层类中作为契约,而让后继的类实现这些契约,或加入一些更加具体的契约让其后继的类实现,解决一般性的问题总是比解决某个具体问题更容易。面向契约编程中,许多动作都在高层完成,可以避免为许多低层类做同样的操作。理解了面向契约编程后,不管是JAVA中的接口、C++中的虚基类或模板,使用的原则都是一样的,最重要(但也最难)的事情就是建立合适的契约(抽象的本质)。
面向对象的方式在短期内是看不到好处的,甚至还会使实现功能的时间变长(实际中许多项目有的时候实现功能是优先级最高的事情),这是因为各个类自成一体,需要维护他们之间的交互,另外为了维护契约,需要做大量与功能无关的工作,并且如果事先没有做好抽象,契约建立得不合适,后面往往面临着改动契约,改动契约的伤害是巨大的,这意味着依赖于这些契约的实际操作很可能需要变化。另一方面,就算是在高层对对象进行操作,但是每一个操作的实际步骤还是需要一行代码一行代码地敲出来。基于这两方面的考虑,所以面向对象的编程方式短期内不会得到好处。但是从长远的角度来看呢,假设契约建立是合适的,许多可以共享的功能都已经以合适的类实现,那么复用就会变得容易很多,可以直接复用或写一个外覆类或Adapter之类的东西就够了,应对新添加的特殊情况也容易许多,写一个针对这种特殊情况的子类就好了,修改很小,编译变得更快。
面向对象编程的方式是一把双刃剑,好的抽象可以节省工程的整体时间,不好的抽象会更加浪费工程的时间。还有就是基于契约的编程方式意味着按规矩办事,所以到了后期有的操作不得不在很别扭的方式下实现,比如,本来有一个可以直接利用的类,但是为了符合契约,却不得不多写一个外覆类或Adapter等。好的抽象来源于好的需求分析,好的需求分析不是具体而完备的,而是对高层的,具有重大影响的那些需求的全面分析。好的需求分析只能经验中得来——从自己的经验和别人的——除此之外别无他法。