诊断Java代码: 消除包间的耦合关联

测试优先编程(test-first programming)中反复遇到的一个问题是,似乎不可能对程序的许多部分进行自动测试。尤其当程序在很大程度上要利用外部资源和库时,似乎很难对它进行测试,因为没有很好的方法来模拟程序与这些外部资源的连接。

然而,虽然只使用 Java 代码很难测试这样的程序,但有一种类型的编程(带有开发工具)可以解决这个问题 ― 基于组件的编程。

基于组件的编程和 Java 语言

我所说的基于组件的编程是指什么?我只是指,编程时程序的各个单元处于分布状态,而不是象 JavaBeans 或类似技术这样的运行时“组件”。

从概念上讲,这些分布的各个单元大致类似于 Java 包。然而,Java 语言中的包非常受限,因为它们相互之间是耦合的。每个包中的类与它们导入的包之间是硬连接的(因为这些类必须显式地引用所导入的包)。

由于这些包之间是相互耦合的,因此很难统一用提供同一功能的其它包的引用来替代程序中这些包的引用。

同样,独立开发的各个团队可能偶尔会用到重复的包名,这些团队试图使用对方的包时,就会引起问题。为确保包名的唯一性,Sun 强烈主张每个开发团队使用这样的约定:用倒序排列的因特网地址作为团队开发的所有包的前缀。开发人员通常都遵守这个约定,但未必总是如此。

然而即便严格遵守了这个包命名约定,仍然有其它一些原因使程序员想解除组件之间的耦合。其中一个原因是,这样可以更有效地测试这些组件 ― 在谈到基于组件的编程工具(Jiazzi 组件系统)时,会解释这一点。

Jiazzi:针对 Java 语言的组件系统

Jiazzi 是一个富有前途的、用 Java 语言进行基于组件编程的系统,它与 JVM 完全兼容,并且完全解除了各组件间的耦合,它是犹他大学计算机科学系所开发的一个项目。这个系统使程序员可以叠加组件,并在现有 Java 代码之上将这些组件连接起来。而不需修改 Java 语言或 JVM。

开发人员的描述

Jiazzi 开发人员是这样描述的:

……是这样一个系统,支持用 Java 编写的大规模二进制组件的构造 [添加了对用 Java 编写的大规模二进制组件的支持]。可以将 Jiazzi 组件看成是对 Java 包的泛化,同时向这些 Java 包添加了外部链接和独立编译的支持。Jiazzi 组件很实用,因为它们是从标准 Java 源代码构造出来的。Jiazzi 既不需要对 Java 语言扩展,也不需要对编写 Java 源码进行特殊的约定,这些扩展和约定将写在组件内部。我们的组件是富有表现力的,因为 Jiazzi 支持循环组件链接和 mixin,在开放的类模式中一起使用了循环组件链接和 mixin,这种模式支持将具有新特性的模块添加到现有的类。

当前的 Jiazzi 实现用 链接程序(linker,用于操作组件)和 存根生成器(使 Jiazzi 可以与常规的 Java 源码编译器共同使用)集成进了 Java 平台。Jiazzi 中的组件可以包含、导入和导出 Java 类,可以跨组件边界使用 Java 平台的用于继承的语言内支持。除了富有表现力之外,这些组件还很健壮 ― 可以分别对组件的实现和链接进行类型检查。

观察解除组件的耦合

让我们研究一个 Java 包 view 的简短示例,来看一下 Jiazzi 如何解除组件间的耦合,这个示例用到了 GUI 库包。我们将调用 toolkit 包。为了引用该包中的所有类,在我们的包中源文件的开头,放置了一条 import 语句:

package view;
import toolkit.*;
...

时间: 2024-09-04 16:39:04

诊断Java代码: 消除包间的耦合关联的相关文章

诊断Java代码

诊断Java代码: Broken Dispatch错误模式 诊断Java代码: Double Descent错误模式 诊断Java代码: Impostor Type错误模式 诊断Java代码: Java编程中的断言和时态逻辑 诊断Java代码: Liar View错误模式 诊断Java代码: Repl提供交互式评价 诊断Java代码: 单元测试与自动化代码分析协同工作 诊断Java代码: 将时态逻辑用于错误模式 诊断Java代码: 进行记录器测试以正确调用方法 诊断Java代码: 空标志错误模式

诊断Java代码: Impostor Type错误模式

当使用字段中特殊的标记来区别对象类型时,可能会产生标记对相关数据误贴标签的错误 ― 通称为 Impostor Type 错误模式.在诊断 Java 代码的这一部分中,Eric Allen 对这个错误的症状和起因进行了分析,详细说明了预防错误发生的方法,并讨论了一种吸引人的混合实现方法,这种方法不使用 impostor type,但最后,还是有很多相同的缺点产生.请在 讨论论坛与作者及其他读者分享您对本文的看法. 程序中除了最无关紧要的部分外都要对某些数据类型进行操作.静态类型系统提供了一种方法,

诊断Java代码: 进行记录器测试以正确调用方法

用 JUnit进行单元测试是一个功能强大的方法,它可以确保您的代码基础的完整性,但是一些不变量比其他(方法调用序列是其中一种)更难测试.在诊断Java 代码这一部分,Eric Allen描述了怎样在您的单元测试中使用记录器(一种特殊的侦听器),来确保一个方法调用序列按恰当的顺序发生.请点击文章顶部和底部的 讨论,与作者和其他读者在论坛上分享您关于本文的看法. 随着时间的推移,当系统开发人员,维护人员甚至是系统详细说明改变时,JUnit 框架提供一个很好的方法来改善系统的坚固性.通过测试,您可以检

诊断Java代码: 设计可扩展应用程序,第3部分

对应于我们上一篇" 诊断 Java 代码"中所讨论的透明盒可扩展性,黑盒可扩展性是指,在源代码既不能查看也不能修改时,可以扩展软件系统的方法.通常通过系统配置或使用特定于应用程序的脚本语言来进行这样的扩展.在本专题中,Eric Allen 讨论了何时设计黑盒可 扩展性的系统是有意义的,并提供了如何有效地实现这一设计的一些想法.阅读了本文后,您将知道何时使用黑盒并掌握如何实现它的一些技巧. 我已在以前的文章中谈到了代码重用设计策略的重要性(主要是因为各种信息处理任务的差异和相应费用的增加

诊断Java代码: 设计可扩展的应用程序,第2部分

玻璃箱可扩展性是指这样一种方式:软件系统可在源代码可以查看而不可以修改时被扩展 ― 它是黑箱设计(在这里构建扩展时,不查看原始代码)和开放箱设计(扩展代码直接写入到基础代码)的折衷.因为新的扩展直接建立在原始代码基础上,但不改动原始代码,所以,玻璃箱设计或许是扩展一个软件系统最有效.最安全的方法.在 诊断 Java 代码的这一部分中,Eric Allen 详述了上个月谈及的玻璃箱可扩展性主题.读完本文后,您将知道什么时候使用玻璃箱,并将获得一些如何实现它的提示. 随着信息处理任务(和与之相关的成

诊断Java代码:孤线程(Orphaned Thread)错误模式

在多线程代码中,使用驱动其它线程所负责的动作的单个主线程是常见的.这个主线程发送消息,通常是通过把它们放到一个队列中,然后其它线程处理这些消息.但是如果主线程抛出一个异常,那么剩余的线程会继续运行,等待更多输入到该队列,导致程序冻结.在诊断 Java 代码的这一部分中,专职 Java 开发者兼兼职捉虫者 Eric Allen 讨论检测.修复和避免这一错误模式. 用多线程编写代码对程序员大有好处.多线程能使编程(和程序)进行得快得多,而且代码能有效得多地使用资源.然而,跟生活中的很多事情一样,多线

诊断Java代码: 将时态逻辑用于错误模式

尽管传统的断言可以增加对 Java 代码所作的检查次数,但仅用它们,还是有许多检查无法完成.处理这种情况的方法之一就是使用 时态逻辑.请回忆上个月的文章" Assertions and temporal logic in Java programming",时态逻辑有助于提供比程序中的方法更有力的断言,从而有助于增强用其它方式难以正式表达的不变量. 我们不必费力搜寻去发现有助于防止我们程序出错的许多有用的不变量.实际上,可以通过使用此类时态逻辑断言来加大我们消除一些最常见错误模式的力度

诊断 Java 代码:设计轻松的代码维护

设计 本月,Eric Allen 解释了在使代码更易于维护的同时,避免和控制无理由的变化怎么会是保持代码健壮性的关键.他集中讨论了诸如函数样式代码编写之类的概念,以及标记字段.方法和类的方法来处理并防止可变性.Eric 还解释了本任务中单元测试和重构的角色,并提供了协助实现重构的两个工具.在相关论坛中与作者和其他读者分享您对本文的看法.(您也可以单击本文顶部或底部的"讨论",访问该论坛.)有效调试源自良好的编程.设计易于维护的程序是程序员面临的最困难挑战之一,其部分原因在于程序通常并不

诊断Java代码: 在规范钢丝上行走

要构建可靠的软件,程序规范很关键.没有良好定义的规范,很难诊断软件系统的异常行为.但是很多软件系统的程序规范定义得很差劲.而且更糟的,是许多软件系统根本就没有规范. 直观的看,程序规范是对程序行为的一种描述.它可以采取许多形式,但无论采取何种形式,都有一条主线贯穿所有实例:必须有某种类型的系统规范,因为您得依靠它来判断系统是否运转正常. 规范可以形式化也可以松散地定义,这取决于开发中系统的稳定性和危险程度,还与开发完毕后修改系统的容易程度有关. 我们将通过讨论规范为什么重要.为什么会经常被忽略以