免费下载案例集|20+数字化领先企业人才培养实践经验 了解详情
写点什么

用 Qi4j 进行面向组合编程

  • 2009-01-04
  • 本文字数:3655 字

    阅读完需:约 12 分钟

长期以来,通过 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 HumanComposite
extends 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


译者简介:罗小平,上海某大型公司互联网中心技术总监, CSDN 大版主,网络 ID 为 lxpbuaa(桂枝香在故国晚秋),曾著有《Delphi 精要》一书。个人博客为 http://blog.csdn.net/lxpbuaa ,他的 Email 和 MSN 为 lxpbuaa AT 263.net

给 InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家加入到 InfoQ 中文站用户讨论组中与我们的编辑和其他读者朋友交流。

2009-01-04 20:258306
用户头像

发布了 26 篇内容, 共 78741 次阅读, 收获喜欢 2 次。

关注

评论

发布
暂无评论
发现更多内容

重磅来袭!权限框架的里程碑,Spring Security电子版教程已问世

做梦都在改BUG

Java spring spring security 权限管理系统

“三问五步”落地医疗行业数据安全建设体系|盾见

极盾科技

数据安全

零信任是什么意思?与堡垒机有什么区别?

行云管家

网络安全 堡垒机 零信任

抬杠小能手GPT

林十二XII

来了!昇腾MindStudio全流程工具链分论坛精彩回顾,助力高效开发和迁移效率提升

科技热闻

苹果电脑超高清4K动态壁纸:Live Wallpaper & Themes 4K Pro

Rose

Mac壁纸软件 花见壁纸 Live Wallpaper 动态壁纸高清

流批一体数据交换引擎解决方案

weigeonlyyou

物联网 数据迁移 ETL系统 Kafka ETL 流批一体化

Mac电脑显示“打不开“XXX”,因为它来自身份不明的开发者的解决办法

Rose

Mac软件打不开 苹果软件 app已损坏

ATLAS.ti 8 for Mac(定性数据分析工具) v8.4.4汉化版

Rose

数据分析 苹果软件资源站 ATLAS.ti 8 ATLAS.ti 8 Mac破解版

网心科技荣获第二十届“深圳知名品牌”荣誉称号

网心科技

在行 | “数智”为离散制造发展注入动能

用友BIP

构建万物互联,华为云IoT+鸿蒙重燃物体感知

华为云开发者联盟

鸿蒙 物联网 华为云 华为云开发者联盟 企业号 5 月 PK 榜

京喜APP - 图片库优化 | 京东云技术团队

京东科技开发者

性能优化 APP开发 企业号 5 月 PK 榜 图片库优化

2023年北京.NET线下技术沙龙来了!大咖分享,还有精品好礼等你

MASA技术团队

.net MASA

PhotoBulk:Mac上批量调整图片大小、分辨率、添加水印和转换格式的工具

Rose

苹果软件资源站 PhotoBulk for Mac 图片水印添加 批量调整图片 PhotoBulk Mac破解版

MAMP Pro(web开发环境)MAMP Pro使用技巧概述

Rose

MAMP Pro破解 MAMP Pro Mac下载 web环境开发 MAMP PRO激活码 MAMP Pro安装教程

独家巨献!阿里专家兼Github贡献者,整理的SpringBoot入门到成神

做梦都在改BUG

Java spring 架构 微服务 Spring Boot

Webpack5构建性能优化:构建耗时从150s到60s再到10s | 京东云技术团队

京东科技开发者

性能优化 webpack webpack-tapable 企业号 5 月 PK 榜

Blender操作笔记——基本操作

Finovy Cloud

blender 3D绘图

揭秘Karmada百倍集群规模多云基础设施体系

华为云开发者联盟

云计算 云原生 华为云 华为云开发者联盟 企业号 5 月 PK 榜

如何做好项目管理工作

老张

项目管理 pmp PMP Certification

Prompt learning 教学[基础篇]:prompt基本原则以及使用场景技巧助力你更好使用chatgpt,得到你想要的答案

汀丶人工智能

人工智能 自然语言处理 深度学习 ChatGPT prompt learning

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

京东科技开发者

ios 单元测试 代码覆盖率 Bamboo 企业号 5 月 PK 榜

如何选择正确的压缩方式?

ScaleFlux

智能硬件 数据压缩 计算存储 NVMeSSD

秒验 创建应用

MobTech袤博科技

带你简单了解Chatgpt背后的秘密:大语言模型所需要条件(数据算法算力)以及其当前阶段的缺点局限性

汀丶人工智能

人工智能 ChatGPT

Mac苹果电脑如何设置色彩滤镜?

Rose

MacBook 苹果电脑使用教程 色彩滤镜功能 Mac使用

泰裤拉,安卓反编译居然可以这么简单——Jadx

吴脑的键客

共筑数字化未来 金山办公携手华为云完成文档中心和GaussDB适配

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 企业号 5 月 PK 榜

提升打字速度,Master of Typing 3中文很简单~

真大的脸盆

Mac Mac 软件 打字练习 打字软件

来了!昇腾MindStudio全流程工具链分论坛精彩回顾,助力高效开发和迁移效率提升

Geek_2d6073

用Qi4j进行面向组合编程_Java_Rickard Öberg_InfoQ精选文章