“JUnit Cook's Tour”中的可用性和维护性
简介:在“JUnit: A Cook's Tour”一文中,作者 Erich Gamma 和 Kent Beck 讨论了 JUnit 的设计。他们指出,与很多成熟框架中的关键抽象一样, TestCase 也有很高的模式密集,易于使用而难以修改。在 AOP@Work 系列的第四 期文章中,Wes Isberg 重温了 Cook's Tour,说明如何通过使用 AOP 切入点设 计来代替面向对象设计,在一定程度上避免导致成熟的设计难以修改的模式密集 。
即使是最好的 Java 程序,也会随着时间的推移而老化。为了满 足新的需求,设计也在不断演化,关键对象承担着各种模式角色,直到它们变得 难以使用或者难以修改,最终不得不重构或者重写系统。面向方面的编程(AOP) 提供了一些将特性结合起来提供服务的更优雅的方法,这些方法可以减少交互、 降低工作量、延长设计和代码的寿命。
本文将分析 Erich Gamma 和 Kent Beck 在“JUnit: A Cook's Tour”(请参阅 参考资料)一 文中提出的设计。对于他们提出的每种 Java 模式,都给出一种 AspectJ 替代方 案,并说明这种方案是否满足下列标准设计目标:
功能性:提供的服 务是否强大、有用?
可用性:客户能否方便地得到服务?
可扩 展性:程序变化时是否容易扩展或者调整?
结合(分解) 性:能否与其他部分协作?
保护:面对运行时错误或者级联错误, 如何保障 API 的安全?
可理解性:代码是否清晰易懂?
设计的 每一步中,Gamma 和 Beck 都面临着两难选择,比如可用性与可维护性 、可理解性与结合性。在所有的选择中,他们采取的都是简单可用的路线,即便 这意味着要放弃次要的目标。因此,他们的设计使得编写单元测试变得很容易。 但我还是要问一问,如果使用 AOP 的话,能否避免其中一部分设计取舍呢?
这样问也许看起来不够通情达理,有些过于苛求。JUnit 把自己的工 作做得很好,设计中的取舍被很多开发人员所了解,并认为是很正常的做法。要 看看 AOP 能否做得更好,我必须问自己一些问题,比方说,能否增加更多的特性 ,使其更适合那些需要更多服务但不能满足 JUnit 最起码要求的客户。我这样做 不是为了改变 JUnit,而是要在达到主要目标的同时不放弃次要的设计目标。
本文中所有的例子都使用了 AspectJ,但也可用于其他 AOP 方法, 而且即使刚接触 AspectJ,这些例子也很容易理解。(事实上,阅读过 Cook's Tour 或者了解设计模式,可能要比您使用过 AspectJ 或 JUnit 更 有帮助。)