Java/j-djc06173/#author1">Eric E. Allen (Mailto:eallen@cs.rice.edu">eallen@cs.rice.edu)
Ph.D. candidate, Java编程语言小组,Rice大学
2003 年 8 月
在诊断Java代码 系列最后一部分,Eric Allen 讨论软件开发的当前动态并展望未来数年内的发展趋势。
尊敬的读者:我非常遗憾的通知您这将是诊断Java代码系列的最后一部分。我已经(最后)完成了我的博士学位工作,将前往行业实验室帮助开始新的编程语言调研项目。
在这最后一篇文章中,让我们来看看我们的水晶球。我们将讨论一些软件行业的流行动态,以及预计它们对软件开发的未来产生的影响。我们将重点讨论在过去两年半内,我们在这一系列文章中使用的有效软件开发。与往常一样,我们将特别关注有效错误预防和诊断在使我们实现在日益复杂的数据领域中自由翱翔扮演的关键角色。
当调查行业整体发展方向时有三种流行动态需要考虑。它们是:
总之,这些动态正在重新塑造软件和软件开发过程中涉及的软件工程的基本特性。从高处看,软件开销及其普遍性正在把我们引向更广泛和更普遍的抽象概念,如强大的虚拟机器,具有精心定义的语义和安全特性,从而使我们能够在更多的平台上更轻松地开发和维系软件。
同时, 计算性能的不断完善使我们能够构建这些抽象概念,不会蒙受无法接受的性能下降。 我非常愿意尝试一些我认为我们可以构建新抽象概念的方法,它们将有助于创建下一代软件产品。
基于组件的开发
在基于组件的开发中,软件使用模块进行开发,其外部引用从特定实施分解。然后这些模块可以动态进行链接,以构建一个完全成熟的应用。注意“外部引用”不仅仅包括引用的对象,还包括可以使用的类,甚至子类。(想一想Java编程中不同包互相引用的方法。现在考虑相互分解包。) 在这一专栏中,我们已经讨论了一种关于基于组件的Java编程理念 -- Jiazzi (见 sources">参考资料 ,2002年月日11月专栏分解包相关性)。
基于组件的编程承诺两种互补性优势,随着上述态势变得越来越突出,这两种优势将变得日益重要。首先,基于组件的系统可以实现更大范围的重新使用。例如,考虑到目前的无数程序,它们提供文本编辑支持(邮件客户机、文字处理程序、ide等等)。同样,考虑众多提供处理电子邮件支持的客户机。姑且不管提供这些业务的程序的数量,很少程序能够处理电子邮件以及作为专用电子邮件客户机。而且没有邮件程序能够实现与专用文本编辑器相同级别的文本控制。但为什么所有邮件客户机(IDE、文字处理程序等等)必须开发自己的文本编辑器呢?如果有一个各种第三方组件可以实施的标准“文本编辑器”api那该多好啊!邮件客户机等工具可以选择它们最喜欢的实施这一API的方法并把它加入。实际上,人们甚至可以想像,用户使用现成的组件(如他们最喜欢的编辑器、他们最喜欢的邮件客户机)来创建自己的环境,可以在应用运行时动态链接这些现成的组件。
基于组件的模式的另一种优势是更大范围测试的潜力。在Java语言中,类的外部引用,如I/O库类和类似类,都是硬连线引用,如未重新编译不能做任何更改。结果是,很难对单独依靠外部引用的程序部份进行测试。例如,实际上如果不允许一个程序从文件系统进行读和写,很难测试它是否正确使用了该文件系统。但在单元测试中读和写文件会减缓测试,增加更多的复杂性(如创建临时目录和在使用后清除文件)。理想状况是我们应分离程序和I/O库的外部引用以便测试。
有多种方式我们可以用来标准化一个组件模式。J2EE在对象级别为web业务提供这样一种模式。Eclipse为IDE组件提供一种模式。Jiazzi提供一种可以链接单独编译的软件“单元”以形成一个完整的应用的模式。每种公式在特殊的环境中使用;我们期望在接下来的数年内看到更多的公式。
断言和不变量 联合基于组件的编程必须将越来越多的重点放在断言和确保实际上满足计划预留用于组件的不变量的其它方法。类型系统自身并没有表现得能够捕获所有计划的不变量。例如,我们不应期望文本编辑API的方法类型可以捕获所有与“只关闭打开的文件”类似的不变量。我们可以依靠非正式文件来规定这类不变量,我们标准化和检查的不变量越多,效果就越好。
确保满足需要的不变量是组件封装的一个方面。通常,客户机编程人员将无法推论组件如何运行,而不是按公布的API中所述的方式。API中不包括的组件的所有行为不是客户机编程人员可以依靠的行为。如果非公布的行为导致运行时错误,编程人员将很难诊断问题并加以解决。
目前正在进行多项调研项目以显著改进我们可以规定用于组件的不变量的种类。其中一些项目,如Time Rover (见 参考资料 2002年7月专栏),使用模态逻辑和其它逻辑形式来表示运行时行为的深度属性。
表示不变量的另一种方法是泛型-作为其它类型参数化的类型来支持类型系统(本专栏中最近一系列文章的主题)。
添加更加强大的不变量的另一种方法是从属类型。 从属类型是运行时值参数化的类型 (与泛型比较,泛型是其它类型参数化的类型)。
从属类型的标准实例是数组大小参数化的数组。通过在该类型中包括数组大小,编译时间检测器可以象征性地分析数组的存取,确保所有存取都在数组范围内进行。从属类型另一种引人注目的使用方式是由 Boyapati、 Liskov和 Shrira开发的所有者(ownership)类型 (见参考资料 ,原始页面链接)。
所有者类型是一个所有者对象参数化的对象的类型。例如,考虑容器上的迭代器(iterator)。可以很自然的说迭代器由容器拥有,因此,容器有该迭代器特殊的存取特权。内部类提供一些相同的存取特权控制,但所有者类型提供更强大、灵活的控制机制。
重整工具中的持续改进 软件应用的规模越来越大,而程序人员越来越难以维持和改进代码或诊断程序错误。优秀开发人员的缺乏进一步加剧了这一难题。幸运的是,开发工具正在为我们提供对软件系统越来越强有力的控制。最强有力的两种控制形式是单元测试工具和重整浏览器。
单元测试工具使我们能够检查重整情况下继续保持的程序的关键不变量。重整浏览器提供多种直接且强有力地修改代码的方式,同时保留行为。我们开始看到“第二代”单元测试工具,它们利用静态类型和单元测试,从而实现代码范围的自动测试和测试的自动生成。重整浏览器向标准字库添加越来越多的重整。从长期来看,我们应寻找更卓越的工具,如“以模板为导向”的重整浏览器,它承认设计模板在程序中的使用(或潜在使用)并应用它们。
我们甚至可以期望开发工具最终利用单元测试来执行更多积极地重整。在Martin Fowler的杰作《重整:完善现有代码设计》中,重整被定义为保留程序看得见的行为。但是,我们通常不会关心一个程序看得见的行为的所有方面,实际上,我们通常只关心维持该行为的某些关键方面,而且这些关键方面正是假定要进行检测的一组单元测试!
因此,重整浏览器可以潜在地利用一组单元测试来确定行为的重要方面。其它方面应可以被重整浏览器积极地随意修改,以简化程序。另一方面,通过确定单元测试允许的重整的种类并向程序人员报告,这类重整浏览器的功能应可以用于检测测试范围。
交互式调试器
随着应用的日益复杂且更多地在远程平台上运行,程序错误的诊断带来了新的挑战。通常在部署平台上调试程序是不可行或不切实践的。最理想的情况是我们能够远程调试软件。
Java平台调试器架构(JPDA)提供用于这类工具,允许调试器在单元的JVM上运行;然后我们可以使用Rmi来进行远程调试。而且,除了远程调试之外,通过在启动调试器时为程序人员提供更多的存取点控制,以及调试过程中提供计算状态的可用视图,程序人员可以更有效地进行诊断。
即使使用现代化调试器,程序人员在多种环境中仍旧必须求助于printlns
以获得他们需要的信息。理想情况下我们应部署调试器,它可以完全取消printlns
的需求。实际上,在Java编程语言小组(JavaPLT)中,我们正在研究这类调试器。由于开放源代码将在2003年秋季发布,这类调试器将使用无缝集成的“交互式窗口”, 它支持代码的渐进式评价(见参考资料,2002年3月专栏)。交互式窗口使您能够通过任意表达式评估来启动调试流程。它还可以在断点使用,以与上下文中运行的流程交互,接入流程中该点看得见的范围并随意进行修改。JavaPLT 调试器将作为 DrJava IDE的一部分和作为单独的Eclipse插件推出。
轻型、可互操作的开发工具
随着开发工具变得越来越先进,一家厂商很难提供所有最好的工具。开发人员倾向于依靠不同厂商提供的工具自助餐。如果不同的工具能够很好地协作,这样做最好不过了,每个人都接受这样一个事实,它们将与其它工具很好地协作。
Eclipse等项目在这一哲学方面抢得先机,提供实现工具互操作的方式以利用相互之间的功能,以及提供任何工具单独提供的范畴之外的业务。随着时间的推移,我们期望这种模式,或其它与其类似的模式,以真正“超越”传统的全方位IDE。
元级别应用逻辑
根据我们最后的水晶球构想,我们考虑软件行业可能在长时间内从事的一个方向。应用中发生的许多最常见的程序错误都是简单的误配置的结果,一旦用户了解应用的基本详细信息就可以轻松对其进行纠正。问题是大多数用户没有时间来了解他们使用的所有应用的基本详细信息。
解决这一问题的一项长期解决方案是将元级别知识嵌入到应用中,这类应用对运行应用的环境以及假设要执行的程序进行编码。例如,字处理程序的元级别知识应包括解释用户在个人计算机上用于生成英文文件的程序的逻辑,其它用户可以阅读这类文件。在对这类知识进行了编码之后,当某些地方出错时应用可以推论出用户正在尝试做的工作(当然,应用还必须首先确定某些地方出错)。
这类元级别知识是向应用添加强韧性的潜在强大机制。它还极其危险,最令人不安的是在极力提倡沿着这一方向前进过程中经常忽略了它的存在。实际上,自身可以动态重新配置的应用的行为极其不可预测。用户可能发现很难在某些情况下说明他的程序将如何运行。而且,程序的开发人员还可能发现很难确保其可靠性。正如我们反复看到的一样,不能预测和了解程序行为导致的一种可以轻松预测到的结果是 -- 错误不断的软件。
为了弄清楚这一点,我真正考虑具有元级别知识的适应软件,这类知识与有可能显著提升软件应用性能的环境有关,但如果我们增加了这类功能,那么我们必须找到相应的方法,从而仍旧使我们能够有效说明我们的程序。
一个结合元级别知识形式和功能(虽然非常有限)且不会影响可预测行为的软件系统实例是TiVo个人数字记录器(或其它类似产品)。TiVo根据您的看电视习惯来自适应地确定您可能希望观看的节目,但这种自适应性是极其受限制的。TiVo将总是遵循用户的节目指令来记录,与任何其自适应行为响应无关。TiVo使用一种非常简单的元级别知识形式,但随着使用的元级别知识变得越来越复杂,我们应继续保持对自适应行为的控制。如果您将认可科幻领域某些稀奇的比较,那么我们将遵循Isaac Asimov创建的先例。Asimovian机器人是异常强大的机器,但它们必须绝对遵循不可侵犯的基本法律,从而能够在一定程度上预测它们的行为。
再会
在Asimovian机器人注释中我将结束这一讨论。非常感谢 developerWorks 小组在过去两年半的时间内所做的工作:编辑Jenni Aloi,为我提供编写这专栏的机会;文字编辑Christine Stackel,对细节一丝不苟;发展编辑 Kane Scarlett,进一步完善了这一专栏的内容。
致读者:非常希望您能够在这些文章中挖掘出一些最新的价值。对于我来说,撰写这些文章已经成为了无价的学习体验。非常感谢您阅读这类文章,祝您在防止和诊断程序错误中好运。
BIOS-->
关于作者
Eric Allen 在康奈尔大学获得计算机科学及数学学士学位,并且是 Rice 大学 Java 编程语言小组的博士研究生。在回 Rice 完成学位前,Eric 是 Cycorp, Inc. 的首席 Java 软件开发人员。他还主持了 JavaWorld 的“Java 初学者”论坛。他的研究包括源代码和字节码级别上 Java 语言的语义模型和静态分析工具的开发。Eric 领导开发了 Rice 的 NextGen 编程语言的实验编译器,NextGen 编程语言是带附加语言特性的 Java 语言扩展,他也是 DrJava(一种为初学者设计的开放源码 Java IDE)的项目经理。可通过 eallen@cs.rice.edu与Eric联系。