Sexy Ruby

来源:互联网 发布:大数据分析 职业规划 编辑:程序博客网 时间:2024/05/18 03:09

接触Ruby已经有了一段时间了,在这段时间里一直处于疯狂和执着的状态。为什么会是这样,我自己也不清楚。就像音乐,当你喜欢之后,会一直在听,不停地跟朋友提起它。

记得知道Ruby这个名词时,还是从RoR了解到的。当时只知道RoR是一个快速开发的Web框架,随后开始看《Web开发敏捷之道》。看着看着逐渐迷上Ruby了,随后就开始了一段与Ruby亲密接触的日子。

有些人觉得Ruby非常难学。不过确实,对于一个从类C语言里跳过来的人多少会对“def……end”语句感到不爽,他们更喜欢“{……}”!但是Ruby就是这样设计的,接受它也无妨,况且比起Visual Basic的“End Function”和“End Sub”来说还是简单不少了。

其实Ruby颠覆了许多传统的观念,Ruby的迭代器是Ruby最得意也是最颠覆的概念。在Ruby中我们基本上不用写For循环,一个times方法附带一个Block就可以了:

Javafor循环:

for(int i = 0; i < 10; i++) {

    System.out.println(i);

}

Ruby等价代码:

Range.new(1, 10).each{|i| puts i}

很有趣,不是吗?虽然上面的代码对于Java程序员来说有点摸不清其原委,但是大致你可以从上面的单词中得到一些提示。each后面在大括号里的代码就是Block,想理解Block并不复杂。如果你有Win32编程经验,那么你可以把它看成是CallBack函数;如果你有C#编程经验,那么你可以把它看成是代理;如果你写Java代码,那么把它看成是匿名类就可以了(最好是看成处理Swing控件事件的匿名类)。

为什么会有Block?这很简单:你可以得到最大化的灵活性,同时又不失规范性。有些时候部分代码是规则,你需要重复;有些时候代码是灵活的,我们需要不同的代码来达到我们的需求。当然这两类代码不交织在一起就阿弥陀佛了,可是现实中并不是如此。拿Java举个例子吧:

操作一个文件大家都会遇到,但是我们会被文件操作的API束缚住。打开文件、操作、关闭文件,外加还得处理异常信息。为了能稳妥地处理文件我们可能会写下这样的Java代码:

FileInputStream fis = null;

try {

    fis = new FileInputStream(“filename”);

    //processing file content code...

    fis.close();

} catch(IOException e) {

    e.printStackTrace();

} finally {

    if(fis != null) {

       try { fis.close();}

       catch(IOException ex) {/*Do nothing here*/}

    }

}

这种处理文件的方法非常稳定,但是给我们带来了比较复杂的一面,我们为了打开一个文件需要处理许多问题,其实对我们最重要的还是“//processing file content code...”这部分。如果我们仅仅是为了打印文件中的内容,那么上面的代码确实太麻烦了。解决问题的方法有很多,使用Template设计模式,或者使用匿名接口实现回掉机制。但是这些都是需要自己动手去做的事情,况且在一个方法中编写一个匿名类来换取一些灵活性在视觉上也会有点污染:

public void processFile(){

    MyFileStreamTemplate mfst = new MyFileStreamTemplate();

    Mfst.processFile(“filename”, new Callback(){

       Public void process(FileInputStream fis) {

           //process file content code...

       }

    });

}

这样的代码显得技巧横飞,写起来也颇有一些艺术创作之感。但是如此高雅的东西大众欣赏起来就有些miss understand了。

Ruby很好地解决了这个问题,它用Block替代了Callback接口,而且Ruby的类库在设计的同时也考虑到了上面的问题,看看Ruby的处理文件方法吧:

File.open(“filename”) do |file|

    //process file content code...

end

放心吧,当我们的文件操作出现问题时不用担心清理的问题,open方法已经替我们做了异常处理的工作了,我们需要做的就是把文件打开,然后用Block处理它,然后结束。怎么样?体会到Ruby的“快”了吧!

有人肯定会抱怨:这一点都不OO!没错,这确实不符合OOP的忠实拥护者内心的理想,但是有时候OO并不是最佳的解决方法,No Silver Bullet.

很多人在使用OOP的思想在编写软件,继承、抽象类、接口等等概念已经深入人心,但Mixin还是一个新的名词等待被更多的人接受。在很多情况下,我们会想到使用继承来让某些类拥有一些特殊的功能。当我们需要一个类拥有更多功能的时候,我们可能会想到多重继承或者实现更多的接口。但是Java不允许多重继承,那么我们有加深继承树的方法。

Ruby走了另外一条路:Mixin。那么什么是Mixin呢?我们来看看,现在有一个数据类A,它里面存了一个数组形式的数据。如果我们想让它把数据以XML形式呈现,那么我们就写一个to_xml的方法;如果我们想让它把数据以HTML表格的形式呈现,那么我们就写一个to_html的方法,and so on

那么如果还有一个数据类B,也要这些功能,而且逻辑是一样的,那么我们就把A的一些方法抽象出一个基类比如“DataBase”类,然后里面有to_xmlto_html等方法。

如果有一个类C,它跟AB的并不属于同一个思路,那么我们把C也从DataBase继承在语意上就比较麻烦,况且它还有可能继承了别的类。这时你可以用Mixin了,把to_xmlto_html两个方法放在一个Ruby模块里,然后让AB还有C Mixin这个模块,一切都OK了。

Mixin像什么呢?可能比较像拼接玩具,给他插上什么构件就有什么功能。而且Mixin还有另外一个好处,它可以让你分离关注点。你是喜欢一个700行代码的类还是7100行代码的模块然后把他们Mixin到一个类中来呢?

好了,就先讲这么多了,Ruby的亮点还有许多,装一个Ruby玩一玩,逐渐就会感受到Ruby给程序员的灵活性。正因为Ruby给程序员极大的灵活性,导致了一些程序员对Ruby的恐惧心里,他们感觉不到这种灵活性给他们带来的成就感,抑或他们还没找到Ruby的门路。其实Ruby很美、很灵巧、很强大,但是它需要驾驭者有一个心里准备:你要经受得住Ruby对传统的反抗。

 

原创粉丝点击