不使用buzzwords说明AOP(翻译)- -
The Ted Neward Challenge (AOP without the buzzwords)
不使用buzzwords说明AOP
作者:
译者:flyingbug
译注:
翻译这篇文章,不知是被其对AOP看法吸引还是其对AOP的描述方式吸引,总之这是AOP文章中看着最舒心的一篇。翻译的水平不高,为了不误人子弟,在上面配上了英文原文的链接,如果有不清楚的地方,可以原文对照一下。
在TSS的java讨论会的AOP小组讨论结束后Ted Neward发出了一个挑战:"an explanation of AOP without resorting to buzzwords."本文作者Adrian Colyer接下了这个挑战,并写出了这篇非常好的文章,从设计角度清晰的说明了AOP解决了什么问题,而且没有用一个令我头大的诸如point cut等等之类的buzzwords(强意词?呵呵)。
每天软件开发领域都会冒出各种各样新鲜的词汇,不知道其他人怎么样,反正我是经常头晕,记得曾经为Martin Fowler的active record头晕了N久(Martin好像很喜欢造词@_@),我希望能多一些Adrian Colyer这样的高人,好让我等下辈不至于追随的那么痛苦。
以下单词和词组在后面的文章中将不会出现:scattering, tangling, crosscutting, modularity, encapsulation, abstraction, dominant decomposition, concern.
当编写软件的时候,一个好的想法是:能够将程序中的每一个想法、概念、需求等等只做一处实现.
举个例子,如果编写一个银行系统,银行帐户的概念可能有一个直接的表示,比如:BankAccount类。如果写一个医疗程序,病人的概念可能有一个直接的表示,比如:Patient类。一个设计上的概念指向一个实现结构。
现在考虑一个简单MVC程序。一个简单的设计层面的需求是:随着model类的状态的变化,所有注册过的view都要被改变-但是这样一个单独的设计需求却很难被设计到一个单独实现结构当中。在一个典型的实现中,你将看到notifyObservers()这样的方法遍及能够使model改变状态的方法中。这个实现背离了需求到实现一对一映射的目标,代之以需求到实现一对多的结构。
设计中的概念和需求可以看作软件演进的一个元素。设计中这个元素到实现一对一的映射使得设计可以容易的添加、删除和维护,而如果元素到实现的映射是一对多的将导致设计很难进行添加、删除和维护,因为需要很多地方更改相同的实现,并且必须保证对他们的更改是完全的和一致的。
在实际的软件系统中,开发者可能遇到最极端的需求到实现的映射是old chestnut, tracing。举个例子,一个设计描述“当trace被设为可用,那么所有方法的进入和返回都要记录在一个trace buffer。”在我经历过的一个系统中,一个单独的需求到实现的映射超过1:100,000。想象一下所有这些实现都要在维护和添加新功能时被更改。当面对这样的情况,大多数的程序员会使这个需求到实现的映射失效来代替修改。
在上面提到的系统中还有一个相似的例子,这是一个用日志来记录程序异常的需求-这个需求到实现的映射超过1:8,000。但是以上都是极端的例子,大多数情况下很难碰到这样巨大的比率。更普遍的情况是一个需求到实现的映射率大概在1:20或者1:30左右。上面描述的MVC需求一般都会在这个范围内。如果想找一个开源的例子研究一下,可以看看Eclipse JDT compiler编译部分的代码。
下 面让我们看看新的方式,你将看到更加巧妙的方法,就像一个类实现一个接口那样。我们仍然要保持需求到实现一对一的清晰的映射,但是在很多情况下,一个类会 用它的方法和状态的一个子集来提供对一个接口的实现,但这是不够严密的。需求虽然被定位到一个实现,但是这个实现的边界是模糊的。据我所知,许多程序员通 过把关于这个接口的实现的方法集放在同一个源文件来实现定位,并且在很多情况下这是一个很不错的方法。在这里我想做的是,描述当你开始努力得到一个需求到 实现的一对一的清晰的实现时可能会遭遇的情况。
现 在让我们来看一看这个问题的另一面。我们要每一个设计上的需求清晰的映射到一个实现结构上。我们也要每一个实现结构仅映射到一个设计需求上。我们已经看到 一些设计上的需求需要在实现中展开,这就意味着在实现的某些部分是不可避免的必须处理多个需求。这就是需求到实现的多对一映射问题。再想想MVC的例子,model类正在处理至少两个设计上的需求:一个是描述他们的模型是什么,另一个是当他们的状态发生变化时通知每一个注册的View。
这 种多对一的问题和一对多的问题一样麻烦。举个例子,它意味着当一个程序员修改一个类的时候,他必须意识到并且正确的处理这个类描述或使用的所有需求。经验 显示,在某些应用领域做这些工作是非常的麻烦,所以一些特殊的框架被发展出来为这种多对一映射问题提供通用的处理。一个例子是企业应用开发,在这个领域中 要求开发者首先必须对业务领域的问题非常熟悉,还要求开发者管理在业务领域的诸如:事务,数据持久和安全方面的需求。在设计中,包含业务逻辑和许多其他需 求的类是很难被重用和测试的(举个例子,你想得到模型类,却不得不把他们纠缠到其他不同的需求中)。
所以在真正的大型系统中,我们需要面对的不是需求与实现间一对一的映射,而是多对多映射。这就是为什么软件如此难以维护,难以理解并且如此复杂的原因。这不是开发人员的错,OO语言提供的能力和方法使我们不能得到一个设计需求到实现结构的清晰的映射(在本文中我们已经看到了几个这样的例子),因此我们看到的例子没有一个是实现结构清晰的映射到设计需求上。而这正是AOP尝试解决的问题。它使我们能够尽可能的接近一对一映射的目标。AOP通过加入一个新的称作方面的概念来解决这个问题,方面使得针对设计上的需求可以保存在一个地方,像上面提到的MVC中的view通知需求,这是OOP所无法做到的。
当你开始学习AOP,我希望你不仅把它看作现有软件的一个辅助手段,而且也是软件设计和实现的一个完整的部分。这也是为什么AspectJ将AOP的概念直接集成到一个语言中。请记住,我们需要一个设计和实现的一对一的映射,并且无论何时,我们向任何方向偏离这个比率都会是我们陷入麻烦。AOP是最能使我们接近一对一这个目标的编程方法。