第一篇 技术
1 基于Policy的Class设计
1.1 软件设计的多样性
专业软件设计师与新手的最大不同在于,前者知道什么可以有效运作,什么不可以。任何设计结构上的问题,都有许多合适的解法,然而它们各有不同规格并且各有优缺点,对眼前的问题可能合适也可能不合适。白板上可接受的方案,不一定真有实用价值。
设计一个软件系统很困难,因为它不断要求你做抉择。而程序设计犹如人生,抉择是困难的。
1.2 全功能型接口的失败
庞大的classes不能视为成功,因为它们会导致沉重的学习负荷,并且有“非必要之大规模”倾向,使得代码远比手工制作还慢。
理想上,一个良好的设计应该在编译期强制表现出大部分constraints(约束条件、规范)。
1.3 多重继承是救世主?
藉由多重继承来组合多项功能,会产生如下问题:
a.关于技术(mechanics)。目前并没有一成不变即可套用的代码,可以在某种受控情况下将继承而来的classes组合(assemble)起来。大多数时候你得小心协调继承而来的classes的运转,让它们得到所需的行为。
b.关于型别信息(Type information)。Base classes并没有足够的型别信息来继续完成它们的工作。
c.关于状态处理(state manipulation)。base classes实作之各种行为必须操作相同的state(数据)。这意味着它们必须虚继承一个持有该state的base class。由于总是由user classes继承library classes(而非反向),这会使设计更加复杂而且变得没有弹性。
1.4 Templates带来曙光
templates是一种很适合“组合各种行为”的机制,主要因为它们是“依赖使用者提供的型别信息”并且“在编译期才产生”的代码。
和一般的class不同,class templates可以以不同的方式定制。(举例特化)
犹有进者,对于带有多个参数的class templates,你可以采用partial template specialization(偏特化)。(举例)
template的编译期特性以及“可互相组合”特性,使它在设计期非常引人注目。然而一旦你开始尝试实作这些设计,你会遭遇一些不是那么浅白的问题:
a.你无法特化结构,你只能特化其成员函数。
b.成员函数的特化并不能“依理扩张”。(这里指成员函数不具有偏特化行为,cuigang)
c.程序库撰写者不能够提供多笔缺省值。
多重继承和templates两者互补,如果我们将templates和多重继承组合起来,将会产生非常具弹性的设备(device),应该很适合用来产生程序库中的“设计元素”(design elements)。