InfoQ: 用Qi4j进行面向组合编程

来源:百度文库 编辑:神马文学网 时间:2024/04/23 21:38:47

用Qi4j进行面向组合编程

作者 Rickard Öberg译者 罗小平 发布于 2009年1月4日 下午8时25分

长期以来,通过OOP对象集对领域概念进行建模的目标并未得到充分实现。那么迄今为止,我们万般努力但难以解决的根本问题到底是什么?有没有更好的解决办法?在本文中我们将介绍面向组合编程(COP,Composite Oriented Programming)的概念,展示它如何规避OOP存在的一些问题,并重先点燃使用可重用部件组装领域建模的希望。

问题

我为何物?实际中我可以有多重身份。某些时候,我是编写软件的开发者;另些时候,我是给大家讲解某个有关Java话题的软件开发者。但其他时候,我可能有完全不同的身份,比如银行的客户、大学的校友。简而言之,我不同时候的身份,由当时的具体环境决定。在不同的环境中,我需要通过不同接口、以相应行为与之交互。在所有这些环境中,我其实就是具有不同接口同一个对象。在我编写软件的时候银行不会出现另一个我。

解决方案

如果在软件中用OOP为我建模,一些人会将我设计为一个Developer类。但这样一个类显然不能在不同时候表达我的不同身份(比如一个大学校友,因为 Developer类不包括社交概念)。因此对我建模的结果,可能会是几个不同的类,或者在一个类中实现所有行为。在本文中,我们提出另一种方案:利用 Mixin(混入)概念完成这个实现。

组合

首先,Mixin被实现为一个普通Java类,它通常实现一个特定接口,而这个接口将是Composite所要暴露接口的一部分。接着,我们用如下方法声明一个Composite:创建一个Java接口,用注解声明它要用到的Mixin,并且使用“extends”关键字指明需暴露哪些领域接口。通过这一方法,我们就可以载一个集中的地点明确定义Composite的结构和行为。

使用COP时,虽然把横切关注点保留在独立的实现类中是一个不错的主意,但是它们的装配或组成方式应该还是集中用Java接口来说明。为了避免出现重复的说明,我们可以通过“extends”关键字重用被扩展接口中的声明。这样,如果修改了被扩展接口,从其扩展而来的Composite接口声明就会自动改变,不需我们逐个做人工修改。

利用这种办法,我们相信可以做到两全其美:存在于各个单独实现类中的关注点实现了分离,每个类仅需关注特定的任务;对于Composite最终应该是什么样的描述则是集中和确定的,这样,Composite的开发者就可以全权负责定义中应该包含的内容。

代码示例

Composite在实际中如何具体应用呢?让我们看一个例子。假设我是一个Composite,那么可如下描述我:

@Mixins({DeveloperMixin.class, SpeakerMixin.class, AlumniMixin.class})public interface HumanCompositeextends Developer, Speaker, Alumni, Composite{}

被扩展接口中包含了实际要被调用的方法,由Qi4j运行时环境去构造一个Composite实例,这一实例可以将“来自客户端的调用”路由给特定的 Mixin实例。但从客户端的角度看,这个Composite实例完全是一个普通Java对象(尽管与普通OOP方法实现的领域对象比较起来,它有更多的接口)。像Developer 这样的领域接口是普通接口,和Qi4j无任何特殊关系,其实现本身也是实现了该接口的简单Java类。但是上面所说的领域对象的身份是由 Composite实例而非某个Mixin实例定义的,这样就解决了身份问题:对“我”这个对象的引用,可在系统范围里传递,并被传递给在特定上下文环境中很有用的接口。如果引入更多领域或上下文环境时,也可通过扩展这个Composite来处理。

如需想创建另一个也使用Alumni接口的Composite及其实现,我们可以让此接口也扩展Alumni,并声明使用相同的Mixin。因此,多重继承和复用基础类的常见问题也解决了。

LMM结构

软件通常是在纸上分模块、分层进行设计的。我们对类似如下的设计图已经非常熟悉了:

这个图包含有多个模块,不同模块构成了不同层,而各层又叠放在一起。我们可将这种设计方法简称为LMM(Layered Modules Metaphor,分层模块表示法)。LMM图可用来传达一个整体应用的总括,不让我们陷入太多的细节当中。严格按照LMM的要求设计系统,可减少系统缺陷、降低长期维护成本,这种系统对未来变更的反映也可更为灵活。绝大多数项目都使用LMM来描述应用程序的构成方式,许多项目设法遵循LMM,但只有很少的项目是按此执行的。我想我们都已经看到过很多惨痛教训,比如在基础结构层的类中直接使用Web层的类。

Qi4j支持的结构

Qi4j目前已经能为LMM提供明确的支持,这有助于规范团队中开发人员的行为。Qi4j应用结构是一个小规则集:

  • 结构
  • 所有结构在应用启动时静态声明
  • 所有Composite实例都有所属模块
  • 所有服务都有所属模块
  • 所有模块都有所属层
  • 所有层都有上下层次关系(但不循环)
  • 所有层一起构成了应用
  • 访问
  • 模块能访问同层的所有其他模块
  • 层能访问它的直接下级层(不能跃层访问)
  • 可见性
  • Composite实例缺省只在所属模块内可见
  • Composite实例也能设置为在层内或层间可见

看起来比较复杂,其实不然。本质上,Composite实例在创建它们的模块中都是私有的,除非显式声明为对模块外或层外公开。这和在普通Java中使用“public”和“pirvate”修饰词限定类的可见性是类似的。

Qi4j目前尚不提供其他可供选择的结构,但其包含了构造常用应用程序结构的简单方法(包括一个层中只包含一个模块的情况)。

结构的使用

领域代码无需了解应用程序结构,但可以用@Structure注解的形式出现。如下例所示:

CompositeBuilderFactory将在创建时被注入Mixin,而且它仅允许代码实例化结构中可见的Composite。

结构发挥作用的另一个常见例子发生在查找服务时。若在相同模块中有且仅有一个要求类型的服务,那么就无需引入额外装配(Assembly)。服务的使用变得十分简单。

例如,如果服务GenericInventory被声明在Bread模块中,那么每个inventory服务实例都将受其邻近各自客户端的程度约束。

应用结构的生成

Qi4j 应用需通过应用程序代码实现自举,最简单的启动方法大致如下:

另外,还可利用SingletonAssembler编写上述功能:

SingletonAssembler是一个用于创建单层单模块Qi4j应用程序的工具类。

newApplication()方法也可接收Assembly[][][]类型的参数,由此可创建“千层饼式”分层结构的应用环境(除了第一个和最后一个层,其他都有相邻的上、下层)。例如:

上面代码实现的结构如下图示:

最后,如果应用程序结构十分复杂,还可将ApplicationAssembly实例作为参数传递给newApplication()方法。 ApplicationAssembly用类似迭代的形式创建全部LayerAssembly,再为每个LayerAssembly创建 ModuleAssembly。举例如下:

运行上面代码可得到如下结构:

结构化的好处

通过代码显式实现应用程序结构有两个显著的好处:

  1. 就近访问。
  2. 架构强制执行。

这意味着,越近的Composite优先级越高,越易访问;外部不能访问模块或层内私有的Composite。因为服务被实现为Composite,其解析方法更为含蓄,需要的装配配置也少得多。

Qi4j结构概念的另一个有趣之处在于每个应用都有一个静态结构组合,它可以通过工具来抽取并展示,而不必单独维护。这使得架构师、设计师或团队负责人可轻松跟踪开发人员对架构的遵循情况,很容易找到越轨者。

总结

本文通过实现于Java平台的Qi4j,简要讨论了COP的可行性。我们看到以传统OOP观念实现对象的Composite,是如何更好分离关注点(concerns),从而提升代码的质量和复用性的。此外,我们也讨论了显式建模应用结构的思路,这一结构通常只在纸面上而不是在代码中定义。通过显式建模应用结构,我们可以更容易落实架构执行并消除服务间的相互依赖。这将帮助我们创建更大规模的系统,而且随着引入越来越多的组件及服务,我们的系统不至被其自身的“重量”压垮。

最后要强调的一点是,COP和Qi4j中的绝大多数理念并非前无古人。我们现在做的,恰恰是在前人编程实践和各种框架中寻找各种优秀的思想和模式,并提炼出那些我们认为在编写软件及保持容易理解且易于维护方面都能给开发者提供帮助的内容。无论是开发软件还是我们的日常生活中,将古老的东西运用于新的环境都是非常重要的。

作者简介

Rickard Öberg曾参与过多个J2EE开源项目的开发工作,如JBoss、XDoclet和WebWork。他也是SiteVision CMS/portal平台(以AOP为基础)的首席架构师。现在服务于Jayway,主要关注方向是在新一轮以互联网为中心的应用中广泛采用的面向领域软件开发技术。

Jayway 简介

Jayway是瑞典一家拥有90位认证Java专家的一流Java公司。我们的服务范围包括:内部开发、专业咨询以及Java平台相关指导与培训。我们对开源软件有坚定信念,并正为大量开源项目积极工作。我们珍视知识的交流与共享。Jayway的网站是www.jayway.com。

阅读英文原文:Composite Oriented Programming with Qi4j。