论坛首页 编程语言技术论坛

转:Martin上海演讲实录

浏览 3125 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-02-02  
Ruby是一个非常好的开发工具

我今天想跟大家讨论的主题是ruby. 我去年来过上海,但是那时候我生病了。今天是我来上海的第一天,也是这次我中国之行的过程中身体好转的第一天。所以,我想这是我在上海的第一次演讲。谢谢大家的到来。

这次演讲的主题是ruby, 在这之前我还从来没有做过这方面的演讲。我使用ruby已经有一段时间了,但是还不算是ruby的专家,因为ruby自身也在不断地快速发展中。我在软件方面有很强的Unix背景,因为在我大学毕业后的第一份工作,曾经是工作站的Unix的管理员。作为一个Unix的管理员,我对Unix的Shell script有比较深的研究,以及相关的一些领域。

在那之后,我继续尝试脚本的相关工作。我一直对脚本语言比较感兴趣。在90年代末,我尝试使用Perl. 但是有一点是我不喜欢的,因为我发现无论我多么努力,我都不能理解我几个月之前写的Perl代码。我想那是Perl的一个不好的现象。之后大概是在 2000年左右,我开始使用Python,相比之下,我更喜欢Python,它是一个非常好的语言。我记得有一次去参加Java one会议,我的程序就是用Python写的。在那之后的几年里,我一直选者Python作为我编程的脚本语言。之后我对Tomas(注:< < pragmatic programmers >>一书的作者)的 pragmatic programmers发生了兴趣, 他写了pragmatic programming这本书,是一本非常好的书,我希望大家都读过这本书。他们告诉我一种新的语言ruby. 他们对ruby非常有信心。我在那个时候认为,python已经是一个不错的选择了,所以我会继续使用它,不需要一门新的语言。但是他们送给我一本书,是他们的新书,关于ruby. 当我开始读这本书的时候,我发现我被这本书吸引了。我发现ruby具有一些python所没有的特性,并且它具有所有python所有我喜欢的优点。所以我就开始使用ruby了。从那以后,我开始使用ruby做越来越多的事情。

在我开始制作我自己的网站的时候,我一直遵循一个原则,这就是,内容或者说商业逻辑和表现分离。也就是软件架构设计逻辑和用户接口(UI)的分离。你也可以在我的代码中看到这个原则,如果你看我早期的代码,一定不会把内容放在stylesheet中. 我的网站绝对的遵循这个原则。我所有的内容都放在了xml文件中。使用转换(transformation)机制把这些内容转换为html. 一开始我使用xsl来做这种转换,因为在xml的使用中,这是很自然的一件事情。那大概是在2000年左右,我的网站就正式开通了。但是后来我发现用 xsl这种语言来表现内容是非常不好的一种方式。这样我就开始尝试使用ruby来做这件事情。我做的第一个程序是我的blog, 第一个版本是在从波士顿到印度的飞机上完成的。这是一个比较长的旅程,但是我印象很深,我在整个飞机飞行的过程中一直都在工作。到达班加德罗,我已经很疲劳了,但是我很清楚的记得,我可以这么快速的工作,并且取得了非常不错的成果。代码尽管是在很高海拔的地方完成的,却有非常好的可读性。尽管用xsl也可以具有这种可读性,但是ruby已经被证明是非常好用的了。这样我就把我的网站转而使用ruby进行了开发。所以就我个人而言,很长时间以来,我认为 ruby是一个非常好的开发工具。

现场演示Ruby编程

[img]http://images.csdn.net/20060606/20060606035747.gif
[/img]
我们现场有多少人使用过ruby进行开发?很惊讶,只是个别人。所以很多人还没有见过ruby,这就是我带笔记本来的原因了。我将演示一下我们究竟能用ruby做什么。这样的话,我们将会对这个语言有一个认识。我现在把话筒放在一边,放好我的笔记本电脑。

Ruby是一种立即执行的脚本语言。接下来在编辑器环境中新建一个源代码文件。

这个控制台的窗口不会被经常用到,不用担心,我可以键入这个文件的名称,然后运行它。我同样可以在编辑器里做这件事情,把它打印在其他的文件里面。我们现在要做一个小程序。这里是一些数据图表,把它想象成是每个国家的图表,包括:失败图表(fails figures),执行图表(operating figures)等等。这些可能是业务人员每天要关注的事情。现在我们把第一项想象成地区,第二项想象成预期的销售额,第三项,想象成实际情况。那么现在这些业务人员提出了一个要求,让我打印出这些数据,并且显示出预期值与真实值之间差别的百分比。所以我们需要花一些时间完成这个工作。

我们要做的第一项工作是读出这个文件,并且把它显示出来。我在一开始会比较慢的展示应该怎样做。(输入代码)这会是一个比较简单的版本。它现在能够把文件的内容显示出来了。我下面来解释一个这里的语法。这里有一个File类,有个方法是open。在这里并没有在参数外面加上括号,不过如果需要的话可以在这里加上,程序依然能工作。括号在ruby编程中是可以选择的,这看起来不是一个很重要的语法点,但是很多时候,这是非常重要的,比如在接下来的编码中,或者是其他的一些脚本。之后这里有一个非常简单的while循环。我们结果一个局部变量line. 同过getline得到这个变量。记住,只有在需要的时候才去声明这个变量,我们不预先声明。之后我们输出这一行,然后关闭文件。

但是,我已经说了,这不是用ruby实现这个功能的方式。通常,你会这样做。这里出了一个错误。Ruby有一个非常好的帮助系统。我们在这里察看一下错误究竟出在哪里。我确实记不起来了。不过可以看一看以前写过的。这样的编程是非常危险的,因为你需要知道你在做什么,同时要把你正在做的东西表达出来。这是非常难的,我很少这样做。所以这里,我正在做的这个事情,就这个语言来说是非常老练的(sophisticated)。这里对于文件的每一行进行了操作。这一部分是文件的closure. 这里是说,在do和end之间执行这一段非常短的代码。在每次执行命令的时候,都执行一次。把一段代码作为参数传入一个function,这在编程语言中是非常常见的。在smalltalk中是如此,那么在java中的也是,匿名方法(anonymous method)。C#中的代理从根本上来说也是这个道理。closure是ruby的一个特点非常强大的特点。如果你经常使用ruby的话,你会发现,这种closure有非常非常多的应用。在这里使用这种方式的好处是,它可以对你传入文件名的每一个文件的每一行执行这个操作,在执行完之后会关闭文件。如果不用这种方法,你必须要每次执行完操作就关闭文件,这就形成了一系列的事务,在做完一件事情的时候要去做下一件。使用这种匿名方法的方式就可以避免这个问题。

接下来要做的事情是,把这一行输出放入一个对象里。在这里建立一个类,名字是performance. 现在给这个类建立我们需要的figure, 名字是attr_assessor, 然后定义name amount 和actual, 这里实际上定义了我们需要显示的三个值。这里我就可以对我的循环里的代码进行改变了。
P = performance.new
p.name = line.split(‘,’)[0] 这里行可以用逗号分隔,然后我们得到其中的第一个。之后我们输出p,这里我们看到输出的是p这个对象本身,而不是我们希望的值。在java中,我们可以定义一个字符串类型。但是在ruby里面,我们定义一个def to_s函数, 使它返回name的值。现在,我们在输出结果里面,就看到我们真正想要的name了。所以,我们可以看到,建立一个我们需要的类是非常容易的。接下来,我们可以把这个类改为真正的面向对象风格。我们需要结果返回一个数组。Read方法的是返回result这个数组。(进行了一系列代码的动作,调试,忘记把 p加入到result数组中了)这样就得到了正确的结果。我们有一些值需要放入我们的这个类里。通过这样做,我们就可以实现了。这里line.split (‘,’)会返回一个数组。这一句代码执行了复合的操作。每一个变量,对应到数组中的不同的值。这是脚本语言的一个特点。所以,在返回字符串的函数里加上 plan,加上actual. 再次查看结果,我们就可以看到我们想得到的所有值了。

现在来看我们的代码是很有条理的。那么我们可以加入计算的功能了。定义一个variance方法。返回(actual -plan)/plan * 100,这样我们就得到了百分比。(写了一系列代码)这时候我可以确定代码是不能运行的,因为现在这些值都还是字符类型(写了一系列代码)。所有的脚本语言都有一个共同的问题:没有异常机制的。但是可以通过其他方式处理错误。现在来看一看结果,我得到了极限值。这里是因为我忘了加入浮点。这样的话结果就是正确的了。不过,我们得到的输出是很难看的。我们即将使用Ruby的格式化字符串的机制。(写了一些代码使输出变为小数点后一位。)接下来输出国家名,这样我们就可以看到完整的显示了。在格式化字符串输出的这段代码里面,就像C语言里面一样,可以对输出进行格式化。

现在程序还是有一些问题,不过我们要继续看下一部分了。在perfs加入排序。这里通过variance进行排序。(写了一些代码)现在显示的结果是按照variance进行排序的了。我们需要知道的最重要的是这一行代码。这是ruby中closure的使用。我把数组放在raw_perfs里,它按照特殊的域进行了排序,然后对他进行了另一个操作。在集合上进行了操作的叠加。在ruby里,对collection的这种操作,使ruby成为一个非常简洁的语言。无论是对 smalltalk还是对list,对对象这样的操作都是相似的。但是,当你还没有使用这种语言的时候,它看起来并不普遍。但是你一旦开始利用这种特性,它将会变得非常强大,因为你可以方便的使用你的meta进行操作。


细数Ruby语言优缺点

解释以上这些究竟在做什么显得有些罗嗦了。但是我希望传递的是,使用 ruby这个语言时候的体会。尽管你不能自己亲自尝试,但是你可以通过屏幕看到这一系列的过程。现在我想展示另外一个例子。我希望你们可以所看到的内容中,得到一些体会。如果你之前还没有尝试过任何一种脚本语言,那么我鼓励你去学习ruby. 我认为ruby是非常值得学习的。因为它是很容易学习和使用的,只需要花几分钟去学习。脚本语言的另一个特点是,你可以写一些代码,然后直接去看它的运行结果。Ruby是一个非常优秀的脚本语言。但是,我想ruby的意义不仅在于它是一个好的脚本语言。接下来的几分钟,我将讨论这个问题。

首先,我希望通过ruby的特性来讨论这个话题。这一点你可能已经从刚在的例子里面有所体会了。Ruby又很简洁的语法,这样你不需要写很多的代码,就能够获得很强大的功能。从刚才的例子里面就可以看到,在写参数的时候,你不需要写括号,当然,你也可以根本没有参数。这个特点可以使你快速的编写代码,但是更重要的是,你可以快速的阅读代码。我们可以对比java, c系列的语言,当你试图去阅读代码的时候,你的视线总是会被分散,并不容易弄明白代码究竟在做什么。松散的类型检查可以帮助我们更快,更好的理解代码。严格的类型检查可以导致更差的可读性。Ruby 在这之间做了很好的一个平衡。代码的可读性无论是对ruby而言,还是对使用ruby的开发人员来说,都有非常重要的价值。我认为用ruby写的代码是可读性很好的。这并不意味着ruby是一个很小的语言,就像smalltalk那样。Ruby是一门很复杂的语言。它具有很多复杂的语法特性,比如在同一行代码中实现多个任务这些小的语法点。如果你使用过其他的脚本语言的的话,(会发现)perl和python的特性都被带到了ruby中。这些给ruby的学习增加了难度。这又是一种新的平衡。在简单的语言里面表达事情是复杂的比如smalltalk, 然而,在ruby里,是很方便的,特别是在控制collection方面。在ruby里,List的语法是很方便的。我并没有展示hashtable在 ruby中的使用,但是它们的用法一样是简单的。

有一点很受到关注,不像java,c#这些主流的静态类型的语言,你不需要在ruby中定义变量类型。它是具有严格的类型的。记得我们在刚才的实验里面举的例子,字符串类型进行减运算,是会被提示错误的。但是你只有在运行的时候才会被告知有错误存在,而不是在编译的时候。所以ruby有严格的类型。但是它的类型是动态的。所以你只有在运行时才能发现错误。这就造成了下面这一个结果,很多人担心在编写ruby的代码的时候是很难发现类型错误的,这不像我们通常在java和c#里面期待的那样。但是,我发现在大多数使用ruby的开发人中并不存在这样的问题,他们通过测试解决这个问题,尤其是单元测试。我本人是测试的拥护者,我会非常多的使用到测试,不是在当前这个小的演示程序里面,而是在以前的稍微大一些的项目里。如果你使用单元测试,你发现那些类型错误的速度将会像在编译中发现错误一样快捷。我非常喜欢这种特性,尤其是在一开始使用 smalltalk建立大型系统的时候。只有在很少的情况下,测试是不能发现类型错误的。但是在这样的语言里面有一个缺点,在阅读代码的时候,你不容易理解程序究竟完成了什么,因为在操控这个变量的时候你不能知道他究竟是哪一种类型的。这意味着,ruby还不能像smalltalk那样有一些强大的调试工具,这样可以在调试环境里面步进的运行程序,看到变量的类型。总体来说,我喜欢动态语言带来的这种灵活性。对象可以被替代,在很多地方都可以作为各种类型被使用。但是在另一方面,它又提高了代码的可读性。当你试图去阅读代码的时候,它是比较容易被理解。这就需要看个人的喜好了,有的人喜欢使用静态的语言,有的人喜欢使用动态的语言。所以,你需要挑选一种更喜欢的语言。很多人认为种类是很重要的,我认为这并不是决定性的。

我认为,ruby的另外一个特性是它具有很强的面向对象的特性。Perl并不是一门面向对象的语言,尽管后来加入了一些面向对象的机制。Python也并不是完全面向对象的。但是ruby在一开始就是面向对象的。在这里我可以展示另外一段代码。(写了一段代码)。所以,在ruby里即使是Nil也有一个类,nothing也是一个对象。这就像smalltalk。一个对象和一个基本的构造类型(primitive build type) 的区别在于:在ruby中,对象就是全部。尽管你看我之前的一些代码是,你并没有看到初始化的代码。Ruby 就是这样被建立起来的。这里有另一个很不错的例子。(写了一段代码)。我们看到,在这里我们得到了一些很大的整数。你能在java里面用这么简单的语句实现么?不能,因为你需要考虑,当你的值增大到一定程度的时候,你应该如何处理。需要考虑类似于增大位数这样的事情。有趣的是ruby在后台这样做了,但是我们看不到。现在来输出它的类型,看看将会发生什么。(写代码)这样做可以使你的输出居中。这里我们看到,这些数字的类型一开始是”fixnum”,是比较小的整数类。当他增长到足够大的时候,它需要像在java里一样,变成比较大的类型bignum. 所以,这里能够显示具体的实现类。这就是动态语言的优势了,用smalltalk甚至可以做得更好,它可以根据你的需要,把数字类型转换分数,浮点类型等等。所以,ruby具有非常好的面向对象的背景。在这样的脚本环境中,可以使你的程序具有更好的结构。你可以有一个比较好的速度,好的机制,更好的结构,使你写出更好的结构性程序。这是不断结合的结果。

然而,不是ruby里面所有的东西都是好的,它有它的缺点。比较重要的一个问题是,它还没有一个非常好的开发工具,特别是在你熟练的使用它的编辑器之后,它不能够像java那样的开发环境,比如eclipse. 和我最喜欢的Intelligent J,提供智能的提示,能够引导程序员编写代码。这些在ruby的社区中还不存在。我当前推荐使用的是emacs。这对于人们来说绝对是一个缺点。这些取决于人们究竟投入多少资源。由此而引发的另外一个问题是,我们不能像在java和c#里面那样进行重构。在动态类型的语言里,进行重构是比较困难的。这也不是绝对的,第一个开发出重构功能的是smalltalk. 但是也并不完善。

Ruby的另外一个问题是,ruby在block上的时间并不快。在脚本语言的标准中中,它是一个门较慢的语言。但是这并不是一个很严重的问题。在我们开发的程序中,ruby被用来调用数据库。跟数据库的连接和硬件的一些功能相比,ruby还是具有比较好的性能的。但是在其他的一些方面ruby还不是最好的。人们把ruby的API内置到c的library中,是很常见的一种情况,像Perl和Python也是这样做的。

Ruby的另外一个不足之处在于处理Unicode. Ruby 处理Unicode是很糟糕的。我刚在演示的程序实际上是使用ACSII类型的字符串。你不能像很多人那样使用Unicode进行代码。它并不像采用起来那么容易。这个问题将会在下一个版本中得到解决,可是,至少目前看来,ruby不能像java和python那样,那么好的支持Unicode。

工具和DSL缔造Ruby魅力
最有趣的和最值得关注的地方在于它的库(library)以及框架(framework),一个web 开发的框架。在我们参与的一些项目里面,ruby on rails是一个可以带来高生产率的web开发框架。在开发企业应用时一个重要的问题是,数据库的代码和其他的代码被糅合在了一起。你必须控制这些代码,使数据库的请求是有效的。当数据库由另外公司不同的部门进行管理时候,这成了非常重要的问题。如果你对数据库有一定的控制,那么你可以你的环境就会变得混乱。Rails是专门针对某些种类的应用程序而设计的,而不是为了解决所有的问题。例如对于互联网应用,它有着特别的优势。

Ruby中的另一个吸引人的库,这也是我个人认为非常有用的是,它能够管理每一个build版本。在Unix环境中有一个非常著名的,就是可以构建C语言的程序。 RAILS这个可以帮助我们描述一个build.我将要在一个小窗口里面展示这个特点, 这会非常有趣。这里是网站上的构建脚本。这里我定义个了任务和依赖。Default 任务依赖于all. all任务依赖于这些所有的任务。这里是任务的逻辑代码,它会去执行这一段代码。我们往下看,这里有help的函数,这里还有clean任务。熟悉 ruby代码的人会熟悉这些都是在做什么。这里的task就是方法的定义。在default这里,你可以看到一个箭头指向all,你可以在一个 hashtable里面找到对应。这里用到了closure(注:就是前面讲到的匿名方法)。所以特殊的build 语言,是有着特殊的用处的。Build文件有自己特别的属性。你希望列出所有task的分支结构,和依赖关系。任何人都想获取任务间的依赖关系,所以 tag标记那一个任务是必须被执行的。我在ruby的代码里面定义这些任务。在内存中构建这些task, 然后必要任务会被执行。构建我的网站意味着构造700个文件。但是我可以知道哪一个文件是被修改过的,哪一个需要重新构建,然后做最小化的构建,得到我想要的结果。我们发现这个是非常有意思的,它可以记录很少的历史信息。这一类的比较早的语言是make语言,通常在Unix系统下使用。Make 是一种特殊的文件格式,用来描述怎样构建代码,它是一种特殊的domain语言,可以用来构建应用程序。它有它自己的格式和语法,描述怎么样构建C语言程序。Make存在一个问题,这就是它学习起来并不容易。你也很难去理解那些自动生成的makefile。但是很多程序都有自动生成make文件的能力,因为如果是你自己去写的话,是不容易掌握的。Java一开始是没有构建工具的。所以James Duncan Davidson写了ant用于java的构建。Ant的作者不想让构建涉及到语法的问题,他们使用xml作为构建的脚本。我并不是在抱怨这个问题,在那个时候xml是不错的选择。使用xml语法会有两个问题。因为语法是十分严格的,你需要花很多精力用于关注语法,所以读懂它执行的操作就变得困难了。另外的一个问题是,当系统越来越大的时候,build文件会包含很多逻辑,就给建立ant文件造成了困难。所以当系统变得很大,建立一个ant的文件来构建系统就会十分困难了。我们需要找到一种方式,从xml中释放出来,用来构建这些类。

Ruby 就是这样一个强大的语言,在有一定语法限制的情况下,去验证ruby的语法。Ruby并没有引入太多新的语法。这看起来还不错,因为你需要一门新的语言,来实现这个功能。但是你还是有一个局限,就是你不能在ruby以外使用它。但是另一个好处在于,当你需要做非常复杂的事情的时候,你可以使用ruby. 所以,你有更强大的能力来完成这件事情。这个外部的语言让你可以使用它的语法,使你逐渐变得更有能力应对。因为在越来越复杂的时候,它可以帮助你编译。这种能力是很容易获得的。它的语法是很直接的,你可以容易的学习。把这样的语言作为宿主(host)语言是一个很传统的想法了。但是这是很有用处的。

有的时候,使ruby能够吸引使用者并不是一件容易的事情。我成为ruby的爱好者已经有几年了。我致力于把它推广用于我们的工作中。我告诉别人我喜欢 ruby,并且鼓励别人去使用它。但是在一个产品中使用或者不用并不是非常重要的。我并不推荐所有的工程都使用。但是在最近半年的许多项目里面,我们都使用了ruby. 我们发现,在一些工程里面ruby可能并不适合,但是在另一些工程里面使用ruby是非常适合的。这个核心在于,那些成功的案例证明,那样项目,才是 ruby真正适合的。尽管Rails提供了一个大的框架,但是如果不用ruby的话,几乎不可能成功。这也是项目成功的原因之一。

我的同事正在做的一个项目是需要大量操作数据库的。把数据从数据库中取出来,在内存中进行计算,再把数据放回数据库是没有必要的。你希望用spl进行这些操作。而使用sql是有一定限制的。它很强大,但是不容易使用。Sql的一个最主要的问题在于,它完全基于domain. 它可以对表格式的数据进行很好的操作,但是没有把表抽象出来的能力。所以如果你想要对表进行操作,这个是非常好的。但是如果你想进行其他操作,就非常麻烦了。典型的例子是:具有层级结构的数据库是比较复杂的,用sql来操作它也变得复杂和困难。在这个项目里面,使用了ruby语言,允许输入domain specific language的ruby, 可以生成sql代码对数据库进行操作。这样的特殊的语言是非常好用的。领域的专家可以脱离出来,去阅读和理解这些代码,不用去考虑语法和究竟如何产生这些。可以把精力放在其他的地方。ruby这样的domain specific language的特点使它非常具有吸引力。

Ruby社区令人激动

现在来看几张照片来总结这个演讲。Ruby是一个有趣的系统。我不能说它适合用于任何地方,但是它的确适合用在很多地方。DSL是它的核心。一些特定类型的网站,特别是那些需要用到数据库的,还有使用RAILS框架的。几乎所有的administrating work 和 scripting work都适合使用ruby. 你可以开始使用ruby,因为他是一个非常强大的工具。Ruby是我见过的最好的脚本语言,你也会有同样的体会。在构建方面,Rake(注:ruby的构建工具)是非常好的构建工具。大约在六个月以前,我把我的网站全部换成使用它进行构建和维护这些构建的文件。我想你一定不会后悔的,因为构建和维护这些构建文件都是非常容易的。

在我完成这次演讲之前,我还有最后一件事情。当我谈论软件开发的时候,我一直在强调,无论你使用什么样的工具,什么样的实践,比如结对编程,测试驱动,关于软件开发项目成功与否的最重要的因素是工作在项目中的人以及这些人如何一起工作。在敏捷软件宣言中,首要的价值观就是个体与互交比过程和工具更重要,更有价值。Ruby值得关注的原因不在于它的特性也不是它的框架,也不是它带来的在RAILS中的生产率的提高,而是 ruby社区成员的工作。Dave Thomas (注:<< pragmatic programmers >>一书的作者)多次提到了这一点,这是正式它吸引我的地方。我在最近的二三年内一直很感兴趣。Ruby社区吸引着越来越多高手的加入,从而使它本身不断进步。另一个优点在于,Ruby的开源作品都可以通过网络直接安装,如果你想要使用,那么可以非常容易的通过RubyGem安装——这是一个package management system. (注:就好像debain的Unix package management system) 。Ruby的社群正在飞速成长,因为不断有优秀的成员加入到这个团队,在这个环境中工作,这使得这个团队非常值得关注。这也是我一直关注ruby的最主要的原因,因为很多值得关注的人都在这个社区里面工作。

这就是我关于ruby的第一次演讲。我希望它不是一个语无伦次的演说。


来源CSDN http://manager.csdn.net/n/20060616/91726.html
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics