• JRuby最近在讨论是否要支持Java 5。

    JRuby邮件列表的讨论
    http://www.nabble.com/Moving-to-Java-5--tf4131923.html

    InfoQ报道
    http://www.infoq.com/news/2007/07/jruby-java5-move
    http://www.infoq.com/cn/news/2007/07/jruby-java5-move

    XRuby起步就是从Java 5开始的,所以,不存在这个问题。在他们还在为此争论的时候,受到Charles Nutter最开始那封邮件的启发,我已经完成了Annotation标记Java代码和Ruby代码绑定的第一个版本。

    下面是一个例子:
    @RubyLevelClass(name="ClassFactory")
    public class ClassFactoryValue extends RubyValue {
        ...        
        @RubyLevelMethod(name="test", type=MethodType.NO_ARG)
        public RubyValue test() {
            return RubyConstant.QNIL;
        }
    }

    首先,用@RubyLevelClass标记出这个Java类对应着一个Ruby层次上的类,其名称为ClassFactory。然后,用@RubyLevelMethod标记出一个Java方法是对应着Ruby的方法,它的Ruby名称为test,而且它是无参数的。

    我们可以这样利用这段代码:
    RubyClass klass = RubyTypeFactory.getClass(ClassFactoryValue.class);

    通过RubyTypeFactory,我们可以生成ClassFactoryValue将Java层次和Ruby层次对应起来的代码,生成代码大致如下:
    public class ClassFactoryValue$ClassBuilder implements RubyClassBuilder {
        public RubyClass createRubyClass() {
            RubyClass rubyclass = RubyAPI.defineClass("ClassFactory", RubyRuntime.ObjectClass);
            MethodFactory methodfactory = MethodFactory.createMethodFactory(ClassFactoryValue.class);
            rubyclass.defineMethod("test", methodfactory.getMethod("test", MethodType.NO_ARG));

            return rubyclass;
        }
    }

    这里用之前介绍过的生成方法Wrapper的MethodFactory去辅助代码生成,简化了编写。

    XRuby本身为了生成bytecode已经做了大量的代码生成,这里只是把代码生成更多的用在了其他的部分。把这里的Annotation更广泛的用在XRuby中,会让代码看上去更干净。
  • 2007年,亚洲杯冠军,伊拉克足球队。

    谁都知道,现在的伊拉克是个什么样子。来自这个国家的球队,能够出现在亚洲杯决赛圈已经不易,更何况一步一步登上了亚洲之巅。在决赛场上,我们看到的内容已经远远超出足球的技战术范围。困境中的伊拉克爆发出惊人的战斗力,让对面的对手完全失去了自己的方向。战至最后阶段,伊拉克的队员几乎完全体力透支,但他们依然不断拼搏,将胜利拿下。

    伊拉克太需要胜利了,这个遍体疮痍的国家需要胜利,这种胜利会给这个民族注入他们目前最需要的信心。信心,对个人,对民族都至关重要,尤其当几乎一切都在一种最糟糕的状态下,这是一针强心剂。

    我不想讨论比赛,毕竟这只是一场亚洲的比赛,但我喜欢这样结果。在极大的压力下,人们往往会发挥超出自身实力的能力,会让观者得到极大的鼓舞,这就是竞技体育一个重要魅力。

    精神胜利的典范应该是意大利的足球。
    1982年,意大利在假球丑闻中成为了世界杯冠军。
    24年后,2006年世界杯,电话门丑闻,意大利队又一次坚强的笑到了最后。
    电话门丑闻使得AC米兰新赛季从一开始就不被人看好,但正是在这样的不利中,他们成为了2007年欧洲冠军联赛的冠军。

    我喜欢这样的足球,精神的胜利带给人们的享受远远大于竞技的内容,虽然那是一种迫不得已的无奈。

    恭喜,亚洲足球的新科状元,伊拉克足球队。

  • 周末,跨越了大半个北京城和几个老朋友聚到了一起,由于有一段时间没有见到,自然一个个都变成了话痨。一个朋友的精神状态对比于之前见到的他来说,明显好了许多,生活显然也丰富多彩了一些。聊到原因,他从之前一个很糟糕的情况逐渐摆脱了出来,心情好了,自然而然人的状态也随之好转了。当然,朋友们也看到了我类似的变化。加入到ThoughtWorks后,我整个人的状态变得明显不同了,更活泼了。按照一个朋友的说法,明显是被释放的结果。

    曾经和老妈聊天,我说找工作的标准是“钱多和心情好” 至少有一样。其实,虽然我也知道金钱的重要性,但我一直没有树立了一个良好的追逐金钱的观念,所以,我真正看重的是心情。工作最初的部门给我留下了一些很美好的回忆,其中一个重要的原因就是那里给了我一个良好的心情,周围的环境让我感到很舒服,所以,在那里我的表现也得到了大家的认可。虽然后来我离开了那里,但原因也与环境无关。反而,每次我回到沈阳,都会回到那个部门与一些老朋友叙旧。在我正式离职之前,我还曾经到那个部门与大家分享了一些Ruby的东西。

    之后工作的那个部门,虽然我从中也学到了不少的东西,但自己整体评价我那两年的表现,很糟糕。自我分析的结果是,我一直没有找一个让自己心情愉快的理由。虽然大家也经常在一起玩,但那个部门的整体氛围一直不是我很喜欢的,人和人之间表现得也不是那么友善。正所谓祸不单行,有一段时间,我觉得自己很“背”,把该倒的霉在那一段时间都倒了。所以,在这种氛围中工作了一段时间之后,我感觉很压抑。我知道自己肯定会离开,只是不知道什么时候,下一个落脚点会在哪里,直到我找到了ThoughtWorks。

    一个朋友看到我写的那篇《一月思想工作者》给出的评价是如鱼得水。经过长时间的压抑之后,我感觉自己一下子解脱了。我很快就融入了这样的环境中,以至于一些新来的同事误以为我已经在这里工作了很长的时间。ThoughtWorks给了我一个我喜欢的环境。我不会为了那些没有意义的东西,消磨自己锐气。

    在ThoughtWorks的招聘流程中,有一条原则,如果应聘者让你感觉不舒服,你就完全有理由拒绝这个应聘者。这是一条看似不合理的原则,但对于维护一个良好的企业文化却至关重要。因为招进来的人是要和我们一起工作的。如果这个人在应聘过程中让人不舒服,那么在日后的工作过程中,他可能也同样会表现得让不舒服,让人不舒服的结果就会是影响工作效率,精力被浪费在一些无谓的地方。事实上,正是有这样一条原则,所以,几乎与所有ThoughtWorker在一起都会让人感觉很舒服。不管这个人来自哪里,即便是刚刚认识,也会很快就会熟悉起来。

    你的工作环境给了你怎样的心情呢?

  • 去年Agile Day的时候,我还在沈阳,没有近距离感受ThoughtWorks带来的敏捷盛宴。今年的Agile Day,我已经成为了一名ThoughtWorker。我不仅仅有机会到了现场,更是成为了一个演讲者。演讲的题目自然是我现在的工作重点:Ruby on JVM。公司对Ruby的关注从这次Agile Day的日程安排中可见一斑,在技术/工具分会场的四场演讲中,就有两场与Ruby相关:第一场我现在的老板Chad讲企业级Ruby和我的Ruby on JVM。

    虽然讲的是自己熟悉的东西,但准备这次演讲的材料还是花了很大的力气。面对的观众不同,讲的内容就应该有所差别。从众多相关的内容选择出让观众有兴趣的内容,而且深浅适度,这是个问题。所以,每次有讲演的机会,我都对仔细考虑讲的内容。好在在ThoughtWorks总是可以找到人一起讨论,一旦确定了演讲的基调,就拥有了骨架,剩下的问题就是血肉丰满起来。在准备这次演讲的内容过程中,yawl和Ola Bini都给了我不少建议。

    这次Agile Day的活动,公司允许任何人在中国的ThoughtWorker参加。本来周六的活动,人在西安的ThoughtWorker周五晚上出发。为了更好的准备这次的演讲,我提前一天到北京。对于自己所讲的内容,因为经过了自己的思考,我觉得还好,我最主要的担心就是怕自己会紧张。在北京办公室准备的过程中,我才发现,原来大家都一样,每个演讲者都是怕自己会紧张,所以,为了能在大会时有个良好的表现,大家都在一遍遍回顾着自己的所讲的内容,偶尔还要拉几个观众实战一下。我就给人当了演习观众。当然,我也会拉着别人来当观众。第一次讲的时候,我能清楚的感觉到自己在开始的时候,声音有一些微微的颤抖,语言的表达上有些凌乱,好在这是练习。Mingle产品经理Adam看我的讲稿之后,第一反应就是问我Mingle是否可以运行在XRuby上,这也增强了我对讲稿的信心,不过,我的答案还是令人遗憾的“暂时不行“。

    Agile Day当天,ThoughtWorker们都会充当杂役,所以,早早就去现场干活。稍微得到一些清闲的时候,脑子里就一次次回顾着要讲的内容。确实这次大会人来了好多,要在这么多人面前讲东西,无论事先我做了多少准备,我还是会觉得紧张,尽管表面上还和同事们开着玩笑。其实,原本我希望在Agile Day多听几场演讲,但事实上,在别人演讲的时候,我都在休息室准备自己的演讲,根本没有心情去听。Chad结束演讲之后跟我说,我还在演讲中提到你了,我只能很抱歉的说,我没有听到。真正到自己站在台上开始演讲,我发现自己的声音没有了练习时的颤抖,这也给了自己不少信心。随着演讲的进行,我也就自己渐渐进入了状态,也就不太顾忌那些无关的东西了。至于表现得到底如何,我不知道,别人评价去吧!gigix之后就告诉我,我经常出现背向观众的情况。之后,精神一下子松懈下来,感觉好累,在外面的沙发上,躺了好长时间,所以,我后面一场的演讲也没怎么听。对我而言,当我是演讲者时,其实往往意味着失去一次很好的学习机会。

    虽然大家都愿意去听各种各样的演讲,但实际上,一个演讲真正能让人记住的只有非常有限的内容,所以,我所希望的只是通过这次演讲,让更多的人知道我们在Ruby on JVM上的努力是有价值的。如果能够吸引更多的人加入到这个过程中来,那就是太完美了。
  • 在《管窥Ruby——方法定义》中,我们曾经讨论过在Java中实现方法定义时,因为Java语言的限制,我们不得不为方法加上了一个Wrapper,让它可以满足接口定义的需要。事实上,XRuby一直就是这么做的,通常Wrapper放在com.xruby.runtime.builtin这个包中,而诸如Array、Hash、String之类的具体实现放在com.xruby.runtime.value这个包中。初涉XRuby的人,常常会被这两个包搞得晕头转向。到底方法的具体实现应该放在哪里,大多是根据感觉来定义的。

    在那篇blog中,我还讨论了JRuby的实现,不过,那里面的讨论并不是特别的完善。事实上,除了利用reflection,其中还有一种方式,通过代码生成动态产生这个Wrapper。我将这个实现借鉴到了XRuby中。通过采用这种生成Wrapper的方式,我们就可以在实际编写的代码中,忽略掉Wrapper部分的实现,而将原来令人混淆的builtin和value包统一起来。

    下面是Array的clear方法原来的实现:
    class Array_clear extends RubyNoArgMethod {
        protected RubyValue run(RubyValue receiver, RubyBlock block) {
            RubyArray value = (RubyArray) receiver;
            return value.clear();
        }
    }

    在这里,其实只要将receiver转型,然后调用它的方法就好。实际上,生成的代码只是做这样简单的工作就好,当然,根据具体的方法还会略有些差别。关于如何使用ASM进行代码生成,我在几篇blog中都进行了介绍,这里就不介绍生成代码的实现了。下面是在代码中如何使用这个方法。
    MethodFactory factory = MethodFactory.createMethodFactory(RubyArray.class);
    c.defineMethod("clear", factory.getMethod("clear", 0));

    在这个方法的实现过程中,还有一些比较有趣的点。首先,并不是每次都需要调用getMethod都要动态生成一个类,因为一个类一旦已经加载,就没有必要再次进行加载,即便强行加载,class loader也是会抱怨的。所以,在创建类之前,我们需要尝试加载一下这个,如果加载成功,便省去了再次生成的麻烦。

    再有,每次都去创建这个Wapper实际上也没有什么必要,一次生成之后,保存起来就可以了。如果我们把它放在class path中,那么我们尝试加载就会成功,所以,刚才提到的尝试加载还有这样一层含义。

    作为builtin实现,我们还是希望这些生成类是可以放在我们最终发布的jar文件中,所以,我们通常的做法,是在打包之前,先用XRuby做一次最简单的执行,让所有的Wrapper生成出来,这样,打包的时候就可以将它们都加入其中。

    具体的做法可以参考XRuby中MethodFactory和build.xml。