有些类的作者想让他们的类满足所有人的所有需要。这样的类已经被亲切地称为温尼贝戈(Winnebago)类。这种很常见和看似高尚的愿望令人忧虑。作为开发人员,我们必须记住,客户端要求增加的功能不一定合适我们编写的类。假设你是一个类的作者,10个客户端中每一个都请求增加不同的功能,如果同意,将会发生两件事情:
(1)你将不得不实现、测试和存档10个新特征。早先,你并没有把这些新特征当作要实现的抽象的一部分(这本身就是出现问题的一个信号)。
(2)10个客户端中的每一个都会得到9个他们并没有请求而且可能不必要、不想要的新特征。
每次增加一个特征去取悦一个客户,你就会扰乱和潜在地骚扰客户群的其他用户。曾经发生过这样的事情:原本是轻量级的而且很有用的类,经过一段时间后变得过于臃肿,不但不能做好每件事情,而且毫不夸张地说,它们已经变得每件事情都做不好了。
注意,在1.5节中,我们选择通过将其单个的成员函数声明为私有,明确指出不允许对IntSet和IntSetlter的实例进行初始化或赋值。拷贝一个集合可能导致大量开发工作,而在实践中很少需要这样的迭代器功能。我们可以推迟多余功能的实现和测试,除非对那个功能出现需求。推迟实现也是保持我们选择权的一种方法。这样做不仅可以使得实现、测试、文档和维护软件所需的工作更少,而且,在谨慎而行,不提早提供功能的情况下,我们既不用对它的行为负责,也不用对它的实现负责。实际上,不实现功能可以改善可用性。例如,让拷贝构造函数私自阻止无意地通过值传递一个对象,就是一种用于输入输出软件包(iostream package)的技术。
这种只要组件足够而不必完备的最小化方法适用于正在开发的大型工程,在这种工程中,组件的用户是“内部的”或组件的用户处在一个一旦需要即可快速请求和接收额外功能的位置。最极端的情况是,组件高度专业化并且作者是唯一有意向的使用者。在这种情况下,实现任何不必要的功能都可能是没有保证的。当然,若一个功能实现对一个抽象来说是固有的,则省略该功能实现将没有意义,比方说,对于一个商业组件库,其用户是付费顾客,他们期望强壮而完整的功能对象。这个问题并不是黑白分明的,在这两个极端之间存在一个范围,对应一个组件被广泛使用的程度。在进行这种权衡时,记住要考虑到功能总是容易添加而不容易删除。