利用Ruby简化你的Java测试
本文是Productive Java with Ruby系列文章的第一篇,我将从单元测试这个话题开始,让Java的开发人员能够在实际工作中利用Ruby提高工作效率。
作者 Werner Schuster译者 高昂 发布于 2007年7月25日 上午1时41分
数周以前,Evan Phoenix加盟EngineYard,在那里他每天的工作中有一半时间花在Rubinius项目上。我们对Evan进行了一次采访,了解项目项目的进展和虚拟机的内部情况,并且(在采访的第二部分)探讨了最新的一些特性的实现方式。
其它的Ruby实现,比如说JRuby、XRuby、Gardens Point Ruby.NET、IronRuby,要么针对已有的虚拟机,要么和Ruby 1.x一样使用C语言编写,而Rubinius另辟蹊径,它从Smalltalk虚拟机处获得灵感,尤其是在Squeak Smalltalk之中。Squeak是用它自己Smalltalk的一个子集写成,这个子集名叫Slang,它基本上是使用了Smalltalk语法的C语言代码,并加入了一定的限制。Rubinius的目标之一,就是使用这种方式贯穿项目始终,它使用的语言名叫Garnet(以前被称为“Cuby”),目前仍处于开发阶段。Evan就目前进展解释说:
这仍然是我计划在近期要做的事情,而不是今后的。之前,我们遇到了许多需要处理的问题,而且我们还没有时间回来着手Garnet(Cuby的新名字)上的工作。目前我们尚未找到什么特别的问题,但我相信我们会发现的。
第一眼看过去Garnet语言和Ruby长得没什么区别,但是里面一些东西代表的语义进行了一些修改。
举例来说,在Garnet语言中,“d = c.to_ref”这样的代码看似调用了c对象的to_ref方法,但实际上Garnet会把这段代码翻译成“d = &c”这样的C代码。我们可以把它看作一个非常先进的C预处理器,试图尽可能将自己和对应的C语言构造映射起来。我们的想法就是写出看起来像 Ruby的代码,而行为则和C语言类似。
目前,虚拟机的基础部分是使用C语言编写的,也采取源自Smalltalk的方式。Evan就此解释了基础实现(primitives)的本意:
他们是可以在Ruby中调用的小块C语言代码,用来实现Ruby无法完成的功能。一个很好的例子是给一个对象分配 (内存)。在系统后端,与垃圾回收机制交互,为特定对象的分配准备出足够的空间。这样的操作在Ruby之中无法实现,这种操作方式只存在于系统的最底层, 也就是所谓的基础实现。
Rubinius的基础实现与Smalltalk的基础实现机制很相近。如果方法指定了原生(primitive)的操作号,当方法被执行时,则会调用原 生(primitive)操作而不是常规的Ruby代码。如果primitive操作执行失败(primitive自身报告执行已经失败),那么Ruby 代码就会作为后备的行为被执行。Ruby代码可以使用如抛出包含操作失败原因的异常的方式,将参数转换并再次进行尝试,或者做一些其他的操作。
为了展现它实际运行的方式,这里附一段rubinius的primitive操作代码作为例子:
def fixnum_size(_ = fixnum)
<<-CODE
stack_push(I2N(sizeof(int)));
CODE
end
接着Evan给我们解释了一遍代码的运行过程:
primitives和指令使用一系列有趣的格式来保持其操作的简单性。所有的操作都是Ruby方法,而程序体是 包含C代码的字符串。在编译的时候,这些文件被执行,然后某些代码会调用每一个方法,收集C的代码并且在其它C代码的#include部分声明。这样做的 主要原因是基础实现和指令在C语言的声明中可以包装为一个大的switch表达式,如果使用手工的方式来完成无疑将会是非常痛苦的。
而且,它 提供给我们一些程序预处理的能力。例如,在这里(代码示例),你看见我们在定义参数的原生类型(primitive)fixnum_size的时候使用了 一些小的技巧。首先,代码的关键是在调用的方法的代码执行前会自动注册C语言代码段“POP(self, FIXNUM_P)”。调用并且输出C语言代码的方法将会正确的声明和写入这些代码。用这样的形式,我们可以方便基础实现(primitives)的编 写。
但是我声明,目前并非所有基础实现(primitives)都使用了这样的形式。很快,我们将会进行审查,将所有的实现都统一使用这种形式。
可以看出,随着可用的Garnet越来越多之后,Ruby和C语言之间的界限会变得模糊,原有的界限将在今后发生改变。对于更深一层的软件栈来说,标准的类库将使用Ruby来实现。
目前,虚拟机的核心(实际上就是操作码)和基础实现(primitives)都是使用C语言编写的。基础实现(primitives)是我想在Garnet中实现的第一个特性。两者的垃圾回收机制也都同样是使用C语言编写(虽然他们所占的的代码量很少)。Rubinius虚拟机在过去一段时间内发展很快。为了保持发展的势头并吸引更多的开发者,在更多的开发者开始贡献代码还有更多的测试人员开始加入到Rubinius项目中之后,他们需要得到更多项目相关的信息。
除了这些,所有的一切都是用Ruby实现的。所有解释器都可以解析命令行参数字符串(就像rubinius -d -v这样开启调试和警告信息)。所有代码的运行时环境可以轻松的操作(修改),因为它们也都是Ruby的。
我们尽力去保持整个过程的透明度。目前,项目的IRC讨论组是最主要的交流方式,并且我们设法将IRC的记录整合到站点http://rubini.us之上。同时我们鼓励用户使用我们在http://rubini.us上的论坛来反馈问题。论坛拥有RSS的feed读取方式,并且大多数的开发者可以通过订阅RSS来加入讨论(尽管我不得不承认,有些功能还有待真正实现)。
关于如何使得项目更加透明,通过各种方式提出的建议,我都非常欢迎。我们可以一直考虑满足用户提出的规格。一旦我们拥有一个完全规范的套件,其余的功能将很容易的添加在其中。
感兴趣的读者可以继续关注这段采访的下一个章节,下个章节探讨了Rubinius调试器、垃圾回收、ObjectSpace和线程方面的一些最新特性的实现方式。
查看英文原文:Evan Phoenix on Rubinius - VM Internals Interview
本文是Productive Java with Ruby系列文章的第一篇,我将从单元测试这个话题开始,让Java的开发人员能够在实际工作中利用Ruby提高工作效率。
InfoQ中文站有幸与阿里软件的首席架构师赵进在一起探讨了SaaS的相关话题,包括SOA和ASP与SaaS的异同、云计算、SaaS的前景、它的关键技术、技术瓶颈等等。
在这篇文章中,Adrien Louis和Marc Dutoo在一个典型的ESB场景中讨论了编配和路由的区别和优缺点。他们讨论了几种连接服务的方法,从使用如自定义路由这样的低级别方法,到使用如工作流和编配这样面向业务的高级别方式,并总结说不存在“一边倒”的解决方案。
本文是根据7月26日InfoQ中文站在杭州举行的QClub活动(第三期)后半程小组讨论总结而成。主要内容包括如何在SOA系统中实现服务编排,如何保证分布式系统中的一致性和可用性,以及如何在实施SOA的过程中控制接口的粒度等。
人们很容易想当然的以为虚拟化技术仅仅应用于服务器。而在现实中,虚拟化这一苏醒的概念正被运用于各个层面,其中包括网络,存储以及应用基础架构。在这篇导论中,InfoQ将深入每个方面,详尽向您描述虚拟化技术的运用以及其优点与不足。
在这篇案例研究中,InfoQ对Adobe AIR和Amazon的简单存储服务(Simple Storage Service ,S3)在NASDAQ市场回放程序(NASDAQ Market Replay)中的应用进行了详细的分析。
没有回复
回复