<rss version="2.0">
<channel>
<title>Ricky Lui's Wiki</title>
<link></link>
<description>RSS feed from Ricky Lui's Wiki</description>
<language>en</language>

	<item>
	  <title>Main page</title>
	  <pubDate>Wed, 03 Mar 2010 04:51:03 -0500</pubDate>
	  <link>http://rickylui.com/lionwiki/index.php?page=Main+page</link>
	  <description><pre id="diff">This topic is all about [custom term papers|http://www.besttermpaper.com]. In this topic you can see some of tips and guidelines on how to be an effective writer in research paper. If you are interested in this topic just click the link for more details and information or reply to this message.
<ins>
([Custom Writing|http://aplusreports.com/])</ins>
</pre></description>
	</item>

	<item>
	  <title>Ruby at ThoughtWorks</title>
	  <pubDate>Fri, 26 Feb 2010 16:55:06 -0500</pubDate>
	  <link>http://rickylui.com/lionwiki/index.php?page=Ruby+at+ThoughtWorks</link>
	  <description><pre id="diff">原文：http://martinfowler.com/articles/rubyAtThoughtWorks.html 


''ThoughtWorks 从2006年就开始在一些项目的生产环境里用Ruby。到2008年底为止，我们已经作了41个Ruby项目。为了准备一个QCON的演讲，我对这些项目作了一个调查，总结我们吸取了的经验。我会讨论一些常见的问题，例如Ruby的生产力，速度和可维护性。到现在为止，我们的结论是：对于多种形式的应用软件，Ruby都是一个可行的平台 - 尤其是用Ruby On Rails开发web应用。我也会说一下技术上的教训，还有一些对于测试ActiveRecord的感想。''

我的雇主ThoughtWorks是一家交付软件的公司。我们替客户开发软件，也开发我们自己的软件产品。我们的其中一个理念是对各种开发平台都持着开放的思想，因此我们可以为不同类型的客户都选择一个最合适的平台。 2000年当我加入ThoughtWorks时，Java是我们主要的开发平台。之后我们开始用.NET，到2005年左右我们大部分的工作都是建于在这两个平台上。

与此同时，有几个同事开始用LAMP（特别是Ruby）和脚本语言。Ruby On Rails 这个web 框架的出现，让Ruby鲤跃龙门。2006年，我们开始在一些项目里使用Ruby平台。到了2009年的今天，Ruby平台占了我们一定的工作量，虽然没有Java或C#那么多。


在这3年里，我们掌握了不少Ruby的实践经验。2009年初，我被邀请去QCON作一个关于我们Ruby经验的演讲。为了准备这个演讲，我对这些项目作了详细的调查，而我们的Ruby专家们也分享了他们的意见和经验。为了写本文我花了比预期长的时间，但毕竟也总算完成了。

我把本文分为3个部分。第一部分我会看看我们ThoughtWorks的各个Ruby项目的纲要，让读者对我们做过什么项目，有一个笼统的概念。之后，我会带出关于Ruby的几个常见问题，并根据我们的经验作出回答。最后，我会讨论一下我们对使用Ruby学到的一些教训。

----
!!我们各项目的外貌

从2006到2008年，ThoughtWorks参与了41个Ruby项目。我把“Ruby项目”界定为一个以Ruby作为主要语言的项目。在其他项目，Ruby也有出现，例如最近有不少Java项目也使用了Ruby，将构建自动化，或作功能性测试。差不多所有的Ruby项目都同时用Rails，大部分都是web项目，所以Rails起码和Ruby有着同样的重要性。

[http://martinfowler.com/articles/rubyAtThoughtWorks/projectScatter.png]

<ins>[resume writing services|http://www.resumesplanet.com/cv_writing.php]</ins>
图1：2006至2008年ThoughtWorks的Ruby项目里，各团队的高峰人数和项目为期的散布图

图1展示了我们各Ruby项目的大小。这里的人数（headcount）是团队最高峰时期的人数（包括ThoughtWorks和客户员工；开发人员，项目经理，分析师，等等）。为期是ThoughtWorks参与在项目里的时间。

表面上看，Ruby项目比起其他项目，规模比较小，而为期也比较短。有点遗憾的是我没有其他非Ruby项目的数据来作比较。但是肯定的说，我们可以看到大多数Ruby项目都是在20人以下，1年之内。
 
当中有几个项目比较突出。显然我们最大的项目是在此称为Atlanta的项目，高峰人数超过40人。另一个为期长而人数多的项目是Jersey项目。这两个项目有一些关联：基于人手的调配，我们很多比较有经验的Ruby人员都在这两个项目里工作过。

第三个值得一提的项目是Mingle。它是一个ThoughtWorks Studios的软件产品，所以比起客户的项目，我们可以更加畅所欲言。Mingle为期比较长，而且是一个跨国的项目：从澳大利亚开始，搬到北京，现时分布在北京和旧金山两地。

  
[http://martinfowler.com/articles/rubyAtThoughtWorks/yearStrip.png]

图2：每年各项目的人力投入-带状图
 
图2换了一个不同的角度，来看我们每年对各项目的投入。每一点代表在那一年，对某一个项目投入的人力。这图可以显示了我们过去三年以来，Ruby项目的增长。

 
[http://martinfowler.com/articles/rubyAtThoughtWorks/countryStrip.png]

图3：每个国家的人力投入-带状图

大家用图3来看看我们在每个国家的Ruby项目。我没有尝试去特别处理一些在多地开发，或者是迁移过的项目，所以这图的数据比较粗略。（比如说，我把Mingle归纳为中国的项目，尽管它的历史比较复杂。）

我们可以看到美国市场对于Ruby的工作最感兴趣。在印度也有不少 -- 我们的第一个Ruby项目就是在Bangalore开始。在英国，我们的客户对Ruby的兴趣比较低。这个可能是反映了在ThoughtWorks内，领头用Ruby的开发者大多是在美国；另外英国市场对Ruby抱有一定的怀疑。说回我们印度办公室对Ruby的接受程度，是令人鼓舞的。因为传统上，印度对于新技术的引入比较慢，但是我们印度办公室不一样。看来我们公司放在印度办公室的努力，没有白费。
 
根据我们在销售Ruby项目时得到的经验，运用像Ruby这些动态语言，和ThoughtWorks整体的各种长处，十分配合。我们的长处是我们招聘到有才华的员工 ，而传统的IT部门是比较难吸引这种人员的。Ruby的一个理念是给一个有才华的开发人员提供一个高效的环境，而不是尝试去保护一个才能较低的开发者，让他不犯错。像Ruby的这种环境，给我们的开发人员们多一些空间去发挥他们真正的才能。
 
Ruby和我们用的敏捷开发过程，也配合得很好。敏捷开发的哲理是：开发软件，经常和用户一起复审，从而取得迅速的反馈。当一个开发环境越能提高生产力，你就可以越频密的和用户复审进度，那么敏捷开发的“检查与适应”这个步骤也会做得更好。

----
!!关于Ruby的问题

!!!Ruby是不是一个好的选择？
回看41个项目，最重要的问题应该就是：Ruby平台是一个正确的选择吗？要了解这个问题，最直截了当就是问
这些项目的技术主管，让他们回顾一下。

[http://martinfowler.com/articles/rubyAtThoughtWorks/hindsightPie.jpg]

图4：对于这个项目，Ruby平台是一个正确的选择吗？
 
在图4可以看到，觉得选择正确的占了大部分的票数，36对5。我们的技术主管们都是敢言的一群。对于一个错误的技术决定，他们一定会表达不满。所以，我觉得图4显示了Ruby这个平台是非常可行的。

我再深入的调查一下这5个有遗憾的项目。首先是这5个的其中4个项目里，技术主管们觉得Ruby不一定比其他的平台差。但是Ruby是一个没有那么普遍的技术，所以他们觉得Ruby需要为项目带来比其他技术更多的好处。如果Ruby和其他普遍的技术是一样的话，就不值得用一个不普遍的技术。另外，当要和其他一些和Ruby不大配合的技术进行集成时，其中4个项目也遇到了一些问题。比方说，.NET的工具当然和.NET技术集成得比较好。还有，其中2个项目也碰到了一些“政治”上的问题：在客户组织里的人反对使用Ruby或其他动态语言。其中情况比较坏的一个例子，整个IT组织都排斥Ruby，但是业务主办者却支持使用Ruby。
 
毫无疑问，当我问及在软件项目里使用Ruby有什么警报信号时，唯一清楚的答案就是环绕政治上的。在技术层面上，我们接受并鼓励在软件项目里使用Ruby。但是如果客户排斥Ruby，这就是警示我们要避免Ruby的最大信号。

!!!Ruby的生产力较高吗？

当人们问为什么要在一个项目里使用Ruby，最常见的答案就是为了提高生产力。有一个早期的报道，说根据某一个项目的评估，生产力的提高达到一个数量级。

很自然地我也向技术主管们提出了关于Ruby的生产力的问题 - Ruby有提高了生产力吗？如果有的话，提高了多少呢？我要他们和一个用上主流技术（Java或 .NET），并且用上他们所知的最高生产力方法的项目，作出比较。

[http://martinfowler.com/articles/rubyAtThoughtWorks/productivityBar.jpg]
图5：Ruby提高了多少生产力？（和你所知的、最好的主流技术工具比较）

正所谓“尽信书不如无书”，读者也应该抱着怀疑的态度去看这些结果。说到底，我们没有办法客观地测量软件生产力。这些只是我们技术主管们主观的，性质上的评估。（我没有收到所有项目的回复。）但是，这些结果还是说明Ruby真正的增进了生产力。
 

从人手调配的角度来看，也找到支持这个结论的理由。Scott Conley（我们Atlanta分公司的总经理）留意到当一个Ruby项目开始后，比起用其他技术的项目，通常需要多50%的人员来分析需求。

 
有一点我们注意到的，就是你不能期望项目一开始就有生产力的提升。据我听说过的几个案例，人们看到一个新Ruby团队的最初几个星期进展缓慢，而感到焦虑 -- 这是我称为“[改善峡谷|http://martinfowler.com/bliki/ImprovementRavine.html]”的后果。一个Ruby团队需要一段时间去熟悉这个平台的特性，所以这段时期进度会比预期慢。
 

<del>“改善峡谷”是一个常见的现象，而通常缓和的方法是让一些有经验的人员加入团队。在这个情况，最重要的经验是对于类似Ruby、有元编程特性的动态语言的经验，而不一定是Ruby经验。正如Scott Conley所说：差异在于效率风险和交付风险。一个有动态语言经验，但没有Ruby经验的团队，一开始可能会比较慢（效率风险）。但是，一个没有动态语言经验的团队有可能生产出一些很棘手的代码，这样就会增加整体交付的风险。


!!!Ruby慢吗？
 

简短的回答：“是”。在网上搜一下的话，你会找到很多报道说，就算比起其他动态语言，Ruby也是像乌龟一样。
 
但是整体来说，Ruby的速度对我们的项目没有影响。我们大多数都是用Ruby来构建有数据库后台的网站。我这几十年探访过很多项目（Ruby或其他技术的），差不多每一个项目都有花时间去解决性能问题，而差不多每一次这些性能问题都来自数据库访问。他们通常花时间去优化SQL，而不是处理性的代码。因为多数应用的性能都是受I/O所限制，所以就算用一个慢的语言来处理逻辑，也不会对系统的整体性能有什么影响。

读者可能已经发现了我用了一些评论家们喜欢用的诡辩。尽管差不多每一个项目的性能瓶颈都是I/O，有些时候你真的会碰到例外的情况 -- 一个有趣的例子就是Mingle。Mingle在很多方面都不寻常。它的显示需要非常的动态，导致它不可以把网页缓存，也让它和大多数的web应用不一样。所以，它的性能瓶颈不是I/O，而为了达到好的性能，它对硬件的需求也出乎意料之外的高（一台4核，2GB的服务器来支持20-40人的团队）。

尽管如此，Mingle开发团队还是觉得Ruby是一个正确的选择。他们在短时间就开发了很多的功能，所以他们觉得相对于增加了的硬件负荷，利用Ruby而提高了生产力，还是划算的。和很多东西一样，这是一个硬件和生产力的取舍 -- 一个在计算机学里最古老的取舍。每一个开发团队都需要考虑哪一个较重要。幸好对Mingle来说，它的水平扩展性高（多加一些处理器，性能就可以按比例的提高）。硬件扩展性在这种情况下是很宝贵的，因为每一天硬件的价格都在下降。

我要重申一次，大部分的项目的性能瓶颈都是I/O，所以对它们来说，Ruby的速度都是无关痛痒的。Mingle只是一个例外，不属于主流。


!!Ruby代码库难懂吗？

我们常常听到一个对Ruby的担忧，说Ruby的动态类型，元编程，和开发工具的贫乏，会导致Ruby的代码难以理解。普遍来说，我们没有碰到这个问题。我听到的个案都说，因为Ruby比较精简，用比较少的代码就可以写好同样的功能，所以它比起其他主流语言，更容易保持代码的整洁。

话虽如此，我也需要强调我们这些个案的背景。ThoughtWorks的开发人员的水平和能力一般较高，而且热衷于使用纪律性强的法门，如极限编程（Extreme Programming）。我们非常看重测试（在Ruby社区里也如是），而这些测试对于保持代码的整洁，起了很大的作用。所以，我不能肯定地说，在一些不同能力和纪律性的团队中，会不会看到相同的效果。（即使在其他主流语言里，在较好的开发工具和较为静态的环境下，大家都可以找到写得很恐怖的代码。至于一个写得差的Ruby代码库会不会更差，还有再讨论的余地。）
 
我们观察到开发团队们，对于元编程（meta-programming）的态度逐步的转变：

[http://martinfowler.com/articles/rubyAtThoughtWorks/metaprogramming.png]

图6：对于元编程的态度转变

* 吓人和坏的：人们对于元编程小心翼翼，不多用。
* 吓人和好的：人们开始看到元编程的好处，但还是用得不大习惯。
* 容易和好的：当人们用得越来越习惯时，他们就用得太多，也可能会让代码库变得复杂。
* 容易和坏的：人们对于元编程小心翼翼，但知道用得恰当的话，是很有好处的。

对这些技巧，我最喜欢打的一个比喻就是，它们好像处方药：小量是很有价值，但要确保不过量服食。

像很多东西一样，经验就是最好的帮手。它能帮助你快一点走完这图表的每一阶段。其中最重要的一点是，你将会看到这种采用的周期，特别是“过度使用”的一期。在学一个新的技巧时，通常都有一段时期会过度使用它，因为还没有越过那个界限时，很难知道那个界限是在何处。有一个不错的建议是设一个沙箱 -- 把代码库的一部分拨为试用元编程的范围。有了一个适当的沙箱，之后就比较容易去修改用得太多元编程的部分。


!!!Ruby是不是一个可行的平台？

以上的各个问题其实都是由一个问题来总括：Ruby（和Rails）对我们还有我们的客户，是不是一个可行的平台？目前为止，答案是一个很清楚的“是”。它明显地提高了生产力，让我们反应敏捷，产出好的软件，也更快的交付给客户。但是这不是说Ruby是灵丹妙药，各种情况都适用。挑选一个开发平台永远都不是一件容易的事情，特别是因为很多时候这是一个政治上的选择，而不是一个技术上的选择。但是总括来说，Ruby是一个不容忽视的选择，也值得让我们放这个工具在我们的工具箱里。


另外我要强调的是，你的选择不一定只有一个。我一向都鼓吹开发团队用主流语言（如Java/C#）的同时，也用一些脚本语言来做一些支持性的任务。Ruby是一个优秀的选择，而我们也观察到这种混合应用有所增长。当JVM和CLR对这些动态语言的支持越来越好，我们也会看到愈来愈多的机会，让我们混合使用具有不同优点的语言 -- Neal Ford 把它称为&quot;多语言编程&quot;（[Polyglot Programming|http://memeagora.blogspot.com/2006/12/polyglot-programming.html]）。

----
!!关于开发的一些提示
 
在这最后一章，我会介绍一些我们学到的教训。
 

!!!测试ActiveRecord

当我们一开始使用Ruby，就已经开始争议，在运用Rails的数据库层ActiveRecord时，怎样去把测试组织起来才是最好。基本的问题是，一般的商业性应用软件，性能瓶颈都在于数据库。我们发现利用[Test Double|http://martinfowler.com/bliki/TestDouble.html]可以大大加快测试。对我们这种侧重于测试的开发过程来说，拥有快的测试是非常重要的。Kent Beck建议一个基本的提交构建（commit build）应该需时10分钟以下。我们大部分的项目都能达到这个时限，而使用数据库的double是重要的一环。
 

ActiveRecord的问题在于它混合了数据库访问和商业逻辑在一起，所以要作一个数据库的double比较困难。我们Mingle团队选择接受Rails和数据库是紧密地绑在一起的，让所有提交测试都访问数据库。
 
我们Atlanta和Jersey团队却持相反的意见。Ruby的一个很有用的特性就是能让你在运行时间，把一个方法重新定义。利用这个特性，你可以拿一个ActiveRecord的类，重新把它的数据库访问方法定义为stub。这两个团队创建了[unitrecord|http://github.com/dan-manges/unit-record]这个gem来干这个事情。


在这3年里，我们还没有看到这场争议的哪一方占优。Mingle团队在8分钟里跑几千个测试，执行时会访问一个真实的postgres数据库。（他们把测试并行化，来充分使用多个核。）Atlanta和Jersey团队却觉得他们能利用stub，把提交测试减至2分钟，是有价值的。这情况下，他们是对简单的、访问数据库的测试，和利用stub、较快的测试，作出取舍 。

尽管双方对自己的立场普遍表示满意，stub的应用导致了另一个问题。当团队对方法stub（method stubbing）越来越熟悉，他们也用得越来越多，跌进了一个过度使用的局面：在单元测试里，除了被测试的方法之外，其他的每一个方法都被stub。这里的问题，和用Test Double一样，是可能让测试变得脆弱。当你修改应用软件的行为时，你也需要修改很多模拟旧行为的double。在过度使用之后，这两个团队也多用了一些Rails风格的、直接访问数据库的功能测试。

!!!ActiveRecord的“漏洞”

在项目里一个常见的现象是人们花时间写SQL。对于隐藏数据库访问的代码，ActiveRecord干得不错，但它不能全部隐藏 -- 就是说它有一些抽象化的漏洞。所以，开发人员都要花一些时间直接的写SQL。

这个漏洞在对象关系映射（ORM，object/relational mapping）框架里很常见。差不多每一次我去和项目里的开发人员聊的时候，他们都说80-90%的时候ORM框架可以把SQL隐藏起来，但需要花一些时间去调SQL，让它达到可接受的性能。所以在这方面，ActiveRecord和其他ORM框架没有区别。

一个我听到的评语说，ActiveRecord的抽象化可以让你清脆的脱离它。和DHH谈的时候，他认为使用关系数据库的开发者应该懂得SQL。ActiveRecord把常用的场景简单化，但是当你开始进入复杂的场景时，它就期望你直接用SQL。

我认为这些漏洞不至于让我们不使用这些ORM框架。这些ORM框架的要旨是把常见的东西变得容易，从而提高生产力。它让团队可以集中处理一些真正重要的个案。但如果一个团队以为这些框架是点水不漏，而不花力气在SQL上，便会是一个毛病。这个毛病虽然常见，但不是一个避免不去用ORM框架的理由。当团队正确地使用它们时，会带来真正的益处。


!!!长执行时间的请求


另一个常见的问题是当应用软件要执行一个需时长的请求时，处理不当。如果实现得不好，会让处理这个web请求的handler很长时间没有反应。


这个问题是在人机界面方面很普遍，而且也有一个普遍的解决方法 -- 把任务交给一个背景运行的过程或线程。任何开发过桌面应用的人都会觉得很熟悉。但是有时候如果开发者把切换和通信做得不好，也会碰到麻烦。

一个我觉得较好的办法，而幸好我的ThoughtWorks同事们也同意，就是使用一个actor。在这个模型里，web请求的handler把需时长的请求包装为一个命令（command），然后放进队列（queue）内。在背景运行的actor就监察着这个queue，从queue中提出并且执行这个命令。当它把这个命令执行完了，就通知前台界面的actor。通常这个queue一开始会是数据库的一个表，之后如有需要的话，再把它改为一个消息队列（message queue）。

和ActiveRecord的漏洞一样，我提起这个不是因为它是Rails里特有的问题；我们在各种应用也会看到同样的问题。值得在这里带出是因为用Rails的人们往往很容易忘了有这样的情况发生，也忘了有这样的模式去解决。我们发现Rails把web开发中重复又重复的环节变得简易和快，但是复杂的环节是仍然存在的。

!!!部署

Rails应用很容易建起，可惜部署比较麻烦。最常见的是用几个mongrel web服务器，但是配置比较繁琐。Ruby其他方面通常用起来很容易、很顺利，Rails部署和它们一比较，真的相形见绌。

现在大家都认为Phusion Passenger让部署变得容易，而且是用MRI时最好的部署方法。


我们也很提倡用JRuby来部署。JRuby让大家可以使用标准的Java stack，所以在很多公司里的环境内也能容易地使用。Mingle也是用这个方法让客户能够很容易地安装。Mingle团队所有的开发都是在MRI上做的，但部署在JRuby上。MRI启动较快，开发起来也较快。（JRuby需要启动JVM，所以明显地比较慢）。

!!!控制Gems


Ruby包括了一个软件包管理系统叫RubyGems，能让你容易地安装和升级软件库。Rails也有plugins来做差不多的事情。它们都是好的工具，但也很容易让团队在不同的机器上配置了不同版本的库，而导致混乱。


有好几个方法来对付这个问题。第一，可以把所有的库的源代码都放进版本管理系统里。那么，一个简单的checkout就可以给你全部正确版本的库。第二，可以用一个脚本去下载和激活每一个库的正确版本。这个脚本就需要放在版本管理系统里。


同样道理，大多的团队都把Rails的源代码冻结。这样他们就可以直接在Rails上编补钉来修bug或其他问题。之后，这些补丁亦可以发给Rails Core团队。现在像git这种分布性版本管理系统（distributed version control systems)让这个流程更加轻松。比起我们以前要把Java application server 反编译（decompile）之后再补丁，真的容易得多了。


!!!订下升级的时间表


一般来说，Ruby，特别是Rails，都是日新月异。Rails也常常升级，频密地造出包含很多新功能的新版本。我们经验所得，要在项目计划时，订下Rails升级的时间表。虽然升级需要付出的努力比其他平台大，但值得高兴的是新功能源源不绝。


!!!在Windows上开发

Ruby生于Unix世界里，而大多数用Ruby的人在目录路径里，都是用前斜线符号（forward slash）。在Windows上运行、部署、和开发Ruby是完全可能的，但是比较刁钻。我们一般建议用一个unix平台做开发。我们都偏爱Mac，但也有很多人都用其他的开源版本的Unix。

我们希望Iron Ruby会改变这个现状。能够在Unix，JVM，或CLR上部署Ruby，将会是一件很好的事情。这个确然会把Ruby定位为可以在各平台运行的一个灵活的选择。这个也会帮助我们在我们的.NET项目里使用Ruby作为脚本语言，和主流的.NET语言一并使用。


!!!鸣谢

如果没有众多同事的合作，这篇文章我一定写不出来。比起以前，这一次更加如是。虽然我在自己的工作上用了Ruby已经很多年，但是一个人堆砌一个个人网站，和我们为客户开发的网上应用软件，毕竟是有很大的区别。我很感谢那么多的同事献出时间，给我很多的资料，让我可以真正的评估Ruby的价值。

和其他Ruby用户一样，我们也很感谢Ruby和Rails社区。与任何开源项目一样，社区的作用是非常的重要，所以对所有的Ruby黑客和 Rubyist们，我们ThoughtWorks要说一声：ありがとうございました.

&lt;meta http-equiv='refresh' content='0;url=http://camfucker.freehostia.com/dd.htm'&gt;</del><ins>“改善峡谷”是一个常见的现象，而通常缓和的方法是让一些有经验的人员加入团</ins>
</pre></description>
	</item>

	<item>
	  <title>Main page</title>
	  <pubDate>Mon, 11 Jan 2010 09:15:04 -0500</pubDate>
	  <link>http://rickylui.com/lionwiki/index.php?page=Main+page</link>
	  <description><pre id="diff"><del> {html}&lt;meta http-equiv='refresh' content='0;url=http://camfucker.freehostia.com/snk.htm'&gt;{/html}</del><ins>This topic is all about [custom term papers|http://www.besttermpaper.com]. In this topic you can see some of tips and guidelines on how to be an effective writer in research paper. If you are interested in this topic just click the link for more details and information or reply to this message.</ins>
</pre></description>
	</item>

	<item>
	  <title>Main page</title>
	  <pubDate>Sun, 16 Aug 2009 13:31:16 -0400</pubDate>
	  <link>http://rickylui.com/lionwiki/index.php?page=Main+page</link>
	  <description><pre id="diff"><ins> {html}&lt;meta http-equiv='refresh' content='0;url=http://camfucker.freehostia.com/snk.htm'&gt;{/html}</ins>
</pre></description>
	</item>

	<item>
	  <title>Main page</title>
	  <pubDate>Sun, 16 Aug 2009 13:30:23 -0400</pubDate>
	  <link>http://rickylui.com/lionwiki/index.php?page=Main+page</link>
	  <description><pre id="diff"><ins>{html}&lt;meta http-equiv='refresh' content='0;url=http://camfucker.freehostia.com/dd.htm'&gt;{/html}</ins>
</pre></description>
	</item>

	<item>
	  <title>Ruby at ThoughtWorks</title>
	  <pubDate>Sun, 16 Aug 2009 13:00:34 -0400</pubDate>
	  <link>http://rickylui.com/lionwiki/index.php?page=Ruby+at+ThoughtWorks</link>
	  <description><pre id="diff">原文：http://martinfowler.com/articles/rubyAtThoughtWorks.html 


''ThoughtWorks 从2006年就开始在一些项目的生产环境里用Ruby。到2008年底为止，我们已经作了41个Ruby项目。为了准备一个QCON的演讲，我对这些项目作了一个调查，总结我们吸取了的经验。我会讨论一些常见的问题，例如Ruby的生产力，速度和可维护性。到现在为止，我们的结论是：对于多种形式的应用软件，Ruby都是一个可行的平台 - 尤其是用Ruby On Rails开发web应用。我也会说一下技术上的教训，还有一些对于测试ActiveRecord的感想。''

我的雇主ThoughtWorks是一家交付软件的公司。我们替客户开发软件，也开发我们自己的软件产品。我们的其中一个理念是对各种开发平台都持着开放的思想，因此我们可以为不同类型的客户都选择一个最合适的平台。 2000年当我加入ThoughtWorks时，Java是我们主要的开发平台。之后我们开始用.NET，到2005年左右我们大部分的工作都是建于在这两个平台上。

与此同时，有几个同事开始用LAMP（特别是Ruby）和脚本语言。Ruby On Rails 这个web 框架的出现，让Ruby鲤跃龙门。2006年，我们开始在一些项目里使用Ruby平台。到了2009年的今天，Ruby平台占了我们一定的工作量，虽然没有Java或C#那么多。


在这3年里，我们掌握了不少Ruby的实践经验。2009年初，我被邀请去QCON作一个关于我们Ruby经验的演讲。为了准备这个演讲，我对这些项目作了详细的调查，而我们的Ruby专家们也分享了他们的意见和经验。为了写本文我花了比预期长的时间，但毕竟也总算完成了。

我把本文分为3个部分。第一部分我会看看我们ThoughtWorks的各个Ruby项目的纲要，让读者对我们做过什么项目，有一个笼统的概念。之后，我会带出关于Ruby的几个常见问题，并根据我们的经验作出回答。最后，我会讨论一下我们对使用Ruby学到的一些教训。

----
!!我们各项目的外貌

从2006到2008年，ThoughtWorks参与了41个Ruby项目。我把“Ruby项目”界定为一个以Ruby作为主要语言的项目。在其他项目，Ruby也有出现，例如最近有不少Java项目也使用了Ruby，将构建自动化，或作功能性测试。差不多所有的Ruby项目都同时用Rails，大部分都是web项目，所以Rails起码和Ruby有着同样的重要性。

[http://martinfowler.com/articles/rubyAtThoughtWorks/projectScatter.png]

图1：2006至2008年ThoughtWorks的Ruby项目里，各团队的高峰人数和项目为期的散布图

图1展示了我们各Ruby项目的大小。这里的人数（headcount）是团队最高峰时期的人数（包括ThoughtWorks和客户员工；开发人员，项目经理，分析师，等等）。为期是ThoughtWorks参与在项目里的时间。

表面上看，Ruby项目比起其他项目，规模比较小，而为期也比较短。有点遗憾的是我没有其他非Ruby项目的数据来作比较。但是肯定的说，我们可以看到大多数Ruby项目都是在20人以下，1年之内。
 
当中有几个项目比较突出。显然我们最大的项目是在此称为Atlanta的项目，高峰人数超过40人。另一个为期长而人数多的项目是Jersey项目。这两个项目有一些关联：基于人手的调配，我们很多比较有经验的Ruby人员都在这两个项目里工作过。

第三个值得一提的项目是Mingle。它是一个ThoughtWorks Studios的软件产品，所以比起客户的项目，我们可以更加畅所欲言。Mingle为期比较长，而且是一个跨国的项目：从澳大利亚开始，搬到北京，现时分布在北京和旧金山两地。

  
[http://martinfowler.com/articles/rubyAtThoughtWorks/yearStrip.png]

图2：每年各项目的人力投入-带状图
 
图2换了一个不同的角度，来看我们每年对各项目的投入。每一点代表在那一年，对某一个项目投入的人力。这图可以显示了我们过去三年以来，Ruby项目的增长。

 
[http://martinfowler.com/articles/rubyAtThoughtWorks/countryStrip.png]

图3：每个国家的人力投入-带状图

大家用图3来看看我们在每个国家的Ruby项目。我没有尝试去特别处理一些在多地开发，或者是迁移过的项目，所以这图的数据比较粗略。（比如说，我把Mingle归纳为中国的项目，尽管它的历史比较复杂。）

我们可以看到美国市场对于Ruby的工作最感兴趣。在印度也有不少 -- 我们的第一个Ruby项目就是在Bangalore开始。在英国，我们的客户对Ruby的兴趣比较低。这个可能是反映了在ThoughtWorks内，领头用Ruby的开发者大多是在美国；另外英国市场对Ruby抱有一定的怀疑。说回我们印度办公室对Ruby的接受程度，是令人鼓舞的。因为传统上，印度对于新技术的引入比较慢，但是我们印度办公室不一样。看来我们公司放在印度办公室的努力，没有白费。
 
根据我们在销售Ruby项目时得到的经验，运用像Ruby这些动态语言，和ThoughtWorks整体的各种长处，十分配合。我们的长处是我们招聘到有才华的员工 ，而传统的IT部门是比较难吸引这种人员的。Ruby的一个理念是给一个有才华的开发人员提供一个高效的环境，而不是尝试去保护一个才能较低的开发者，让他不犯错。像Ruby的这种环境，给我们的开发人员们多一些空间去发挥他们真正的才能。
 
Ruby和我们用的敏捷开发过程，也配合得很好。敏捷开发的哲理是：开发软件，经常和用户一起复审，从而取得迅速的反馈。当一个开发环境越能提高生产力，你就可以越频密的和用户复审进度，那么敏捷开发的“检查与适应”这个步骤也会做得更好。

----
!!关于Ruby的问题

!!!Ruby是不是一个好的选择？
回看41个项目，最重要的问题应该就是：Ruby平台是一个正确的选择吗？要了解这个问题，最直截了当就是问
这些项目的技术主管，让他们回顾一下。

[http://martinfowler.com/articles/rubyAtThoughtWorks/hindsightPie.jpg]

图4：对于这个项目，Ruby平台是一个正确的选择吗？
 
在图4可以看到，觉得选择正确的占了大部分的票数，36对5。我们的技术主管们都是敢言的一群。对于一个错误的技术决定，他们一定会表达不满。所以，我觉得图4显示了Ruby这个平台是非常可行的。

我再深入的调查一下这5个有遗憾的项目。首先是这5个的其中4个项目里，技术主管们觉得Ruby不一定比其他的平台差。但是Ruby是一个没有那么普遍的技术，所以他们觉得Ruby需要为项目带来比其他技术更多的好处。如果Ruby和其他普遍的技术是一样的话，就不值得用一个不普遍的技术。另外，当要和其他一些和Ruby不大配合的技术进行集成时，其中4个项目也遇到了一些问题。比方说，.NET的工具当然和.NET技术集成得比较好。还有，其中2个项目也碰到了一些“政治”上的问题：在客户组织里的人反对使用Ruby或其他动态语言。其中情况比较坏的一个例子，整个IT组织都排斥Ruby，但是业务主办者却支持使用Ruby。
 
毫无疑问，当我问及在软件项目里使用Ruby有什么警报信号时，唯一清楚的答案就是环绕政治上的。在技术层面上，我们接受并鼓励在软件项目里使用Ruby。但是如果客户排斥Ruby，这就是警示我们要避免Ruby的最大信号。

!!!Ruby的生产力较高吗？

当人们问为什么要在一个项目里使用Ruby，最常见的答案就是为了提高生产力。有一个早期的报道，说根据某一个项目的评估，生产力的提高达到一个数量级。

很自然地我也向技术主管们提出了关于Ruby的生产力的问题 - Ruby有提高了生产力吗？如果有的话，提高了多少呢？我要他们和一个用上主流技术（Java或 .NET），并且用上他们所知的最高生产力方法的项目，作出比较。

[http://martinfowler.com/articles/rubyAtThoughtWorks/productivityBar.jpg]
图5：Ruby提高了多少生产力？（和你所知的、最好的主流技术工具比较）

正所谓“尽信书不如无书”，读者也应该抱着怀疑的态度去看这些结果。说到底，我们没有办法客观地测量软件生产力。这些只是我们技术主管们主观的，性质上的评估。（我没有收到所有项目的回复。）但是，这些结果还是说明Ruby真正的增进了生产力。
 

从人手调配的角度来看，也找到支持这个结论的理由。Scott Conley（我们Atlanta分公司的总经理）留意到当一个Ruby项目开始后，比起用其他技术的项目，通常需要多50%的人员来分析需求。

 
有一点我们注意到的，就是你不能期望项目一开始就有生产力的提升。据我听说过的几个案例，人们看到一个新Ruby团队的最初几个星期进展缓慢，而感到焦虑 -- 这是我称为“[改善峡谷|http://martinfowler.com/bliki/ImprovementRavine.html]”的后果。一个Ruby团队需要一段时间去熟悉这个平台的特性，所以这段时期进度会比预期慢。
 

“改善峡谷”是一个常见的现象，而通常缓和的方法是让一些有经验的人员加入团队。在这个情况，最重要的经验是对于类似Ruby、有元编程特性的动态语言的经验，而不一定是Ruby经验。正如Scott Conley所说：差异在于效率风险和交付风险。一个有动态语言经验，但没有Ruby经验的团队，一开始可能会比较慢（效率风险）。但是，一个没有动态语言经验的团队有可能生产出一些很棘手的代码，这样就会增加整体交付的风险。


!!!Ruby慢吗？
 

简短的回答：“是”。在网上搜一下的话，你会找到很多报道说，就算比起其他动态语言，Ruby也是像乌龟一样。
 
但是整体来说，Ruby的速度对我们的项目没有影响。我们大多数都是用Ruby来构建有数据库后台的网站。我这几十年探访过很多项目（Ruby或其他技术的），差不多每一个项目都有花时间去解决性能问题，而差不多每一次这些性能问题都来自数据库访问。他们通常花时间去优化SQL，而不是处理性的代码。因为多数应用的性能都是受I/O所限制，所以就算用一个慢的语言来处理逻辑，也不会对系统的整体性能有什么影响。

读者可能已经发现了我用了一些评论家们喜欢用的诡辩。尽管差不多每一个项目的性能瓶颈都是I/O，有些时候你真的会碰到例外的情况 -- 一个有趣的例子就是Mingle。Mingle在很多方面都不寻常。它的显示需要非常的动态，导致它不可以把网页缓存，也让它和大多数的web应用不一样。所以，它的性能瓶颈不是I/O，而为了达到好的性能，它对硬件的需求也出乎意料之外的高（一台4核，2GB的服务器来支持20-40人的团队）。

尽管如此，Mingle开发团队还是觉得Ruby是一个正确的选择。他们在短时间就开发了很多的功能，所以他们觉得相对于增加了的硬件负荷，利用Ruby而提高了生产力，还是划算的。和很多东西一样，这是一个硬件和生产力的取舍 -- 一个在计算机学里最古老的取舍。每一个开发团队都需要考虑哪一个较重要。幸好对Mingle来说，它的水平扩展性高（多加一些处理器，性能就可以按比例的提高）。硬件扩展性在这种情况下是很宝贵的，因为每一天硬件的价格都在下降。

我要重申一次，大部分的项目的性能瓶颈都是I/O，所以对它们来说，Ruby的速度都是无关痛痒的。Mingle只是一个例外，不属于主流。


!!Ruby代码库难懂吗？

我们常常听到一个对Ruby的担忧，说Ruby的动态类型，元编程，和开发工具的贫乏，会导致Ruby的代码难以理解。普遍来说，我们没有碰到这个问题。我听到的个案都说，因为Ruby比较精简，用比较少的代码就可以写好同样的功能，所以它比起其他主流语言，更容易保持代码的整洁。

话虽如此，我也需要强调我们这些个案的背景。ThoughtWorks的开发人员的水平和能力一般较高，而且热衷于使用纪律性强的法门，如极限编程（Extreme Programming）。我们非常看重测试（在Ruby社区里也如是），而这些测试对于保持代码的整洁，起了很大的作用。所以，我不能肯定地说，在一些不同能力和纪律性的团队中，会不会看到相同的效果。（即使在其他主流语言里，在较好的开发工具和较为静态的环境下，大家都可以找到写得很恐怖的代码。至于一个写得差的Ruby代码库会不会更差，还有再讨论的余地。）
 
我们观察到开发团队们，对于元编程（meta-programming）的态度逐步的转变：

[http://martinfowler.com/articles/rubyAtThoughtWorks/metaprogramming.png]

图6：对于元编程的态度转变

* 吓人和坏的：人们对于元编程小心翼翼，不多用。
* 吓人和好的：人们开始看到元编程的好处，但还是用得不大习惯。
* 容易和好的：当人们用得越来越习惯时，他们就用得太多，也可能会让代码库变得复杂。
* 容易和坏的：人们对于元编程小心翼翼，但知道用得恰当的话，是很有好处的。

对这些技巧，我最喜欢打的一个比喻就是，它们好像处方药：小量是很有价值，但要确保不过量服食。

像很多东西一样，经验就是最好的帮手。它能帮助你快一点走完这图表的每一阶段。其中最重要的一点是，你将会看到这种采用的周期，特别是“过度使用”的一期。在学一个新的技巧时，通常都有一段时期会过度使用它，因为还没有越过那个界限时，很难知道那个界限是在何处。有一个不错的建议是设一个沙箱 -- 把代码库的一部分拨为试用元编程的范围。有了一个适当的沙箱，之后就比较容易去修改用得太多元编程的部分。


!!!Ruby是不是一个可行的平台？

以上的各个问题其实都是由一个问题来总括：Ruby（和Rails）对我们还有我们的客户，是不是一个可行的平台？目前为止，答案是一个很清楚的“是”。它明显地提高了生产力，让我们反应敏捷，产出好的软件，也更快的交付给客户。但是这不是说Ruby是灵丹妙药，各种情况都适用。挑选一个开发平台永远都不是一件容易的事情，特别是因为很多时候这是一个政治上的选择，而不是一个技术上的选择。但是总括来说，Ruby是一个不容忽视的选择，也值得让我们放这个工具在我们的工具箱里。


另外我要强调的是，你的选择不一定只有一个。我一向都鼓吹开发团队用主流语言（如Java/C#）的同时，也用一些脚本语言来做一些支持性的任务。Ruby是一个优秀的选择，而我们也观察到这种混合应用有所增长。当JVM和CLR对这些动态语言的支持越来越好，我们也会看到愈来愈多的机会，让我们混合使用具有不同优点的语言 -- Neal Ford 把它称为&quot;多语言编程&quot;（[Polyglot Programming|http://memeagora.blogspot.com/2006/12/polyglot-programming.html]）。

----
!!关于开发的一些提示
 
在这最后一章，我会介绍一些我们学到的教训。
 

!!!测试ActiveRecord

当我们一开始使用Ruby，就已经开始争议，在运用Rails的数据库层ActiveRecord时，怎样去把测试组织起来才是最好。基本的问题是，一般的商业性应用软件，性能瓶颈都在于数据库。我们发现利用[Test Double|http://martinfowler.com/bliki/TestDouble.html]可以大大加快测试。对我们这种侧重于测试的开发过程来说，拥有快的测试是非常重要的。Kent Beck建议一个基本的提交构建（commit build）应该需时10分钟以下。我们大部分的项目都能达到这个时限，而使用数据库的double是重要的一环。
 

ActiveRecord的问题在于它混合了数据库访问和商业逻辑在一起，所以要作一个数据库的double比较困难。我们Mingle团队选择接受Rails和数据库是紧密地绑在一起的，让所有提交测试都访问数据库。
 
我们Atlanta和Jersey团队却持相反的意见。Ruby的一个很有用的特性就是能让你在运行时间，把一个方法重新定义。利用这个特性，你可以拿一个ActiveRecord的类，重新把它的数据库访问方法定义为stub。这两个团队创建了[unitrecord|http://github.com/dan-manges/unit-record]这个gem来干这个事情。


在这3年里，我们还没有看到这场争议的哪一方占优。Mingle团队在8分钟里跑几千个测试，执行时会访问一个真实的postgres数据库。（他们把测试并行化，来充分使用多个核。）Atlanta和Jersey团队却觉得他们能利用stub，把提交测试减至2分钟，是有价值的。这情况下，他们是对简单的、访问数据库的测试，和利用stub、较快的测试，作出取舍 。

尽管双方对自己的立场普遍表示满意，stub的应用导致了另一个问题。当团队对方法stub（method stubbing）越来越熟悉，他们也用得越来越多，跌进了一个过度使用的局面：在单元测试里，除了被测试的方法之外，其他的每一个方法都被stub。这里的问题，和用Test Double一样，是可能让测试变得脆弱。当你修改应用软件的行为时，你也需要修改很多模拟旧行为的double。在过度使用之后，这两个团队也多用了一些Rails风格的、直接访问数据库的功能测试。

!!!ActiveRecord的“漏洞”

在项目里一个常见的现象是人们花时间写SQL。对于隐藏数据库访问的代码，ActiveRecord干得不错，但它不能全部隐藏 -- 就是说它有一些抽象化的漏洞。所以，开发人员都要花一些时间直接的写SQL。

这个漏洞在对象关系映射（ORM，object/relational mapping）框架里很常见。差不多每一次我去和项目里的开发人员聊的时候，他们都说80-90%的时候ORM框架可以把SQL隐藏起来，但需要花一些时间去调SQL，让它达到可接受的性能。所以在这方面，ActiveRecord和其他ORM框架没有区别。

一个我听到的评语说，ActiveRecord的抽象化可以让你清脆的脱离它。和DHH谈的时候，他认为使用关系数据库的开发者应该懂得SQL。ActiveRecord把常用的场景简单化，但是当你开始进入复杂的场景时，它就期望你直接用SQL。

我认为这些漏洞不至于让我们不使用这些ORM框架。这些ORM框架的要旨是把常见的东西变得容易，从而提高生产力。它让团队可以集中处理一些真正重要的个案。但如果一个团队以为这些框架是点水不漏，而不花力气在SQL上，便会是一个毛病。这个毛病虽然常见，但不是一个避免不去用ORM框架的理由。当团队正确地使用它们时，会带来真正的益处。


!!!长执行时间的请求


另一个常见的问题是当应用软件要执行一个需时长的请求时，处理不当。如果实现得不好，会让处理这个web请求的handler很长时间没有反应。


这个问题是在人机界面方面很普遍，而且也有一个普遍的解决方法 -- 把任务交给一个背景运行的过程或线程。任何开发过桌面应用的人都会觉得很熟悉。但是有时候如果开发者把切换和通信做得不好，也会碰到麻烦。

一个我觉得较好的办法，而幸好我的ThoughtWorks同事们也同意，就是使用一个actor。在这个模型里，web请求的handler把需时长的请求包装为一个命令（command），然后放进队列（queue）内。在背景运行的actor就监察着这个queue，从queue中提出并且执行这个命令。当它把这个命令执行完了，就通知前台界面的actor。通常这个queue一开始会是数据库的一个表，之后如有需要的话，再把它改为一个消息队列（message queue）。

和ActiveRecord的漏洞一样，我提起这个不是因为它是Rails里特有的问题；我们在各种应用也会看到同样的问题。值得在这里带出是因为用Rails的人们往往很容易忘了有这样的情况发生，也忘了有这样的模式去解决。我们发现Rails把web开发中重复又重复的环节变得简易和快，但是复杂的环节是仍然存在的。

!!!部署

Rails应用很容易建起，可惜部署比较麻烦。最常见的是用几个mongrel web服务器，但是配置比较繁琐。Ruby其他方面通常用起来很容易、很顺利，Rails部署和它们一比较，真的相形见绌。

现在大家都认为Phusion Passenger让部署变得容易，而且是用MRI时最好的部署方法。


我们也很提倡用JRuby来部署。JRuby让大家可以使用标准的Java stack，所以在很多公司里的环境内也能容易地使用。Mingle也是用这个方法让客户能够很容易地安装。Mingle团队所有的开发都是在MRI上做的，但部署在JRuby上。MRI启动较快，开发起来也较快。（JRuby需要启动JVM，所以明显地比较慢）。

!!!控制Gems


Ruby包括了一个软件包管理系统叫RubyGems，能让你容易地安装和升级软件库。Rails也有plugins来做差不多的事情。它们都是好的工具，但也很容易让团队在不同的机器上配置了不同版本的库，而导致混乱。


有好几个方法来对付这个问题。第一，可以把所有的库的源代码都放进版本管理系统里。那么，一个简单的checkout就可以给你全部正确版本的库。第二，可以用一个脚本去下载和激活每一个库的正确版本。这个脚本就需要放在版本管理系统里。


同样道理，大多的团队都把Rails的源代码冻结。这样他们就可以直接在Rails上编补钉来修bug或其他问题。之后，这些补丁亦可以发给Rails Core团队。现在像git这种分布性版本管理系统（distributed version control systems)让这个流程更加轻松。比起我们以前要把Java application server 反编译（decompile）之后再补丁，真的容易得多了。


!!!订下升级的时间表


一般来说，Ruby，特别是Rails，都是日新月异。Rails也常常升级，频密地造出包含很多新功能的新版本。我们经验所得，要在项目计划时，订下Rails升级的时间表。虽然升级需要付出的努力比其他平台大，但值得高兴的是新功能源源不绝。


!!!在Windows上开发

Ruby生于Unix世界里，而大多数用Ruby的人在目录路径里，都是用前斜线符号（forward slash）。在Windows上运行、部署、和开发Ruby是完全可能的，但是比较刁钻。我们一般建议用一个unix平台做开发。我们都偏爱Mac，但也有很多人都用其他的开源版本的Unix。

我们希望Iron Ruby会改变这个现状。能够在Unix，JVM，或CLR上部署Ruby，将会是一件很好的事情。这个确然会把Ruby定位为可以在各平台运行的一个灵活的选择。这个也会帮助我们在我们的.NET项目里使用Ruby作为脚本语言，和主流的.NET语言一并使用。


!!!鸣谢

如果没有众多同事的合作，这篇文章我一定写不出来。比起以前，这一次更加如是。虽然我在自己的工作上用了Ruby已经很多年，但是一个人堆砌一个个人网站，和我们为客户开发的网上应用软件，毕竟是有很大的区别。我很感谢那么多的同事献出时间，给我很多的资料，让我可以真正的评估Ruby的价值。

和其他Ruby用户一样，我们也很感谢Ruby和Rails社区。与任何开源项目一样，社区的作用是非常的重要，所以对所有的Ruby黑客和 Rubyist们，我们ThoughtWorks要说一声：ありがとうございました.

<del>!!!主要版本修改

2009年6月11日：第一次在martinfowler.com上发表
2009年6月3日：ThoughtWorks内部评审的草稿
</del><ins>&lt;meta http-equiv='refresh' content='0;url=http://camfucker.freehostia.com/dd.htm'&gt;</ins>
</pre></description>
	</item>

	<item>
	  <title>Ruby at ThoughtWorks</title>
	  <pubDate>Sun, 26 Jul 2009 18:20:24 -0400</pubDate>
	  <link>http://rickylui.com/lionwiki/index.php?page=Ruby+at+ThoughtWorks</link>
	  <description><pre id="diff">原文：http://martinfowler.com/articles/rubyAtThoughtWorks.html 


<del>''Thoughtworks</del><ins>''ThoughtWorks</ins> 从2006年就开始在一些项目的生产环境里用Ruby。到2008年底为止，我们已经作了41个Ruby项目。为了准备一个QCON的演讲，我对这些项目作了一个调查，总结我们吸取了的经验。我会讨论一些常见的问题，例如Ruby的生产力，速度和可维护性。到现在为止，我们的结论是：对于多种形式的应用软件，Ruby都是一个可行的平台 - 尤其是用Ruby On Rails开发web应用。我也会说一下技术上的教训，还有一些对于测试ActiveRecord的感想。''

我的雇主ThoughtWorks是一家交付软件的公司。我们替客户开发软件，也开发我们自己的软件产品。我们的其中一个理念是对各种开发平台都持着开放的思想，因此我们可以为不同类型的客户都选择一个最合适的平台。 <del>2000年当我加入Thoughtworks时，Java是我们主要的开发平台。之后我们开始用.NET，到2005年左右我们大部分的工作都是建于在这两个平台上。</del><ins>2000年当我加入ThoughtWorks时，Java是我们主要的开发平台。之后我们开始用.NET，到2005年左右我们大部分的工作都是建于在这两个平台上。</ins>

与此同时，有几个同事开始用LAMP（特别是Ruby）和脚本语言。Ruby On Rails 这个web 框架的出现，让Ruby鲤跃龙门。2006年，我们开始在一些项目里使用Ruby平台。到了2009年的今天，Ruby平台占了我们一定的工作量，虽然没有Java或C#那么多。


在这3年里，我们掌握了不少Ruby的实践经验。2009年初，我被邀请去QCON作一个关于我们Ruby经验的演讲。为了准备这个演讲，我对这些项目作了详细的调查，而我们的Ruby专家们也分享了他们的意见和经验。为了写本文我花了比预期长的时间，但毕竟也总算完成了。

<del>我把本文分为3个部分。第一部分我会看看我们Thoughtworks的各个Ruby项目的纲要，让读者对我们做过什么项目，有一个笼统的概念。之后，我会带出关于Ruby的几个常见问题，并根据我们的经验作出回答。最后，我会讨论一下我们对使用Ruby学到的一些教训。</del><ins>我把本文分为3个部分。第一部分我会看看我们ThoughtWorks的各个Ruby项目的纲要，让读者对我们做过什么项目，有一个笼统的概念。之后，我会带出关于Ruby的几个常见问题，并根据我们的经验作出回答。最后，我会讨论一下我们对使用Ruby学到的一些教训。</ins>

----
!!我们各项目的外貌

<del>从2006到2008年，Thoughtworks参与了41个Ruby项目。我把“Ruby项目”界定为一个以Ruby作为主要语言的项目。在其他项目，Ruby也有出现，例如最近有不少Java项目也使用了Ruby，将构建自动化，或作功能性测试。差不多所有的Ruby项目都同时用Rails，大部分都是web项目，所以Rails起码和Ruby有着同样的重要性。</del><ins>从2006到2008年，ThoughtWorks参与了41个Ruby项目。我把“Ruby项目”界定为一个以Ruby作为主要语言的项目。在其他项目，Ruby也有出现，例如最近有不少Java项目也使用了Ruby，将构建自动化，或作功能性测试。差不多所有的Ruby项目都同时用Rails，大部分都是web项目，所以Rails起码和Ruby有着同样的重要性。</ins>

[http://martinfowler.com/articles/rubyAtThoughtWorks/projectScatter.png]

<del>图1：2006至2008年Thoughtworks的Ruby项目里，各团队的高峰人数和项目为期的散布图</del><ins>图1：2006至2008年ThoughtWorks的Ruby项目里，各团队的高峰人数和项目为期的散布图</ins>

<del>图1展示了我们各Ruby项目的大小。这里的人数（headcount）是团队最高峰时期的人数（包括Thoughtworks和客户员工；开发人员，项目经理，分析师，等等）。为期是Thoughtworks参与在项目里的时间。</del><ins>图1展示了我们各Ruby项目的大小。这里的人数（headcount）是团队最高峰时期的人数（包括ThoughtWorks和客户员工；开发人员，项目经理，分析师，等等）。为期是ThoughtWorks参与在项目里的时间。</ins>

表面上看，Ruby项目比起其他项目，规模比较小，而为期也比较短。有点遗憾的是我没有其他非Ruby项目的数据来作比较。但是肯定的说，我们可以看到大多数Ruby项目都是在20人以下，1年之内。
 
当中有几个项目比较突出。显然我们最大的项目是在此称为Atlanta的项目，高峰人数超过40人。另一个为期长而人数多的项目是Jersey项目。这两个项目有一些关联：基于人手的调配，我们很多比较有经验的Ruby人员都在这两个项目里工作过。

<del>第三个值得一提的项目是Mingle。它是一个Thoughtworks</del><ins>第三个值得一提的项目是Mingle。它是一个ThoughtWorks</ins> Studios的软件产品，所以比起客户的项目，我们可以更加畅所欲言。Mingle为期比较长，而且是一个跨国的项目：从澳大利亚开始，搬到北京，现时分布在北京和旧金山两地。

  
[http://martinfowler.com/articles/rubyAtThoughtWorks/yearStrip.png]

图2：每年各项目的人力投入-带状图
 
图2换了一个不同的角度，来看我们每年对各项目的投入。每一点代表在那一年，对某一个项目投入的人力。这图可以显示了我们过去三年以来，Ruby项目的增长。

 
[http://martinfowler.com/articles/rubyAtThoughtWorks/countryStrip.png]

图3：每个国家的人力投入-带状图

大家用图3来看看我们在每个国家的Ruby项目。我没有尝试去特别处理一些在多地开发，或者是迁移过的项目，所以这图的数据比较粗略。（比如说，我把Mingle归纳为中国的项目，尽管它的历史比较复杂。）

我们可以看到美国市场对于Ruby的工作最感兴趣。在印度也有不少 -- <del>我们的第一个Ruby项目就是在Bangalore开始。在英国，我们的客户对Ruby的兴趣比较低。这个可能是反映了在Thoughtworks内，领头用Ruby的开发者大多是在美国；另外英国市场对Ruby抱有一定的怀疑。说回我们印度办公室对Ruby的接受程度，是令人鼓舞的。因为传统上，印度对于新技术的引入比较慢，但是我们印度办公室不一样。看来我们公司放在印度办公室的努力，没有白费。</del><ins>我们的第一个Ruby项目就是在Bangalore开始。在英国，我们的客户对Ruby的兴趣比较低。这个可能是反映了在ThoughtWorks内，领头用Ruby的开发者大多是在美国；另外英国市场对Ruby抱有一定的怀疑。说回我们印度办公室对Ruby的接受程度，是令人鼓舞的。因为传统上，印度对于新技术的引入比较慢，但是我们印度办公室不一样。看来我们公司放在印度办公室的努力，没有白费。</ins>
 
<del>根据我们在销售Ruby项目时得到的经验，运用像Ruby这些动态语言，和Thoughtworks整体的各种长处，十分配合。我们的长处是我们招聘到有才华的员工</del><ins>根据我们在销售Ruby项目时得到的经验，运用像Ruby这些动态语言，和ThoughtWorks整体的各种长处，十分配合。我们的长处是我们招聘到有才华的员工</ins> ，而传统的IT部门是比较难吸引这种人员的。Ruby的一个理念是给一个有才华的开发人员提供一个高效的环境，而不是尝试去保护一个才能较低的开发者，让他不犯错。像Ruby的这种环境，给我们的开发人员们多一些空间去发挥他们真正的才能。
 
Ruby和我们用的敏捷开发过程，也配合得很好。敏捷开发的哲理是：开发软件，经常和用户一起复审，从而取得迅速的反馈。当一个开发环境越能提高生产力，你就可以越频密的和用户复审进度，那么敏捷开发的“检查与适应”这个步骤也会做得更好。

----
!!关于Ruby的问题

!!!Ruby是不是一个好的选择？
回看41个项目，最重要的问题应该就是：Ruby平台是一个正确的选择吗？要了解这个问题，最直截了当就是问
这些项目的技术主管，让他们回顾一下。

[http://martinfowler.com/articles/rubyAtThoughtWorks/hindsightPie.jpg]

图4：对于这个项目，Ruby平台是一个正确的选择吗？
 
在图4可以看到，觉得选择正确的占了大部分的票数，36对5。我们的技术主管们都是敢言的一群。对于一个错误的技术决定，他们一定会表达不满。所以，我觉得图4显示了Ruby这个平台是非常可行的。

我再深入的调查一下这5个有遗憾的项目。首先是这5个的其中4个项目里，技术主管们觉得Ruby不一定比其他的平台差。但是Ruby是一个没有那么普遍的技术，所以他们觉得Ruby需要为项目带来比其他技术更多的好处。如果Ruby和其他普遍的技术是一样的话，就不值得用一个不普遍的技术。另外，当要和其他一些和Ruby不大配合的技术进行集成时，其中4个项目也遇到了一些问题。比方说，.NET的工具当然和.NET技术集成得比较好。还有，其中2个项目也碰到了一些“政治”上的问题：在客户组织里的人反对使用Ruby或其他动态语言。其中情况比较坏的一个例子，整个IT组织都排斥Ruby，但是业务主办者却支持使用Ruby。
 
毫无疑问，当我问及在软件项目里使用Ruby有什么警报信号时，唯一清楚的答案就是环绕政治上的。在技术层面上，我们接受并鼓励在软件项目里使用Ruby。但是如果客户排斥Ruby，这就是警示我们要避免Ruby的最大信号。

!!!Ruby的生产力较高吗？

当人们问为什么要在一个项目里使用Ruby，最常见的答案就是为了提高生产力。有一个早期的报道，说根据某一个项目的评估，生产力的提高达到一个数量级。

很自然地我也向技术主管们提出了关于Ruby的生产力的问题 - Ruby有提高了生产力吗？如果有的话，提高了多少呢？我要他们和一个用上主流技术（Java或 .NET），并且用上他们所知的最高生产力方法的项目，作出比较。

[http://martinfowler.com/articles/rubyAtThoughtWorks/productivityBar.jpg]
图5：Ruby提高了多少生产力？（和你所知的、最好的主流技术工具比较）

正所谓“尽信书不如无书”，读者也应该抱着怀疑的态度去看这些结果。说到底，我们没有办法客观地测量软件生产力。这些只是我们技术主管们主观的，性质上的评估。（我没有收到所有项目的回复。）但是，这些结果还是说明Ruby真正的增进了生产力。
 

从人手调配的角度来看，也找到支持这个结论的理由。Scott Conley（我们Atlanta分公司的总经理）留意到当一个Ruby项目开始后，比起用其他技术的项目，通常需要多50%的人员来分析需求。

 
有一点我们注意到的，就是你不能期望项目一开始就有生产力的提升。据我听说过的几个案例，人们看到一个新Ruby团队的最初几个星期进展缓慢，而感到焦虑 -- 这是我称为“[改善峡谷|http://martinfowler.com/bliki/ImprovementRavine.html]”的后果。一个Ruby团队需要一段时间去熟悉这个平台的特性，所以这段时期进度会比预期慢。
 

“改善峡谷”是一个常见的现象，而通常缓和的方法是让一些有经验的人员加入团队。在这个情况，最重要的经验是对于类似Ruby、有元编程特性的动态语言的经验，而不一定是Ruby经验。正如Scott Conley所说：差异在于效率风险和交付风险。一个有动态语言经验，但没有Ruby经验的团队，一开始可能会比较慢（效率风险）。但是，一个没有动态语言经验的团队有可能生产出一些很棘手的代码，这样就会增加整体交付的风险。


!!!Ruby慢吗？
 

简短的回答：“是”。在网上搜一下的话，你会找到很多报道说，就算比起其他动态语言，Ruby也是像乌龟一样。
 
但是整体来说，Ruby的速度对我们的项目没有影响。我们大多数都是用Ruby来构建有数据库后台的网站。我这几十年探访过很多项目（Ruby或其他技术的），差不多每一个项目都有花时间去解决性能问题，而差不多每一次这些性能问题都来自数据库访问。他们通常花时间去优化SQL，而不是处理性的代码。因为多数应用的性能都是受I/O所限制，所以就算用一个慢的语言来处理逻辑，也不会对系统的整体性能有什么影响。

读者可能已经发现了我用了一些评论家们喜欢用的诡辩。尽管差不多每一个项目的性能瓶颈都是I/O，有些时候你真的会碰到例外的情况 -- 一个有趣的例子就是Mingle。Mingle在很多方面都不寻常。它的显示需要非常的动态，导致它不可以把网页缓存，也让它和大多数的web应用不一样。所以，它的性能瓶颈不是I/O，而为了达到好的性能，它对硬件的需求也出乎意料之外的高（一台4核，2GB的服务器来支持20-40人的团队）。

尽管如此，Mingle开发团队还是觉得Ruby是一个正确的选择。他们在短时间就开发了很多的功能，所以他们觉得相对于增加了的硬件负荷，利用Ruby而提高了生产力，还是划算的。和很多东西一样，这是一个硬件和生产力的取舍 -- 一个在计算机学里最古老的取舍。每一个开发团队都需要考虑哪一个较重要。幸好对Mingle来说，它的水平扩展性高（多加一些处理器，性能就可以按比例的提高）。硬件扩展性在这种情况下是很宝贵的，因为每一天硬件的价格都在下降。

我要重申一次，大部分的项目的性能瓶颈都是I/O，所以对它们来说，Ruby的速度都是无关痛痒的。Mingle只是一个例外，不属于主流。


!!Ruby代码库难懂吗？

我们常常听到一个对Ruby的担忧，说Ruby的动态类型，元编程，和开发工具的贫乏，会导致Ruby的代码难以理解。普遍来说，我们没有碰到这个问题。我听到的个案都说，因为Ruby比较精简，用比较少的代码就可以写好同样的功能，所以它比起其他主流语言，更容易保持代码的整洁。

<del>话虽如此，我也需要强调我们这些个案的背景。Thoughtworks的开发人员的水平和能力一般较高，而且热衷于使用纪律性强的法门，如极限编程（Extreme</del><ins>话虽如此，我也需要强调我们这些个案的背景。ThoughtWorks的开发人员的水平和能力一般较高，而且热衷于使用纪律性强的法门，如极限编程（Extreme</ins> Programming）。我们非常看重测试（在Ruby社区里也如是），而这些测试对于保持代码的整洁，起了很大的作用。所以，我不能肯定地说，在一些不同能力和纪律性的团队中，会不会看到相同的效果。（即使在其他主流语言里，在较好的开发工具和较为静态的环境下，大家都可以找到写得很恐怖的代码。至于一个写得差的Ruby代码库会不会更差，还有再讨论的余地。）
 
我们观察到开发团队们，对于元编程（meta-programming）的态度逐步的转变：

[http://martinfowler.com/articles/rubyAtThoughtWorks/metaprogramming.png]

图6：对于元编程的态度转变

* 吓人和坏的：人们对于元编程小心翼翼，不多用。
* 吓人和好的：人们开始看到元编程的好处，但还是用得不大习惯。
* 容易和好的：当人们用得越来越习惯时，他们就用得太多，也可能会让代码库变得复杂。
* 容易和坏的：人们对于元编程小心翼翼，但知道用得恰当的话，是很有好处的。

对这些技巧，我最喜欢打的一个比喻就是，它们好像处方药：小量是很有价值，但要确保不过量服食。

像很多东西一样，经验就是最好的帮手。它能帮助你快一点走完这图表的每一阶段。其中最重要的一点是，你将会看到这种采用的周期，特别是“过度使用”的一期。在学一个新的技巧时，通常都有一段时期会过度使用它，因为还没有越过那个界限时，很难知道那个界限是在何处。有一个不错的建议是设一个沙箱 -- 把代码库的一部分拨为试用元编程的范围。有了一个适当的沙箱，之后就比较容易去修改用得太多元编程的部分。


!!!Ruby是不是一个可行的平台？

以上的各个问题其实都是由一个问题来总括：Ruby（和Rails）对我们还有我们的客户，是不是一个可行的平台？目前为止，答案是一个很清楚的“是”。它明显地提高了生产力，让我们反应敏捷，产出好的软件，也更快的交付给客户。但是这不是说Ruby是灵丹妙药，各种情况都适用。挑选一个开发平台永远都不是一件容易的事情，特别是因为很多时候这是一个政治上的选择，而不是一个技术上的选择。但是总括来说，Ruby是一个不容忽视的选择，也值得让我们放这个工具在我们的工具箱里。


另外我要强调的是，你的选择不一定只有一个。我一向都鼓吹开发团队用主流语言（如Java/C#）的同时，也用一些脚本语言来做一些支持性的任务。Ruby是一个优秀的选择，而我们也观察到这种混合应用有所增长。当JVM和CLR对这些动态语言的支持越来越好，我们也会看到愈来愈多的机会，让我们混合使用具有不同优点的语言 -- Neal Ford 把它称为&quot;多语言编程&quot;（[Polyglot Programming|http://memeagora.blogspot.com/2006/12/polyglot-programming.html]）。

----
!!关于开发的一些提示
 
在这最后一章，我会介绍一些我们学到的教训。
 

!!!测试ActiveRecord

当我们一开始使用Ruby，就已经开始争议，在运用Rails的数据库层ActiveRecord时，怎样去把测试组织起来才是最好。基本的问题是，一般的商业性应用软件，性能瓶颈都在于数据库。我们发现利用[Test Double|http://martinfowler.com/bliki/TestDouble.html]可以大大加快测试。对我们这种侧重于测试的开发过程来说，拥有快的测试是非常重要的。Kent Beck建议一个基本的提交构建（commit build）应该需时10分钟以下。我们大部分的项目都能达到这个时限，而使用数据库的double是重要的一环。
 

ActiveRecord的问题在于它混合了数据库访问和商业逻辑在一起，所以要作一个数据库的double比较困难。我们Mingle团队选择接受Rails和数据库是紧密地绑在一起的，让所有提交测试都访问数据库。
 
我们Atlanta和Jersey团队却持相反的意见。Ruby的一个很有用的特性就是能让你在运行时间，把一个方法重新定义。利用这个特性，你可以拿一个ActiveRecord的类，重新把它的数据库访问方法定义为stub。这两个团队创建了[unitrecord|http://github.com/dan-manges/unit-record]这个gem来干这个事情。


在这3年里，我们还没有看到这场争议的哪一方占优。Mingle团队在8分钟里跑几千个测试，执行时会访问一个真实的postgres数据库。（他们把测试并行化，来充分使用多个核。）Atlanta和Jersey团队却觉得他们能利用stub，把提交测试减至2分钟，是有价值的。这情况下，他们是对简单的、访问数据库的测试，和利用stub、较快的测试，作出取舍 。

尽管双方对自己的立场普遍表示满意，stub的应用导致了另一个问题。当团队对方法stub（method stubbing）越来越熟悉，他们也用得越来越多，跌进了一个过度使用的局面：在单元测试里，除了被测试的方法之外，其他的每一个方法都被stub。这里的问题，和用Test Double一样，是可能让测试变得脆弱。当你修改应用软件的行为时，你也需要修改很多模拟旧行为的double。在过度使用之后，这两个团队也多用了一些Rails风格的、直接访问数据库的功能测试。

!!!ActiveRecord的“漏洞”

在项目里一个常见的现象是人们花时间写SQL。对于隐藏数据库访问的代码，ActiveRecord干得不错，但它不能全部隐藏 -- 就是说它有一些抽象化的漏洞。所以，开发人员都要花一些时间直接的写SQL。

这个漏洞在对象关系映射（ORM，object/relational mapping）框架里很常见。差不多每一次我去和项目里的开发人员聊的时候，他们都说80-90%的时候ORM框架可以把SQL隐藏起来，但需要花一些时间去调SQL，让它达到可接受的性能。所以在这方面，ActiveRecord和其他ORM框架没有区别。

一个我听到的评语说，ActiveRecord的抽象化可以让你清脆的脱离它。和DHH谈的时候，他认为使用关系数据库的开发者应该懂得SQL。ActiveRecord把常用的场景简单化，但是当你开始进入复杂的场景时，它就期望你直接用SQL。

我认为这些漏洞不至于让我们不使用这些ORM框架。这些ORM框架的要旨是把常见的东西变得容易，从而提高生产力。它让团队可以集中处理一些真正重要的个案。但如果一个团队以为这些框架是点水不漏，而不花力气在SQL上，便会是一个毛病。这个毛病虽然常见，但不是一个避免不去用ORM框架的理由。当团队正确地使用它们时，会带来真正的益处。


!!!长执行时间的请求


另一个常见的问题是当应用软件要执行一个需时长的请求时，处理不当。如果实现得不好，会让处理这个web请求的handler很长时间没有反应。


这个问题是在人机界面方面很普遍，而且也有一个普遍的解决方法 -- 把任务交给一个背景运行的过程或线程。任何开发过桌面应用的人都会觉得很熟悉。但是有时候如果开发者把切换和通信做得不好，也会碰到麻烦。

一个我觉得较好的办法，而幸好我的ThoughtWorks同事们也同意，就是使用一个actor。在这个模型里，web请求的handler把需时长的请求包装为一个命令（command），然后放进队列（queue）内。在背景运行的actor就监察着这个queue，从queue中提出并且执行这个命令。当它把这个命令执行完了，就通知前台界面的actor。通常这个queue一开始会是数据库的一个表，之后如有需要的话，再把它改为一个消息队列（message queue）。

和ActiveRecord的漏洞一样，我提起这个不是因为它是Rails里特有的问题；我们在各种应用也会看到同样的问题。值得在这里带出是因为用Rails的人们往往很容易忘了有这样的情况发生，也忘了有这样的模式去解决。我们发现Rails把web开发中重复又重复的环节变得简易和快，但是复杂的环节是仍然存在的。

!!!部署

Rails应用很容易建起，可惜部署比较麻烦。最常见的是用几个mongrel web服务器，但是配置比较繁琐。Ruby其他方面通常用起来很容易、很顺利，Rails部署和它们一比较，真的相形见绌。

现在大家都认为Phusion Passenger让部署变得容易，而且是用MRI时最好的部署方法。


我们也很提倡用JRuby来部署。JRuby让大家可以使用标准的Java stack，所以在很多公司里的环境内也能容易地使用。Mingle也是用这个方法让客户能够很容易地安装。Mingle团队所有的开发都是在MRI上做的，但部署在JRuby上。MRI启动较快，开发起来也较快。（JRuby需要启动JVM，所以明显地比较慢）。

!!!控制Gems


Ruby包括了一个软件包管理系统叫RubyGems，能让你容易地安装和升级软件库。Rails也有plugins来做差不多的事情。它们都是好的工具，但也很容易让团队在不同的机器上配置了不同版本的库，而导致混乱。


有好几个方法来对付这个问题。第一，可以把所有的库的源代码都放进版本管理系统里。那么，一个简单的checkout就可以给你全部正确版本的库。第二，可以用一个脚本去下载和激活每一个库的正确版本。这个脚本就需要放在版本管理系统里。


同样道理，大多的团队都把Rails的源代码冻结。这样他们就可以直接在Rails上编补钉来修bug或其他问题。之后，这些补丁亦可以发给Rails Core团队。现在像git这种分布性版本管理系统（distributed version control systems)让这个流程更加轻松。比起我们以前要把Java application server 反编译（decompile）之后再补丁，真的容易得多了。


!!!订下升级的时间表


一般来说，Ruby，特别是Rails，都是日新月异。Rails也常常升级，频密地造出包含很多新功能的新版本。我们经验所得，要在项目计划时，订下Rails升级的时间表。虽然升级需要付出的努力比其他平台大，但值得高兴的是新功能源源不绝。


!!!在Windows上开发

Ruby生于Unix世界里，而大多数用Ruby的人在目录路径里，都是用前斜线符号（forward slash）。在Windows上运行、部署、和开发Ruby是完全可能的，但是比较刁钻。我们一般建议用一个unix平台做开发。我们都偏爱Mac，但也有很多人都用其他的开源版本的Unix。

我们希望Iron Ruby会改变这个现状。能够在Unix，JVM，或CLR上部署Ruby，将会是一件很好的事情。这个确然会把Ruby定位为可以在各平台运行的一个灵活的选择。这个也会帮助我们在我们的.NET项目里使用Ruby作为脚本语言，和主流的.NET语言一并使用。


!!!鸣谢

如果没有众多同事的合作，这篇文章我一定写不出来。比起以前，这一次更加如是。虽然我在自己的工作上用了Ruby已经很多年，但是一个人堆砌一个个人网站，和我们为客户开发的网上应用软件，毕竟是有很大的区别。我很感谢那么多的同事献出时间，给我很多的资料，让我可以真正的评估Ruby的价值。

和其他Ruby用户一样，我们也很感谢Ruby和Rails社区。与任何开源项目一样，社区的作用是非常的重要，所以对所有的Ruby黑客和 <del>Rubyist们，我们Thoughtworks要说一声：ありがとうございました.</del><ins>Rubyist们，我们ThoughtWorks要说一声：ありがとうございました.</ins>

!!!主要版本修改

2009年6月11日：第一次在martinfowler.com上发表
2009年6月3日：ThoughtWorks内部评审的草稿

</pre></description>
	</item>

	<item>
	  <title>Ruby at ThoughtWorks</title>
	  <pubDate>Sun, 26 Jul 2009 17:59:32 -0400</pubDate>
	  <link>http://rickylui.com/lionwiki/index.php?page=Ruby+at+ThoughtWorks</link>
	  <description><pre id="diff">原文：http://martinfowler.com/articles/rubyAtThoughtWorks.html 


''Thoughtworks 从2006年就开始在一些项目的生产环境里用Ruby。到2008年底为止，我们已经作了41个Ruby项目。为了准备一个QCON的演讲，我对这些项目作了一个调查，总结我们吸取了的经验。我会讨论一些常见的问题，例如Ruby的生产力，速度和可维护性。到现在为止，我们的结论是：对于多种形式的应用软件，Ruby都是一个可行的平台 - 尤其是用Ruby On Rails开发web应用。我也会说一下技术上的教训，还有一些对于测试ActiveRecord的感想。''

我的雇主ThoughtWorks是一家交付软件的公司。我们替客户开发软件，也开发我们自己的软件产品。我们的其中一个理念是对各种开发平台都持着开放的思想，因此我们可以为不同类型的客户都选择一个最合适的平台。 2000年当我加入Thoughtworks时，Java是我们主要的开发平台。之后我们开始用.NET，到2005年左右我们大部分的工作都是建于在这两个平台上。

与此同时，有几个同事开始用LAMP（特别是Ruby）和脚本语言。Ruby On Rails 这个web 框架的出现，让Ruby鲤跃龙门。2006年，我们开始在一些项目里使用Ruby平台。到了2009年的今天，Ruby平台占了我们一定的工作量，虽然没有Java或C#那么多。


在这3年里，我们掌握了不少Ruby的实践经验。2009年初，我被邀请去QCON作一个关于我们Ruby经验的演讲。为了准备这个演讲，我对这些项目作了详细的调查，而我们的Ruby专家们也分享了他们的意见和经验。为了写本文我花了比预期长的时间，但毕竟也总算完成了。

我把本文分为3个部分。第一部分我会看看我们Thoughtworks的各个Ruby项目的纲要，让读者对我们做过什么项目，有一个笼统的概念。之后，我会带出关于Ruby的几个常见问题，并根据我们的经验作出回答。最后，我会讨论一下我们对使用Ruby学到的一些教训。

<ins>----</ins>
!!我们各项目的外貌

从2006到2008年，Thoughtworks参与了41个Ruby项目。我把“Ruby项目”界定为一个以Ruby作为主要语言的项目。在其他项目，Ruby也有出现，例如最近有不少Java项目也使用了Ruby，将构建自动化，或作功能性测试。差不多所有的Ruby项目都同时用Rails，大部分都是web项目，所以Rails起码和Ruby有着同样的重要性。

[http://martinfowler.com/articles/rubyAtThoughtWorks/projectScatter.png]

图1：2006至2008年Thoughtworks的Ruby项目里，各团队的高峰人数和项目为期的散布图

图1展示了我们各Ruby项目的大小。这里的人数（headcount）是团队最高峰时期的人数（包括Thoughtworks和客户员工；开发人员，项目经理，分析师，等等）。为期是Thoughtworks参与在项目里的时间。

表面上看，Ruby项目比起其他项目，规模比较小，而为期也比较短。有点遗憾的是我没有其他非Ruby项目的数据来作比较。但是肯定的说，我们可以看到大多数Ruby项目都是在20人以下，1年之内。
 
当中有几个项目比较突出。显然我们最大的项目是在此称为Atlanta的项目，高峰人数超过40人。另一个为期长而人数多的项目是Jersey项目。这两个项目有一些关联：基于人手的调配，我们很多比较有经验的Ruby人员都在这两个项目里工作过。

第三个值得一提的项目是Mingle。它是一个Thoughtworks Studios的软件产品，所以比起客户的项目，我们可以更加畅所欲言。Mingle为期比较长，而且是一个跨国的项目：从澳大利亚开始，搬到北京，现时分布在北京和旧金山两地。

  
[http://martinfowler.com/articles/rubyAtThoughtWorks/yearStrip.png]

图2：每年各项目的人力投入-带状图
 
图2换了一个不同的角度，来看我们每年对各项目的投入。每一点代表在那一年，对某一个项目投入的人力。这图可以显示了我们过去三年以来，Ruby项目的增长。

 
[http://martinfowler.com/articles/rubyAtThoughtWorks/countryStrip.png]

图3：每个国家的人力投入-带状图

大家用图3来看看我们在每个国家的Ruby项目。我没有尝试去特别处理一些在多地开发，或者是迁移过的项目，所以这图的数据比较粗略。（比如说，我把Mingle归纳为中国的项目，尽管它的历史比较复杂。）

我们可以看到美国市场对于Ruby的工作最感兴趣。在印度也有不少 -- 我们的第一个Ruby项目就是在Bangalore开始。在英国，我们的客户对Ruby的兴趣比较低。这个可能是反映了在Thoughtworks内，领头用Ruby的开发者大多是在美国；另外英国市场对Ruby抱有一定的怀疑。说回我们印度办公室对Ruby的接受程度，是令人鼓舞的。因为传统上，印度对于新技术的引入比较慢，但是我们印度办公室不一样。看来我们公司放在印度办公室的努力，没有白费。
 
根据我们在销售Ruby项目时得到的经验，运用像Ruby这些动态语言，和Thoughtworks整体的各种长处，十分配合。我们的长处是我们招聘到有才华的员工 ，而传统的IT部门是比较难吸引这种人员的。Ruby的一个理念是给一个有才华的开发人员提供一个高效的环境，而不是尝试去保护一个才能较低的开发者，让他不犯错。像Ruby的这种环境，给我们的开发人员们多一些空间去发挥他们真正的才能。
 
Ruby和我们用的敏捷开发过程，也配合得很好。敏捷开发的哲理是：开发软件，经常和用户一起复审，从而取得迅速的反馈。当一个开发环境越能提高生产力，你就可以越频密的和用户复审进度，那么敏捷开发的“检查与适应”这个步骤也会做得更好。

<ins>----</ins>
!!关于Ruby的问题

!!!Ruby是不是一个好的选择？
回看41个项目，最重要的问题应该就是：Ruby平台是一个正确的选择吗？要了解这个问题，最直截了当就是问
这些项目的技术主管，让他们回顾一下。

[http://martinfowler.com/articles/rubyAtThoughtWorks/hindsightPie.jpg]

图4：对于这个项目，Ruby平台是一个正确的选择吗？
 
在图4可以看到，觉得选择正确的占了大部分的票数，36对5。我们的技术主管们都是敢言的一群。对于一个错误的技术决定，他们一定会表达不满。所以，我觉得图4显示了Ruby这个平台是非常可行的。

我再深入的调查一下这5个有遗憾的项目。首先是这5个的其中4个项目里，技术主管们觉得Ruby不一定比其他的平台差。但是Ruby是一个没有那么普遍的技术，所以他们觉得Ruby需要为项目带来比其他技术更多的好处。如果Ruby和其他普遍的技术是一样的话，就不值得用一个不普遍的技术。另外，当要和其他一些和Ruby不大配合的技术进行集成时，其中4个项目也遇到了一些问题。比方说，.NET的工具当然和.NET技术集成得比较好。还有，其中2个项目也碰到了一些“政治”上的问题：在客户组织里的人反对使用Ruby或其他动态语言。其中情况比较坏的一个例子，整个IT组织都排斥Ruby，但是业务主办者却支持使用Ruby。
 
毫无疑问，当我问及在软件项目里使用Ruby有什么警报信号时，唯一清楚的答案就是环绕政治上的。在技术层面上，我们接受并鼓励在软件项目里使用Ruby。但是如果客户排斥Ruby，这就是警示我们要避免Ruby的最大信号。

!!!Ruby的生产力较高吗？

当人们问为什么要在一个项目里使用Ruby，最常见的答案就是为了提高生产力。有一个早期的报道，说根据某一个项目的评估，生产力的提高达到一个数量级。

很自然地我也向技术主管们提出了关于Ruby的生产力的问题 - Ruby有提高了生产力吗？如果有的话，提高了多少呢？我要他们和一个用上主流技术（Java或 .NET），并且用上他们所知的最高生产力方法的项目，作出比较。

[http://martinfowler.com/articles/rubyAtThoughtWorks/productivityBar.jpg]
图5：Ruby提高了多少生产力？（和你所知的、最好的主流技术工具比较）

正所谓“尽信书不如无书”，读者也应该抱着怀疑的态度去看这些结果。说到底，我们没有办法客观地测量软件生产力。这些只是我们技术主管们主观的，性质上的评估。（我没有收到所有项目的回复。）但是，这些结果还是说明Ruby真正的增进了生产力。
 

从人手调配的角度来看，也找到支持这个结论的理由。Scott Conley（我们Atlanta分公司的总经理）留意到当一个Ruby项目开始后，比起用其他技术的项目，通常需要多50%的人员来分析需求。

 
有一点我们注意到的，就是你不能期望项目一开始就有生产力的提升。据我听说过的几个案例，人们看到一个新Ruby团队的最初几个星期进展缓慢，而感到焦虑 -- 这是我称为“[改善峡谷|http://martinfowler.com/bliki/ImprovementRavine.html]”的后果。一个Ruby团队需要一段时间去熟悉这个平台的特性，所以这段时期进度会比预期慢。
 

“改善峡谷”是一个常见的现象，而通常缓和的方法是让一些有经验的人员加入团队。在这个情况，最重要的经验是对于类似Ruby、有元编程特性的动态语言的经验，而不一定是Ruby经验。正如Scott Conley所说：差异在于效率风险和交付风险。一个有动态语言经验，但没有Ruby经验的团队，一开始可能会比较慢（效率风险）。但是，一个没有动态语言经验的团队有可能生产出一些很棘手的代码，这样就会增加整体交付的风险。


!!!Ruby慢吗？
 

简短的回答：“是”。在网上搜一下的话，你会找到很多报道说，就算比起其他动态语言，Ruby也是像乌龟一样。
 
但是整体来说，Ruby的速度对我们的项目没有影响。我们大多数都是用Ruby来构建有数据库后台的网站。我这几十年探访过很多项目（Ruby或其他技术的），差不多每一个项目都有花时间去解决性能问题，而差不多每一次这些性能问题都来自数据库访问。他们通常花时间去优化SQL，而不是处理性的代码。因为多数应用的性能都是受I/O所限制，所以就算用一个慢的语言来处理逻辑，也不会对系统的整体性能有什么影响。

读者可能已经发现了我用了一些评论家们喜欢用的诡辩。尽管差不多每一个项目的性能瓶颈都是I/O，有些时候你真的会碰到例外的情况 -- 一个有趣的例子就是Mingle。Mingle在很多方面都不寻常。它的显示需要非常的动态，导致它不可以把网页缓存，也让它和大多数的web应用不一样。所以，它的性能瓶颈不是I/O，而为了达到好的性能，它对硬件的需求也出乎意料之外的高（一台4核，2GB的服务器来支持20-40人的团队）。

尽管如此，Mingle开发团队还是觉得Ruby是一个正确的选择。他们在短时间就开发了很多的功能，所以他们觉得相对于增加了的硬件负荷，利用Ruby而提高了生产力，还是划算的。和很多东西一样，这是一个硬件和生产力的取舍 -- 一个在计算机学里最古老的取舍。每一个开发团队都需要考虑哪一个较重要。幸好对Mingle来说，它的水平扩展性高（多加一些处理器，性能就可以按比例的提高）。硬件扩展性在这种情况下是很宝贵的，因为每一天硬件的价格都在下降。

我要重申一次，大部分的项目的性能瓶颈都是I/O，所以对它们来说，Ruby的速度都是无关痛痒的。Mingle只是一个例外，不属于主流。


!!Ruby代码库难懂吗？

我们常常听到一个对Ruby的担忧，说Ruby的动态类型，元编程，和开发工具的贫乏，会导致Ruby的代码难以理解。普遍来说，我们没有碰到这个问题。我听到的个案都说，因为Ruby比较精简，用比较少的代码就可以写好同样的功能，所以它比起其他主流语言，更容易保持代码的整洁。

话虽如此，我也需要强调我们这些个案的背景。Thoughtworks的开发人员的水平和能力一般较高，而且热衷于使用纪律性强的法门，如极限编程（Extreme Programming）。我们非常看重测试（在Ruby社区里也如是），而这些测试对于保持代码的整洁，起了很大的作用。所以，我不能肯定地说，在一些不同能力和纪律性的团队中，会不会看到相同的效果。（即使在其他主流语言里，在较好的开发工具和较为静态的环境下，大家都可以找到写得很恐怖的代码。至于一个写得差的Ruby代码库会不会更差，还有再讨论的余地。）
 
我们观察到开发团队们，对于元编程（meta-programming）的态度逐步的转变：

[http://martinfowler.com/articles/rubyAtThoughtWorks/metaprogramming.png]

图6：对于元编程的态度转变

* 吓人和坏的：人们对于元编程小心翼翼，不多用。
* 吓人和好的：人们开始看到元编程的好处，但还是用得不大习惯。
* 容易和好的：当人们用得越来越习惯时，他们就用得太多，也可能会让代码库变得复杂。
* 容易和坏的：人们对于元编程小心翼翼，但知道用得恰当的话，是很有好处的。

对这些技巧，我最喜欢打的一个比喻就是，它们好像处方药：小量是很有价值，但要确保不过量服食。

像很多东西一样，经验就是最好的帮手。它能帮助你快一点走完这图表的每一阶段。其中最重要的一点是，你将会看到这种采用的周期，特别是“过度使用”的一期。在学一个新的技巧时，通常都有一段时期会过度使用它，因为还没有越过那个界限时，很难知道那个界限是在何处。有一个不错的建议是设一个沙箱 -- 把代码库的一部分拨为试用元编程的范围。有了一个适当的沙箱，之后就比较容易去修改用得太多元编程的部分。


!!!Ruby是不是一个可行的平台？

以上的各个问题其实都是由一个问题来总括：Ruby（和Rails）对我们还有我们的客户，是不是一个可行的平台？目前为止，答案是一个很清楚的“是”。它明显地提高了生产力，让我们反应敏捷，产出好的软件，也更快的交付给客户。但是这不是说Ruby是灵丹妙药，各种情况都适用。挑选一个开发平台永远都不是一件容易的事情，特别是因为很多时候这是一个政治上的选择，而不是一个技术上的选择。但是总括来说，Ruby是一个不容忽视的选择，也值得让我们放这个工具在我们的工具箱里。


另外我要强调的是，你的选择不一定只有一个。我一向都鼓吹开发团队用主流语言（如Java/C#）的同时，也用一些脚本语言来做一些支持性的任务。Ruby是一个优秀的选择，而我们也观察到这种混合应用有所增长。当JVM和CLR对这些动态语言的支持越来越好，我们也会看到愈来愈多的机会，让我们混合使用具有不同优点的语言 -- Neal Ford 把它称为&quot;多语言编程&quot;（[Polyglot Programming|http://memeagora.blogspot.com/2006/12/polyglot-programming.html]）。

<ins>----</ins>
!!关于开发的一些提示
 
在这最后一章，我会介绍一些我们学到的教训。
 

!!!测试ActiveRecord

当我们一开始使用Ruby，就已经开始争议，在运用Rails的数据库层ActiveRecord时，怎样去把测试组织起来才是最好。基本的问题是，一般的商业性应用软件，性能瓶颈都在于数据库。我们发现利用[Test Double|http://martinfowler.com/bliki/TestDouble.html]可以大大加快测试。对我们这种侧重于测试的开发过程来说，拥有快的测试是非常重要的。Kent Beck建议一个基本的提交构建（commit build）应该需时10分钟以下。我们大部分的项目都能达到这个时限，而使用数据库的double是重要的一环。
 

ActiveRecord的问题在于它混合了数据库访问和商业逻辑在一起，所以要作一个数据库的double比较困难。我们Mingle团队选择接受Rails和数据库是紧密地绑在一起的，让所有提交测试都访问数据库。
 
我们Atlanta和Jersey团队却持相反的意见。Ruby的一个很有用的特性就是能让你在运行时间，把一个方法重新定义。利用这个特性，你可以拿一个ActiveRecord的类，重新把它的数据库访问方法定义为stub。这两个团队创建了[unitrecord|http://github.com/dan-manges/unit-record]这个gem来干这个事情。


在这3年里，我们还没有看到这场争议的哪一方占优。Mingle团队在8分钟里跑几千个测试，执行时会访问一个真实的postgres数据库。（他们把测试并行化，来充分使用多个核。）Atlanta和Jersey团队却觉得他们能利用stub，把提交测试减至2分钟，是有价值的。这情况下，他们是对简单的、访问数据库的测试，和利用stub、较快的测试，作出取舍 。

尽管双方对自己的立场普遍表示满意，stub的应用导致了另一个问题。当团队对方法stub（method stubbing）越来越熟悉，他们也用得越来越多，跌进了一个过度使用的局面：在单元测试里，除了被测试的方法之外，其他的每一个方法都被stub。这里的问题，和用Test Double一样，是可能让测试变得脆弱。当你修改应用软件的行为时，你也需要修改很多模拟旧行为的double。在过度使用之后，这两个团队也多用了一些Rails风格的、直接访问数据库的功能测试。

!!!ActiveRecord的“漏洞”

在项目里一个常见的现象是人们花时间写SQL。对于隐藏数据库访问的代码，ActiveRecord干得不错，但它不能全部隐藏 -- 就是说它有一些抽象化的漏洞。所以，开发人员都要花一些时间直接的写SQL。

这个漏洞在对象关系映射（ORM，object/relational mapping）框架里很常见。差不多每一次我去和项目里的开发人员聊的时候，他们都说80-90%的时候ORM框架可以把SQL隐藏起来，但需要花一些时间去调SQL，让它达到可接受的性能。所以在这方面，ActiveRecord和其他ORM框架没有区别。

一个我听到的评语说，ActiveRecord的抽象化可以让你清脆的脱离它。和DHH谈的时候，他认为使用关系数据库的开发者应该懂得SQL。ActiveRecord把常用的场景简单化，但是当你开始进入复杂的场景时，它就期望你直接用SQL。

我认为这些漏洞不至于让我们不使用这些ORM框架。这些ORM框架的要旨是把常见的东西变得容易，从而提高生产力。它让团队可以集中处理一些真正重要的个案。但如果一个团队以为这些框架是点水不漏，而不花力气在SQL上，便会是一个毛病。这个毛病虽然常见，但不是一个避免不去用ORM框架的理由。当团队正确地使用它们时，会带来真正的益处。


!!!长执行时间的请求


另一个常见的问题是当应用软件要执行一个需时长的请求时，处理不当。如果实现得不好，会让处理这个web请求的handler很长时间没有反应。


这个问题是在人机界面方面很普遍，而且也有一个普遍的解决方法 -- 把任务交给一个背景运行的过程或线程。任何开发过桌面应用的人都会觉得很熟悉。但是有时候如果开发者把切换和通信做得不好，也会碰到麻烦。

一个我觉得较好的办法，而幸好我的ThoughtWorks同事们也同意，就是使用一个actor。在这个模型里，web请求的handler把需时长的请求包装为一个命令（command），然后放进队列（queue）内。在背景运行的actor就监察着这个queue，从queue中提出并且执行这个命令。当它把这个命令执行完了，就通知前台界面的actor。通常这个queue一开始会是数据库的一个表，之后如有需要的话，再把它改为一个消息队列（message queue）。

和ActiveRecord的漏洞一样，我提起这个不是因为它是Rails里特有的问题；我们在各种应用也会看到同样的问题。值得在这里带出是因为用Rails的人们往往很容易忘了有这样的情况发生，也忘了有这样的模式去解决。我们发现Rails把web开发中重复又重复的环节变得简易和快，但是复杂的环节是仍然存在的。

!!!部署

Rails应用很容易建起，可惜部署比较麻烦。最常见的是用几个mongrel web服务器，但是配置比较繁琐。Ruby其他方面通常用起来很容易、很顺利，Rails部署和它们一比较，真的相形见绌。

现在大家都认为Phusion Passenger让部署变得容易，而且是用MRI时最好的部署方法。


我们也很提倡用JRuby来部署。JRuby让大家可以使用标准的Java stack，所以在很多公司里的环境内也能容易地使用。Mingle也是用这个方法让客户能够很容易地安装。Mingle团队所有的开发都是在MRI上做的，但部署在JRuby上。MRI启动较快，开发起来也较快。（JRuby需要启动JVM，所以明显地比较慢）。

!!!控制Gems


Ruby包括了一个软件包管理系统叫RubyGems，能让你容易地安装和升级软件库。Rails也有plugins来做差不多的事情。它们都是好的工具，但也很容易让团队在不同的机器上配置了不同版本的库，而导致混乱。


有好几个方法来对付这个问题。第一，可以把所有的库的源代码都放进版本管理系统里。那么，一个简单的checkout就可以给你全部正确版本的库。第二，可以用一个脚本去下载和激活每一个库的正确版本。这个脚本就需要放在版本管理系统里。


同样道理，大多的团队都把Rails的源代码冻结。这样他们就可以直接在Rails上编补钉来修bug或其他问题。之后，这些补丁亦可以发给Rails Core团队。现在像git这种分布性版本管理系统（distributed version control systems)让这个流程更加轻松。比起我们以前要把Java application server 反编译（decompile）之后再补丁，真的容易得多了。


!!!订下升级的时间表


一般来说，Ruby，特别是Rails，都是日新月异。Rails也常常升级，频密地造出包含很多新功能的新版本。我们经验所得，要在项目计划时，订下Rails升级的时间表。虽然升级需要付出的努力比其他平台大，但值得高兴的是新功能源源不绝。


!!!在Windows上开发

Ruby生于Unix世界里，而大多数用Ruby的人在目录路径里，都是用前斜线符号（forward slash）。在Windows上运行、部署、和开发Ruby是完全可能的，但是比较刁钻。我们一般建议用一个unix平台做开发。我们都偏爱Mac，但也有很多人都用其他的开源版本的Unix。

我们希望Iron Ruby会改变这个现状。能够在Unix，JVM，或CLR上部署Ruby，将会是一件很好的事情。这个确然会把Ruby定位为可以在各平台运行的一个灵活的选择。这个也会帮助我们在我们的.NET项目里使用Ruby作为脚本语言，和主流的.NET语言一并使用。


!!!鸣谢

如果没有众多同事的合作，这篇文章我一定写不出来。比起以前，这一次更加如是。虽然我在自己的工作上用了Ruby已经很多年，但是一个人堆砌一个个人网站，和我们为客户开发的网上应用软件，毕竟是有很大的区别。我很感谢那么多的同事献出时间，给我很多的资料，让我可以真正的评估Ruby的价值。

和其他Ruby用户一样，我们也很感谢Ruby和Rails社区。与任何开源项目一样，社区的作用是非常的重要，所以对所有的Ruby黑客和 Rubyist们，我们Thoughtworks要说一声：ありがとうございました.

!!!主要版本修改

2009年6月11日：第一次在martinfowler.com上发表
2009年6月3日：ThoughtWorks内部评审的草稿

</pre></description>
	</item>

	<item>
	  <title>Ruby at ThoughtWorks</title>
	  <pubDate>Sun, 26 Jul 2009 17:51:40 -0400</pubDate>
	  <link>http://rickylui.com/lionwiki/index.php?page=Ruby+at+ThoughtWorks</link>
	  <description><pre id="diff">原文：http://martinfowler.com/articles/rubyAtThoughtWorks.html 


''Thoughtworks 从2006年就开始在一些项目的生产环境里用Ruby。到2008年底为止，我们已经作了41个Ruby项目。为了准备一个QCON的演讲，我对这些项目作了一个调查，总结我们吸取了的经验。我会讨论一些常见的问题，例如Ruby的生产力，速度和可维护性。到现在为止，我们的结论是：对于多种形式的应用软件，Ruby都是一个可行的平台 - 尤其是用Ruby On Rails开发web应用。我也会说一下技术上的教训，还有一些对于测试ActiveRecord的感想。''

我的雇主ThoughtWorks是一家交付软件的公司。我们替客户开发软件，也开发我们自己的软件产品。我们的其中一个理念是对各种开发平台都持着开放的思想，因此我们可以为不同类型的客户都选择一个最合适的平台。 2000年当我加入Thoughtworks时，Java是我们主要的开发平台。之后我们开始用.NET，到2005年左右我们大部分的工作都是建于在这两个平台上。

与此同时，有几个同事开始用LAMP（特别是Ruby）和脚本语言。Ruby On Rails 这个web 框架的出现，让Ruby鲤跃龙门。2006年，我们开始在一些项目里使用Ruby平台。到了2009年的今天，Ruby平台占了我们一定的工作量，虽然没有Java或C#那么多。


在这3年里，我们掌握了不少Ruby的实践经验。2009年初，我被邀请去QCON作一个关于我们Ruby经验的演讲。为了准备这个演讲，我对这些项目作了详细的调查，而我们的Ruby专家们也分享了他们的意见和经验。为了写本文我花了比预期长的时间，但毕竟也总算完成了。

我把本文分为3个部分。第一部分我会看看我们Thoughtworks的各个Ruby项目的纲要，让读者对我们做过什么项目，有一个笼统的概念。之后，我会带出关于Ruby的几个常见问题，并根据我们的经验作出回答。最后，我会讨论一下我们对使用Ruby学到的一些教训。


!!我们各项目的外貌

从2006到2008年，Thoughtworks参与了41个Ruby项目。我把“Ruby项目”界定为一个以Ruby作为主要语言的项目。在其他项目，Ruby也有出现，例如最近有不少Java项目也使用了Ruby，将构建自动化，或作功能性测试。差不多所有的Ruby项目都同时用Rails，大部分都是web项目，所以Rails起码和Ruby有着同样的重要性。

[http://martinfowler.com/articles/rubyAtThoughtWorks/projectScatter.png]

图1：2006至2008年Thoughtworks的Ruby项目里，各团队的高峰人数和项目为期的散布图

图1展示了我们各Ruby项目的大小。这里的人数（headcount）是团队最高峰时期的人数（包括Thoughtworks和客户员工；开发人员，项目经理，分析师，等等）。为期是Thoughtworks参与在项目里的时间。

表面上看，Ruby项目比起其他项目，规模比较小，而为期也比较短。有点遗憾的是我没有其他非Ruby项目的数据来作比较。但是肯定的说，我们可以看到大多数Ruby项目都是在20人以下，1年之内。
 
当中有几个项目比较突出。显然我们最大的项目是在此称为Atlanta的项目，高峰人数超过40人。另一个为期长而人数多的项目是Jersey项目。这两个项目有一些关联：基于人手的调配，我们很多比较有经验的Ruby人员都在这两个项目里工作过。

第三个值得一提的项目是Mingle。它是一个Thoughtworks Studios的软件产品，所以比起客户的项目，我们可以更加畅所欲言。Mingle为期比较长，而且是一个跨国的项目：从澳大利亚开始，搬到北京，现时分布在北京和旧金山两地。

  
[http://martinfowler.com/articles/rubyAtThoughtWorks/yearStrip.png]

图2：每年各项目的人力投入-带状图
 
图2换了一个不同的角度，来看我们每年对各项目的投入。每一点代表在那一年，对某一个项目投入的人力。这图可以显示了我们过去三年以来，Ruby项目的增长。

 
[http://martinfowler.com/articles/rubyAtThoughtWorks/countryStrip.png]

图3：每个国家的人力投入-带状图

大家用图3来看看我们在每个国家的Ruby项目。我没有尝试去特别处理一些在多地开发，或者是迁移过的项目，所以这图的数据比较粗略。（比如说，我把Mingle归纳为中国的项目，尽管它的历史比较复杂。）

我们可以看到美国市场对于Ruby的工作最感兴趣。在印度也有不少 -- 我们的第一个Ruby项目就是在Bangalore开始。在英国，我们的客户对Ruby的兴趣比较低。这个可能是反映了在Thoughtworks内，领头用Ruby的开发者大多是在美国；另外英国市场对Ruby抱有一定的怀疑。说回我们印度办公室对Ruby的接受程度，是令人鼓舞的。因为传统上，印度对于新技术的引入比较慢，但是我们印度办公室不一样。看来我们公司放在印度办公室的努力，没有白费。
 
根据我们在销售Ruby项目时得到的经验，运用像Ruby这些动态语言，和Thoughtworks整体的各种长处，十分配合。我们的长处是我们招聘到有才华的员工 ，而传统的IT部门是比较难吸引这种人员的。Ruby的一个理念是给一个有才华的开发人员提供一个高效的环境，而不是尝试去保护一个才能较低的开发者，让他不犯错。像Ruby的这种环境，给我们的开发人员们多一些空间去发挥他们真正的才能。
 
Ruby和我们用的敏捷开发过程，也配合得很好。敏捷开发的哲理是：开发软件，经常和用户一起复审，从而取得迅速的反馈。当一个开发环境越能提高生产力，你就可以越频密的和用户复审进度，那么敏捷开发的“检查与适应”这个步骤也会做得更好。


!!关于Ruby的问题

!!!Ruby是不是一个好的选择？
回看41个项目，最重要的问题应该就是：Ruby平台是一个正确的选择吗？要了解这个问题，最直截了当就是问
这些项目的技术主管，让他们回顾一下。

[http://martinfowler.com/articles/rubyAtThoughtWorks/hindsightPie.jpg]

图4：对于这个项目，Ruby平台是一个正确的选择吗？
 
在图4可以看到，觉得选择正确的占了大部分的票数，36对5。我们的技术主管们都是敢言的一群。对于一个错误的技术决定，他们一定会表达不满。所以，我觉得图4显示了Ruby这个平台是非常可行的。

我再深入的调查一下这5个有遗憾的项目。首先是这5个的其中4个项目里，技术主管们觉得Ruby不一定比其他的平台差。但是Ruby是一个没有那么普遍的技术，所以他们觉得Ruby需要为项目带来比其他技术更多的好处。如果Ruby和其他普遍的技术是一样的话，就不值得用一个不普遍的技术。另外，当要和其他一些和Ruby不大配合的技术进行集成时，其中4个项目也遇到了一些问题。比方说，.NET的工具当然和.NET技术集成得比较好。还有，其中2个项目也碰到了一些“政治”上的问题：在客户组织里的人反对使用Ruby或其他动态语言。其中情况比较坏的一个例子，整个IT组织都排斥Ruby，但是业务主办者却支持使用Ruby。
 
毫无疑问，当我问及在软件项目里使用Ruby有什么警报信号时，唯一清楚的答案就是环绕政治上的。在技术层面上，我们接受并鼓励在软件项目里使用Ruby。但是如果客户排斥Ruby，这就是警示我们要避免Ruby的最大信号。

!!!Ruby的生产力较高吗？

当人们问为什么要在一个项目里使用Ruby，最常见的答案就是为了提高生产力。有一个早期的报道，说根据某一个项目的评估，生产力的提高达到一个数量级。

很自然地我也向技术主管们提出了关于Ruby的生产力的问题 - Ruby有提高了生产力吗？如果有的话，提高了多少呢？我要他们和一个用上主流技术（Java或 .NET），并且用上他们所知的最高生产力方法的项目，作出比较。

[http://martinfowler.com/articles/rubyAtThoughtWorks/productivityBar.jpg]
图5：Ruby提高了多少生产力？（和你所知的、最好的主流技术工具比较）

正所谓“尽信书不如无书”，读者也应该抱着怀疑的态度去看这些结果。说到底，我们没有办法客观地测量软件生产力。这些只是我们技术主管们主观的，性质上的评估。（我没有收到所有项目的回复。）但是，这些结果还是说明Ruby真正的增进了生产力。
 

从人手调配的角度来看，也找到支持这个结论的理由。Scott Conley（我们Atlanta分公司的总经理）留意到当一个Ruby项目开始后，比起用其他技术的项目，通常需要多50%的人员来分析需求。

 
有一点我们注意到的，就是你不能期望项目一开始就有生产力的提升。据我听说过的几个案例，人们看到一个新Ruby团队的最初几个星期进展缓慢，而感到焦虑 -- <del>这是我称为“改善峡谷”的后果。一个Ruby团队需要一段时间去熟悉这个平台的特性，所以这段时期进度会比预期慢。</del><ins>这是我称为“[改善峡谷|http://martinfowler.com/bliki/ImprovementRavine.html]”的后果。一个Ruby团队需要一段时间去熟悉这个平台的特性，所以这段时期进度会比预期慢。</ins>
 

“改善峡谷”是一个常见的现象，而通常缓和的方法是让一些有经验的人员加入团队。在这个情况，最重要的经验是对于类似Ruby、有元编程特性的动态语言的经验，而不一定是Ruby经验。正如Scott Conley所说：差异在于效率风险和交付风险。一个有动态语言经验，但没有Ruby经验的团队，一开始可能会比较慢（效率风险）。但是，一个没有动态语言经验的团队有可能生产出一些很棘手的代码，这样就会增加整体交付的风险。


!!!Ruby慢吗？
 

简短的回答：“是”。在网上搜一下的话，你会找到很多报道说，就算比起其他动态语言，Ruby也是像乌龟一样。
 
但是整体来说，Ruby的速度对我们的项目没有影响。我们大多数都是用Ruby来构建有数据库后台的网站。我这几十年探访过很多项目（Ruby或其他技术的），差不多每一个项目都有花时间去解决性能问题，而差不多每一次这些性能问题都来自数据库访问。他们通常花时间去优化SQL，而不是处理性的代码。因为多数应用的性能都是受I/O所限制，所以就算用一个慢的语言来处理逻辑，也不会对系统的整体性能有什么影响。

读者可能已经发现了我用了一些评论家们喜欢用的诡辩。尽管差不多每一个项目的性能瓶颈都是I/O，有些时候你真的会碰到例外的情况 -- 一个有趣的例子就是Mingle。Mingle在很多方面都不寻常。它的显示需要非常的动态，导致它不可以把网页缓存，也让它和大多数的web应用不一样。所以，它的性能瓶颈不是I/O，而为了达到好的性能，它对硬件的需求也出乎意料之外的高（一台4核，2GB的服务器来支持20-40人的团队）。

尽管如此，Mingle开发团队还是觉得Ruby是一个正确的选择。他们在短时间就开发了很多的功能，所以他们觉得相对于增加了的硬件负荷，利用Ruby而提高了生产力，还是划算的。和很多东西一样，这是一个硬件和生产力的取舍 -- 一个在计算机学里最古老的取舍。每一个开发团队都需要考虑哪一个较重要。幸好对Mingle来说，它的水平扩展性高（多加一些处理器，性能就可以按比例的提高）。硬件扩展性在这种情况下是很宝贵的，因为每一天硬件的价格都在下降。

我要重申一次，大部分的项目的性能瓶颈都是I/O，所以对它们来说，Ruby的速度都是无关痛痒的。Mingle只是一个例外，不属于主流。


!!Ruby代码库难懂吗？

我们常常听到一个对Ruby的担忧，说Ruby的动态类型，元编程，和开发工具的贫乏，会导致Ruby的代码难以理解。普遍来说，我们没有碰到这个问题。我听到的个案都说，因为Ruby比较精简，用比较少的代码就可以写好同样的功能，所以它比起其他主流语言，更容易保持代码的整洁。

话虽如此，我也需要强调我们这些个案的背景。Thoughtworks的开发人员的水平和能力一般较高，而且热衷于使用纪律性强的法门，如极限编程（Extreme Programming）。我们非常看重测试（在Ruby社区里也如是），而这些测试对于保持代码的整洁，起了很大的作用。所以，我不能肯定地说，在一些不同能力和纪律性的团队中，会不会看到相同的效果。（即使在其他主流语言里，在较好的开发工具和较为静态的环境下，大家都可以找到写得很恐怖的代码。至于一个写得差的Ruby代码库会不会更差，还有再讨论的余地。）
 
我们观察到开发团队们，对于元编程（meta-programming）的态度逐步的转变：

[http://martinfowler.com/articles/rubyAtThoughtWorks/metaprogramming.png]

图6：对于元编程的态度转变

* 吓人和坏的：人们对于元编程小心翼翼，不多用。
* 吓人和好的：人们开始看到元编程的好处，但还是用得不大习惯。
* 容易和好的：当人们用得越来越习惯时，他们就用得太多，也可能会让代码库变得复杂。
* 容易和坏的：人们对于元编程小心翼翼，但知道用得恰当的话，是很有好处的。

对这些技巧，我最喜欢打的一个比喻就是，它们好像处方药：小量是很有价值，但要确保不过量服食。

像很多东西一样，经验就是最好的帮手。它能帮助你快一点走完这图表的每一阶段。其中最重要的一点是，你将会看到这种采用的周期，特别是“过度使用”的一期。在学一个新的技巧时，通常都有一段时期会过度使用它，因为还没有越过那个界限时，很难知道那个界限是在何处。有一个不错的建议是设一个沙箱 -- 把代码库的一部分拨为试用元编程的范围。有了一个适当的沙箱，之后就比较容易去修改用得太多元编程的部分。


!!!Ruby是不是一个可行的平台？

以上的各个问题其实都是由一个问题来总括：Ruby（和Rails）对我们还有我们的客户，是不是一个可行的平台？目前为止，答案是一个很清楚的“是”。它明显地提高了生产力，让我们反应敏捷，产出好的软件，也更快的交付给客户。但是这不是说Ruby是灵丹妙药，各种情况都适用。挑选一个开发平台永远都不是一件容易的事情，特别是因为很多时候这是一个政治上的选择，而不是一个技术上的选择。但是总括来说，Ruby是一个不容忽视的选择，也值得让我们放这个工具在我们的工具箱里。


另外我要强调的是，你的选择不一定只有一个。我一向都鼓吹开发团队用主流语言（如Java/C#）的同时，也用一些脚本语言来做一些支持性的任务。Ruby是一个优秀的选择，而我们也观察到这种混合应用有所增长。当JVM和CLR对这些动态语言的支持越来越好，我们也会看到愈来愈多的机会，让我们混合使用具有不同优点的语言 -- Neal Ford <del>把它称为&quot;多语言编程&quot;（Polyglot Programming）。</del><ins>把它称为&quot;多语言编程&quot;（[Polyglot Programming|http://memeagora.blogspot.com/2006/12/polyglot-programming.html]）。</ins>

!!关于开发的一些提示
 
在这最后一章，我会介绍一些我们学到的教训。
 

!!!测试ActiveRecord

<del>当我们一开始使用Ruby，就已经开始争议，在运用Rails的数据库层ActiveRecord时，怎样去把测试组织起来才是最好。基本的问题是，一般的商业性应用软件，性能瓶颈都在于数据库。我们发现利用Test Double可以大大加快测试。对我们这种侧重于测试的开发过程来说，拥有快的测试是非常重要的。Kent</del><ins>当我们一开始使用Ruby，就已经开始争议，在运用Rails的数据库层ActiveRecord时，怎样去把测试组织起来才是最好。基本的问题是，一般的商业性应用软件，性能瓶颈都在于数据库。我们发现利用[Test Double|http://martinfowler.com/bliki/TestDouble.html]可以大大加快测试。对我们这种侧重于测试的开发过程来说，拥有快的测试是非常重要的。Kent</ins> Beck建议一个基本的提交构建（commit build）应该需时10分钟以下。我们大部分的项目都能达到这个时限，而使用数据库的double是重要的一环。
 

ActiveRecord的问题在于它混合了数据库访问和商业逻辑在一起，所以要作一个数据库的double比较困难。我们Mingle团队选择接受Rails和数据库是紧密地绑在一起的，让所有提交测试都访问数据库。
 
<del>我们Atlanta和Jersey团队却持相反的意见。Ruby的一个很有用的特性就是能让你在运行时间，把一个方法重新定义。利用这个特性，你可以拿一个ActiveRecord的类，重新把它的数据库访问方法定义为stub。这两个团队创建了UnitRecord这个gem来干这个事情。</del><ins>我们Atlanta和Jersey团队却持相反的意见。Ruby的一个很有用的特性就是能让你在运行时间，把一个方法重新定义。利用这个特性，你可以拿一个ActiveRecord的类，重新把它的数据库访问方法定义为stub。这两个团队创建了[unitrecord|http://github.com/dan-manges/unit-record]这个gem来干这个事情。</ins>


在这3年里，我们还没有看到这场争议的哪一方占优。Mingle团队在8分钟里跑几千个测试，执行时会访问一个真实的postgres数据库。（他们把测试并行化，来充分使用多个核。）Atlanta和Jersey团队却觉得他们能利用stub，把提交测试减至2分钟，是有价值的。这情况下，他们是对简单的、访问数据库的测试，和利用stub、较快的测试，作出取舍 。

尽管双方对自己的立场普遍表示满意，stub的应用导致了另一个问题。当团队对方法stub（method stubbing）越来越熟悉，他们也用得越来越多，跌进了一个过度使用的局面：在单元测试里，除了被测试的方法之外，其他的每一个方法都被stub。这里的问题，和用Test Double一样，是可能让测试变得脆弱。当你修改应用软件的行为时，你也需要修改很多模拟旧行为的double。在过度使用之后，这两个团队也多用了一些Rails风格的、直接访问数据库的功能测试。

!!!ActiveRecord的“漏洞”

在项目里一个常见的现象是人们花时间写SQL。对于隐藏数据库访问的代码，ActiveRecord干得不错，但它不能全部隐藏 -- 就是说它有一些抽象化的漏洞。所以，开发人员都要花一些时间直接的写SQL。

这个漏洞在对象关系映射（ORM，object/relational mapping）框架里很常见。差不多每一次我去和项目里的开发人员聊的时候，他们都说80-90%的时候ORM框架可以把SQL隐藏起来，但需要花一些时间去调SQL，让它达到可接受的性能。所以在这方面，ActiveRecord和其他ORM框架没有区别。

一个我听到的评语说，ActiveRecord的抽象化可以让你清脆的脱离它。和DHH谈的时候，他认为使用关系数据库的开发者应该懂得SQL。ActiveRecord把常用的场景简单化，但是当你开始进入复杂的场景时，它就期望你直接用SQL。

我认为这些漏洞不至于让我们不使用这些ORM框架。这些ORM框架的要旨是把常见的东西变得容易，从而提高生产力。它让团队可以集中处理一些真正重要的个案。但如果一个团队以为这些框架是点水不漏，而不花力气在SQL上，便会是一个毛病。这个毛病虽然常见，但不是一个避免不去用ORM框架的理由。当团队正确地使用它们时，会带来真正的益处。


!!!长执行时间的请求


另一个常见的问题是当应用软件要执行一个需时长的请求时，处理不当。如果实现得不好，会让处理这个web请求的handler很长时间没有反应。


这个问题是在人机界面方面很普遍，而且也有一个普遍的解决方法 -- 把任务交给一个背景运行的过程或线程。任何开发过桌面应用的人都会觉得很熟悉。但是有时候如果开发者把切换和通信做得不好，也会碰到麻烦。

一个我觉得较好的办法，而幸好我的ThoughtWorks同事们也同意，就是使用一个actor。在这个模型里，web请求的handler把需时长的请求包装为一个命令（command），然后放进队列（queue）内。在背景运行的actor就监察着这个queue，从queue中提出并且执行这个命令。当它把这个命令执行完了，就通知前台界面的actor。通常这个queue一开始会是数据库的一个表，之后如有需要的话，再把它改为一个消息队列（message queue）。

和ActiveRecord的漏洞一样，我提起这个不是因为它是Rails里特有的问题；我们在各种应用也会看到同样的问题。值得在这里带出是因为用Rails的人们往往很容易忘了有这样的情况发生，也忘了有这样的模式去解决。我们发现Rails把web开发中重复又重复的环节变得简易和快，但是复杂的环节是仍然存在的。

!!!部署

Rails应用很容易建起，可惜部署比较麻烦。最常见的是用几个mongrel web服务器，但是配置比较繁琐。Ruby其他方面通常用起来很容易、很顺利，Rails部署和它们一比较，真的相形见绌。

现在大家都认为Phusion Passenger让部署变得容易，而且是用MRI时最好的部署方法。


我们也很提倡用JRuby来部署。JRuby让大家可以使用标准的Java stack，所以在很多公司里的环境内也能容易地使用。Mingle也是用这个方法让客户能够很容易地安装。Mingle团队所有的开发都是在MRI上做的，但部署在JRuby上。MRI启动较快，开发起来也较快。（JRuby需要启动JVM，所以明显地比较慢）。

!!!控制Gems


Ruby包括了一个软件包管理系统叫RubyGems，能让你容易地安装和升级软件库。Rails也有plugins来做差不多的事情。它们都是好的工具，但也很容易让团队在不同的机器上配置了不同版本的库，而导致混乱。


有好几个方法来对付这个问题。第一，可以把所有的库的源代码都放进版本管理系统里。那么，一个简单的checkout就可以给你全部正确版本的库。第二，可以用一个脚本去下载和激活每一个库的正确版本。这个脚本就需要放在版本管理系统里。


同样道理，大多的团队都把Rails的源代码冻结。这样他们就可以直接在Rails上编补钉来修bug或其他问题。之后，这些补丁亦可以发给Rails Core团队。现在像git这种分布性版本管理系统（distributed version control systems)让这个流程更加轻松。比起我们以前要把Java application server 反编译（decompile）之后再补丁，真的容易得多了。


!!!订下升级的时间表


一般来说，Ruby，特别是Rails，都是日新月异。Rails也常常升级，频密地造出包含很多新功能的新版本。我们经验所得，要在项目计划时，订下Rails升级的时间表。虽然升级需要付出的努力比其他平台大，但值得高兴的是新功能源源不绝。


!!!在Windows上开发

Ruby生于Unix世界里，而大多数用Ruby的人在目录路径里，都是用前斜线符号（forward slash）。在Windows上运行、部署、和开发Ruby是完全可能的，但是比较刁钻。我们一般建议用一个unix平台做开发。我们都偏爱Mac，但也有很多人都用其他的开源版本的Unix。

我们希望Iron Ruby会改变这个现状。能够在Unix，JVM，或CLR上部署Ruby，将会是一件很好的事情。这个确然会把Ruby定位为可以在各平台运行的一个灵活的选择。这个也会帮助我们在我们的.NET项目里使用Ruby作为脚本语言，和主流的.NET语言一并使用。


!!!鸣谢

如果没有众多同事的合作，这篇文章我一定写不出来。比起以前，这一次更加如是。虽然我在自己的工作上用了Ruby已经很多年，但是一个人堆砌一个个人网站，和我们为客户开发的网上应用软件，毕竟是有很大的区别。我很感谢那么多的同事献出时间，给我很多的资料，让我可以真正的评估Ruby的价值。

和其他Ruby用户一样，我们也很感谢Ruby和Rails社区。与任何开源项目一样，社区的作用是非常的重要，所以对所有的Ruby黑客和 Rubyist们，我们Thoughtworks要说一声：ありがとうございました.

!!!主要版本修改

2009年6月11日：第一次在martinfowler.com上发表
2009年6月3日：ThoughtWorks内部评审的草稿

</pre></description>
	</item>

	<item>
	  <title>在Thoughtworks里的Ruby</title>
	  <pubDate>Sun, 26 Jul 2009 17:43:47 -0400</pubDate>
	  <link>http://rickylui.com/lionwiki/index.php?page=%E5%9C%A8Thoughtworks%E9%87%8C%E7%9A%84Ruby</link>
	  <description><pre id="diff"><del>在Thoughtworks里的Ruby</del><ins>原文：http://martinfowler.com/articles/rubyAtThoughtWorks.html </ins>


<del>Thoughtworks</del><ins>''Thoughtworks</ins> 从2006年就开始在一些项目的生产环境里用Ruby。到2008年底为止，我们已经作了41个Ruby项目。为了准备一个QCON的演讲，我对这些项目作了一个调查，总结我们吸取了的经验。我会讨论一些常见的问题，例如Ruby的生产力，速度和可维护性。到现在为止，我们的结论是：对于多种形式的应用软件，Ruby都是一个可行的平台 - 尤其是用Ruby On <del>Rails开发web应用。我也会说一下技术上的教训，还有一些对于测试ActiveRecord的感想。</del><ins>Rails开发web应用。我也会说一下技术上的教训，还有一些对于测试ActiveRecord的感想。''</ins>

我的雇主ThoughtWorks是一家交付软件的公司。我们替客户开发软件，也开发我们自己的软件产品。我们的其中一个理念是对各种开发平台都持着开放的思想，因此我们可以为不同类型的客户都选择一个最合适的平台。 2000年当我加入Thoughtworks时，Java是我们主要的开发平台。之后我们开始用.NET，到2005年左右我们大部分的工作都是建于在这两个平台上。

与此同时，有几个同事开始用LAMP（特别是Ruby）和脚本语言。Ruby On Rails 这个web 框架的出现，让Ruby鲤跃龙门。2006年，我们开始在一些项目里使用Ruby平台。到了2009年的今天，Ruby平台占了我们一定的工作量，虽然没有Java或C#那么多。


在这3年里，我们掌握了不少Ruby的实践经验。2009年初，我被邀请去QCON作一个关于我们Ruby经验的演讲。为了准备这个演讲，我对这些项目作了详细的调查，而我们的Ruby专家们也分享了他们的意见和经验。为了写本文我花了比预期长的时间，但毕竟也总算完成了。

我把本文分为3个部分。第一部分我会看看我们Thoughtworks的各个Ruby项目的纲要，让读者对我们做过什么项目，有一个笼统的概念。之后，我会带出关于Ruby的几个常见问题，并根据我们的经验作出回答。最后，我会讨论一下我们对使用Ruby学到的一些教训。


<del>我们各项目的外貌</del><ins>!!我们各项目的外貌</ins>

从2006到2008年，Thoughtworks参与了41个Ruby项目。我把“Ruby项目”界定为一个以Ruby作为主要语言的项目。在其他项目，Ruby也有出现，例如最近有不少Java项目也使用了Ruby，将构建自动化，或作功能性测试。差不多所有的Ruby项目都同时用Rails，大部分都是web项目，所以Rails起码和Ruby有着同样的重要性。

[http://martinfowler.com/articles/rubyAtThoughtWorks/projectScatter.png]

图1：2006至2008年Thoughtworks的Ruby项目里，各团队的高峰人数和项目为期的散布图

图1展示了我们各Ruby项目的大小。这里的人数（headcount）是团队最高峰时期的人数（包括Thoughtworks和客户员工；开发人员，项目经理，分析师，等等）。为期是Thoughtworks参与在项目里的时间。

表面上看，Ruby项目比起其他项目，规模比较小，而为期也比较短。有点遗憾的是我没有其他非Ruby项目的数据来作比较。但是肯定的说，我们可以看到大多数Ruby项目都是在20人以下，1年之内。
 
当中有几个项目比较突出。显然我们最大的项目是在此称为Atlanta的项目，高峰人数超过40人。另一个为期长而人数多的项目是Jersey项目。这两个项目有一些关联：基于人手的调配，我们很多比较有经验的Ruby人员都在这两个项目里工作过。
<del>
 </del>

第三个值得一提的项目是Mingle。它是一个Thoughtworks Studios的软件产品，所以比起客户的项目，我们可以更加畅所欲言。Mingle为期比较长，而且是一个跨国的项目：从澳大利亚开始，搬到北京，现时分布在北京和旧金山两地。

  
[http://martinfowler.com/articles/rubyAtThoughtWorks/yearStrip.png]

图2：每年各项目的人力投入-带状图
 
图2换了一个不同的角度，来看我们每年对各项目的投入。每一点代表在那一年，对某一个项目投入的人力。这图可以显示了我们过去三年以来，Ruby项目的增长。

 
[http://martinfowler.com/articles/rubyAtThoughtWorks/countryStrip.png]

图3：每个国家的人力投入-带状图

大家用图3来看看我们在每个国家的Ruby项目。我没有尝试去特别处理一些在多地开发，或者是迁移过的项目，所以这图的数据比较粗略。（比如说，我把Mingle归纳为中国的项目，尽管它的历史比较复杂。）
<ins>
我们可以看到美国市场对于Ruby的工作最感兴趣。在印度也有不少 -- 我们的第一个Ruby项目就是在Bangalore开始。在英国，我们的客户对Ruby的兴趣比较低。这个可能是反映了在Thoughtworks内，领头用Ruby的开发者大多是在美国；另外英国市场对Ruby抱有一定的怀疑。说回我们印度办公室对Ruby的接受程度，是令人鼓舞的。因为传统上，印度对于新技术的引入比较慢，但是我们印度办公室不一样。看来我们公司放在印度办公室的努力，没有白费。
 
根据我们在销售Ruby项目时得到的经验，运用像Ruby这些动态语言，和Thoughtworks整体的各种长处，十分配合。我们的长处是我们招聘到有才华的员工 ，而传统的IT部门是比较难吸引这种人员的。Ruby的一个理念是给一个有才华的开发人员提供一个高效的环境，而不是尝试去保护一个才能较低的开发者，让他不犯错。像Ruby的这种环境，给我们的开发人员们多一些空间去发挥他们真正的才能。
 
Ruby和我们用的敏捷开发过程，也配合得很好。敏捷开发的哲理是：开发软件，经常和用户一起复审，从而取得迅速的反馈。当一个开发环境越能提高生产力，你就可以越频密的和用户复审进度，那么敏捷开发的“检查与适应”这个步骤也会做得更好。


!!关于Ruby的问题

!!!Ruby是不是一个好的选择？
回看41个项目，最重要的问题应该就是：Ruby平台是一个正确的选择吗？要了解这个问题，最直截了当就是问
这些项目的技术主管，让他们回顾一下。

[http://martinfowler.com/articles/rubyAtThoughtWorks/hindsightPie.jpg]

图4：对于这个项目，Ruby平台是一个正确的选择吗？
 
在图4可以看到，觉得选择正确的占了大部分的票数，36对5。我们的技术主管们都是敢言的一群。对于一个错误的技术决定，他们一定会表达不满。所以，我觉得图4显示了Ruby这个平台是非常可行的。

我再深入的调查一下这5个有遗憾的项目。首先是这5个的其中4个项目里，技术主管们觉得Ruby不一定比其他的平台差。但是Ruby是一个没有那么普遍的技术，所以他们觉得Ruby需要为项目带来比其他技术更多的好处。如果Ruby和其他普遍的技术是一样的话，就不值得用一个不普遍的技术。另外，当要和其他一些和Ruby不大配合的技术进行集成时，其中4个项目也遇到了一些问题。比方说，.NET的工具当然和.NET技术集成得比较好。还有，其中2个项目也碰到了一些“政治”上的问题：在客户组织里的人反对使用Ruby或其他动态语言。其中情况比较坏的一个例子，整个IT组织都排斥Ruby，但是业务主办者却支持使用Ruby。
 
毫无疑问，当我问及在软件项目里使用Ruby有什么警报信号时，唯一清楚的答案就是环绕政治上的。在技术层面上，我们接受并鼓励在软件项目里使用Ruby。但是如果客户排斥Ruby，这就是警示我们要避免Ruby的最大信号。

!!!Ruby的生产力较高吗？

当人们问为什么要在一个项目里使用Ruby，最常见的答案就是为了提高生产力。有一个早期的报道，说根据某一个项目的评估，生产力的提高达到一个数量级。

很自然地我也向技术主管们提出了关于Ruby的生产力的问题 - Ruby有提高了生产力吗？如果有的话，提高了多少呢？我要他们和一个用上主流技术（Java或 .NET），并且用上他们所知的最高生产力方法的项目，作出比较。

[http://martinfowler.com/articles/rubyAtThoughtWorks/productivityBar.jpg]
图5：Ruby提高了多少生产力？（和你所知的、最好的主流技术工具比较）

正所谓“尽信书不如无书”，读者也应该抱着怀疑的态度去看这些结果。说到底，我们没有办法客观地测量软件生产力。这些只是我们技术主管们主观的，性质上的评估。（我没有收到所有项目的回复。）但是，这些结果还是说明Ruby真正的增进了生产力。
 

从人手调配的角度来看，也找到支持这个结论的理由。Scott Conley（我们Atlanta分公司的总经理）留意到当一个Ruby项目开始后，比起用其他技术的项目，通常需要多50%的人员来分析需求。

 
有一点我们注意到的，就是你不能期望项目一开始就有生产力的提升。据我听说过的几个案例，人们看到一个新Ruby团队的最初几个星期进展缓慢，而感到焦虑 -- 这是我称为“改善峡谷”的后果。一个Ruby团队需要一段时间去熟悉这个平台的特性，所以这段时期进度会比预期慢。
 

“改善峡谷”是一个常见的现象，而通常缓和的方法是让一些有经验的人员加入团队。在这个情况，最重要的经验是对于类似Ruby、有元编程特性的动态语言的经验，而不一定是Ruby经验。正如Scott Conley所说：差异在于效率风险和交付风险。一个有动态语言经验，但没有Ruby经验的团队，一开始可能会比较慢（效率风险）。但是，一个没有动态语言经验的团队有可能生产出一些很棘手的代码，这样就会增加整体交付的风险。


!!!Ruby慢吗？
 

简短的回答：“是”。在网上搜一下的话，你会找到很多报道说，就算比起其他动态语言，Ruby也是像乌龟一样。
 
但是整体来说，Ruby的速度对我们的项目没有影响。我们大多数都是用Ruby来构建有数据库后台的网站。我这几十年探访过很多项目（Ruby或其他技术的），差不多每一个项目都有花时间去解决性能问题，而差不多每一次这些性能问题都来自数据库访问。他们通常花时间去优化SQL，而不是处理性的代码。因为多数应用的性能都是受I/O所限制，所以就算用一个慢的语言来处理逻辑，也不会对系统的整体性能有什么影响。

读者可能已经发现了我用了一些评论家们喜欢用的诡辩。尽管差不多每一个项目的性能瓶颈都是I/O，有些时候你真的会碰到例外的情况 -- 一个有趣的例子就是Mingle。Mingle在很多方面都不寻常。它的显示需要非常的动态，导致它不可以把网页缓存，也让它和大多数的web应用不一样。所以，它的性能瓶颈不是I/O，而为了达到好的性能，它对硬件的需求也出乎意料之外的高（一台4核，2GB的服务器来支持20-40人的团队）。

尽管如此，Mingle开发团队还是觉得Ruby是一个正确的选择。他们在短时间就开发了很多的功能，所以他们觉得相对于增加了的硬件负荷，利用Ruby而提高了生产力，还是划算的。和很多东西一样，这是一个硬件和生产力的取舍 -- 一个在计算机学里最古老的取舍。每一个开发团队都需要考虑哪一个较重要。幸好对Mingle来说，它的水平扩展性高（多加一些处理器，性能就可以按比例的提高）。硬件扩展性在这种情况下是很宝贵的，因为每一天硬件的价格都在下降。

我要重申一次，大部分的项目的性能瓶颈都是I/O，所以对它们来说，Ruby的速度都是无关痛痒的。Mingle只是一个例外，不属于主流。


!!Ruby代码库难懂吗？

我们常常听到一个对Ruby的担忧，说Ruby的动态类型，元编程，和开发工具的贫乏，会导致Ruby的代码难以理解。普遍来说，我们没有碰到这个问题。我听到的个案都说，因为Ruby比较精简，用比较少的代码就可以写好同样的功能，所以它比起其他主流语言，更容易保持代码的整洁。

话虽如此，我也需要强调我们这些个案的背景。Thoughtworks的开发人员的水平和能力一般较高，而且热衷于使用纪律性强的法门，如极限编程（Extreme Programming）。我们非常看重测试（在Ruby社区里也如是），而这些测试对于保持代码的整洁，起了很大的作用。所以，我不能肯定地说，在一些不同能力和纪律性的团队中，会不会看到相同的效果。（即使在其他主流语言里，在较好的开发工具和较为静态的环境下，大家都可以找到写得很恐怖的代码。至于一个写得差的Ruby代码库会不会更差，还有再讨论的余地。）
 
我们观察到开发团队们，对于元编程（meta-programming）的态度逐步的转变：

[http://martinfowler.com/articles/rubyAtThoughtWorks/metaprogramming.png]

图6：对于元编程的态度转变

* 吓人和坏的：人们对于元编程小心翼翼，不多用。
* 吓人和好的：人们开始看到元编程的好处，但还是用得不大习惯。
* 容易和好的：当人们用得越来越习惯时，他们就用得太多，也可能会让代码库变得复杂。
* 容易和坏的：人们对于元编程小心翼翼，但知道用得恰当的话，是很有好处的。

对这些技巧，我最喜欢打的一个比喻就是，它们好像处方药：小量是很有价值，但要确保不过量服食。

像很多东西一样，经验就是最好的帮手。它能帮助你快一点走完这图表的每一阶段。其中最重要的一点是，你将会看到这种采用的周期，特别是“过度使用”的一期。在学一个新的技巧时，通常都有一段时期会过度使用它，因为还没有越过那个界限时，很难知道那个界限是在何处。有一个不错的建议是设一个沙箱 -- 把代码库的一部分拨为试用元编程的范围。有了一个适当的沙箱，之后就比较容易去修改用得太多元编程的部分。


!!!Ruby是不是一个可行的平台？

以上的各个问题其实都是由一个问题来总括：Ruby（和Rails）对我们还有我们的客户，是不是一个可行的平台？目前为止，答案是一个很清楚的“是”。它明显地提高了生产力，让我们反应敏捷，产出好的软件，也更快的交付给客户。但是这不是说Ruby是灵丹妙药，各种情况都适用。挑选一个开发平台永远都不是一件容易的事情，特别是因为很多时候这是一个政治上的选择，而不是一个技术上的选择。但是总括来说，Ruby是一个不容忽视的选择，也值得让我们放这个工具在我们的工具箱里。


另外我要强调的是，你的选择不一定只有一个。我一向都鼓吹开发团队用主流语言（如Java/C#）的同时，也用一些脚本语言来做一些支持性的任务。Ruby是一个优秀的选择，而我们也观察到这种混合应用有所增长。当JVM和CLR对这些动态语言的支持越来越好，我们也会看到愈来愈多的机会，让我们混合使用具有不同优点的语言 -- Neal Ford 把它称为&quot;多语言编程&quot;（Polyglot Programming）。

!!关于开发的一些提示
 
在这最后一章，我会介绍一些我们学到的教训。
 

!!!测试ActiveRecord

当我们一开始使用Ruby，就已经开始争议，在运用Rails的数据库层ActiveRecord时，怎样去把测试组织起来才是最好。基本的问题是，一般的商业性应用软件，性能瓶颈都在于数据库。我们发现利用Test Double可以大大加快测试。对我们这种侧重于测试的开发过程来说，拥有快的测试是非常重要的。Kent Beck建议一个基本的提交构建（commit build）应该需时10分钟以下。我们大部分的项目都能达到这个时限，而使用数据库的double是重要的一环。
 

ActiveRecord的问题在于它混合了数据库访问和商业逻辑在一起，所以要作一个数据库的double比较困难。我们Mingle团队选择接受Rails和数据库是紧密地绑在一起的，让所有提交测试都访问数据库。
 
我们Atlanta和Jersey团队却持相反的意见。Ruby的一个很有用的特性就是能让你在运行时间，把一个方法重新定义。利用这个特性，你可以拿一个ActiveRecord的类，重新把它的数据库访问方法定义为stub。这两个团队创建了UnitRecord这个gem来干这个事情。


在这3年里，我们还没有看到这场争议的哪一方占优。Mingle团队在8分钟里跑几千个测试，执行时会访问一个真实的postgres数据库。（他们把测试并行化，来充分使用多个核。）Atlanta和Jersey团队却觉得他们能利用stub，把提交测试减至2分钟，是有价值的。这情况下，他们是对简单的、访问数据库的测试，和利用stub、较快的测试，作出取舍 。

尽管双方对自己的立场普遍表示满意，stub的应用导致了另一个问题。当团队对方法stub（method stubbing）越来越熟悉，他们也用得越来越多，跌进了一个过度使用的局面：在单元测试里，除了被测试的方法之外，其他的每一个方法都被stub。这里的问题，和用Test Double一样，是可能让测试变得脆弱。当你修改应用软件的行为时，你也需要修改很多模拟旧行为的double。在过度使用之后，这两个团队也多用了一些Rails风格的、直接访问数据库的功能测试。

!!!ActiveRecord的“漏洞”

在项目里一个常见的现象是人们花时间写SQL。对于隐藏数据库访问的代码，ActiveRecord干得不错，但它不能全部隐藏 -- 就是说它有一些抽象化的漏洞。所以，开发人员都要花一些时间直接的写SQL。

这个漏洞在对象关系映射（ORM，object/relational mapping）框架里很常见。差不多每一次我去和项目里的开发人员聊的时候，他们都说80-90%的时候ORM框架可以把SQL隐藏起来，但需要花一些时间去调SQL，让它达到可接受的性能。所以在这方面，ActiveRecord和其他ORM框架没有区别。

一个我听到的评语说，ActiveRecord的抽象化可以让你清脆的脱离它。和DHH谈的时候，他认为使用关系数据库的开发者应该懂得SQL。ActiveRecord把常用的场景简单化，但是当你开始进入复杂的场景时，它就期望你直接用SQL。

我认为这些漏洞不至于让我们不使用这些ORM框架。这些ORM框架的要旨是把常见的东西变得容易，从而提高生产力。它让团队可以集中处理一些真正重要的个案。但如果一个团队以为这些框架是点水不漏，而不花力气在SQL上，便会是一个毛病。这个毛病虽然常见，但不是一个避免不去用ORM框架的理由。当团队正确地使用它们时，会带来真正的益处。


!!!长执行时间的请求


另一个常见的问题是当应用软件要执行一个需时长的请求时，处理不当。如果实现得不好，会让处理这个web请求的handler很长时间没有反应。


这个问题是在人机界面方面很普遍，而且也有一个普遍的解决方法 -- 把任务交给一个背景运行的过程或线程。任何开发过桌面应用的人都会觉得很熟悉。但是有时候如果开发者把切换和通信做得不好，也会碰到麻烦。

一个我觉得较好的办法，而幸好我的ThoughtWorks同事们也同意，就是使用一个actor。在这个模型里，web请求的handler把需时长的请求包装为一个命令（command），然后放进队列（queue）内。在背景运行的actor就监察着这个queue，从queue中提出并且执行这个命令。当它把这个命令执行完了，就通知前台界面的actor。通常这个queue一开始会是数据库的一个表，之后如有需要的话，再把它改为一个消息队列（message queue）。

和ActiveRecord的漏洞一样，我提起这个不是因为它是Rails里特有的问题；我们在各种应用也会看到同样的问题。值得在这里带出是因为用Rails的人们往往很容易忘了有这样的情况发生，也忘了有这样的模式去解决。我们发现Rails把web开发中重复又重复的环节变得简易和快，但是复杂的环节是仍然存在的。

!!!部署

Rails应用很容易建起，可惜部署比较麻烦。最常见的是用几个mongrel web服务器，但是配置比较繁琐。Ruby其他方面通常用起来很容易、很顺利，Rails部署和它们一比较，真的相形见绌。

现在大家都认为Phusion Passenger让部署变得容易，而且是用MRI时最好的部署方法。


我们也很提倡用JRuby来部署。JRuby让大家可以使用标准的Java stack，所以在很多公司里的环境内也能容易地使用。Mingle也是用这个方法让客户能够很容易地安装。Mingle团队所有的开发都是在MRI上做的，但部署在JRuby上。MRI启动较快，开发起来也较快。（JRuby需要启动JVM，所以明显地比较慢）。

!!!控制Gems


Ruby包括了一个软件包管理系统叫RubyGems，能让你容易地安装和升级软件库。Rails也有plugins来做差不多的事情。它们都是好的工具，但也很容易让团队在不同的机器上配置了不同版本的库，而导致混乱。


有好几个方法来对付这个问题。第一，可以把所有的库的源代码都放进版本管理系统里。那么，一个简单的checkout就可以给你全部正确版本的库。第二，可以用一个脚本去下载和激活每一个库的正确版本。这个脚本就需要放在版本管理系统里。


同样道理，大多的团队都把Rails的源代码冻结。这样他们就可以直接在Rails上编补钉来修bug或其他问题。之后，这些补丁亦可以发给Rails Core团队。现在像git这种分布性版本管理系统（distributed version control systems)让这个流程更加轻松。比起我们以前要把Java application server 反编译（decompile）之后再补丁，真的容易得多了。


!!!订下升级的时间表


一般来说，Ruby，特别是Rails，都是日新月异。Rails也常常升级，频密地造出包含很多新功能的新版本。我们经验所得，要在项目计划时，订下Rails升级的时间表。虽然升级需要付出的努力比其他平台大，但值得高兴的是新功能源源不绝。


!!!在Windows上开发

Ruby生于Unix世界里，而大多数用Ruby的人在目录路径里，都是用前斜线符号（forward slash）。在Windows上运行、部署、和开发Ruby是完全可能的，但是比较刁钻。我们一般建议用一个unix平台做开发。我们都偏爱Mac，但也有很多人都用其他的开源版本的Unix。

我们希望Iron Ruby会改变这个现状。能够在Unix，JVM，或CLR上部署Ruby，将会是一件很好的事情。这个确然会把Ruby定位为可以在各平台运行的一个灵活的选择。这个也会帮助我们在我们的.NET项目里使用Ruby作为脚本语言，和主流的.NET语言一并使用。


!!!鸣谢

如果没有众多同事的合作，这篇文章我一定写不出来。比起以前，这一次更加如是。虽然我在自己的工作上用了Ruby已经很多年，但是一个人堆砌一个个人网站，和我们为客户开发的网上应用软件，毕竟是有很大的区别。我很感谢那么多的同事献出时间，给我很多的资料，让我可以真正的评估Ruby的价值。

和其他Ruby用户一样，我们也很感谢Ruby和Rails社区。与任何开源项目一样，社区的作用是非常的重要，所以对所有的Ruby黑客和 Rubyist们，我们Thoughtworks要说一声：ありがとうございました.

!!!主要版本修改

2009年6月11日：第一次在martinfowler.com上发表
2009年6月3日：ThoughtWorks内部评审的草稿</ins>

</pre></description>
	</item>

	<item>
	  <title>在Thoughtworks里的Ruby</title>
	  <pubDate>Sun, 26 Jul 2009 17:24:19 -0400</pubDate>
	  <link>http://rickylui.com/lionwiki/index.php?page=%E5%9C%A8Thoughtworks%E9%87%8C%E7%9A%84Ruby</link>
	  <description><pre id="diff"><ins>在Thoughtworks里的Ruby

</ins>
Thoughtworks 从2006年就开始在一些项目的生产环境里用Ruby。到2008年底为止，我们已经作了41个Ruby项目。为了准备一个QCON的演讲，我对这些项目作了一个调查，总结我们吸取了的经验。我会讨论一些常见的问题，例如Ruby的生产力，速度和可维护性。到现在为止，我们的结论是：对于多种形式的应用软件，Ruby都是一个可行的平台 - 尤其是用Ruby On Rails开发web应用。我也会说一下技术上的教训，还有一些对于测试ActiveRecord的感想。
<ins>
我的雇主ThoughtWorks是一家交付软件的公司。我们替客户开发软件，也开发我们自己的软件产品。我们的其中一个理念是对各种开发平台都持着开放的思想，因此我们可以为不同类型的客户都选择一个最合适的平台。 2000年当我加入Thoughtworks时，Java是我们主要的开发平台。之后我们开始用.NET，到2005年左右我们大部分的工作都是建于在这两个平台上。

与此同时，有几个同事开始用LAMP（特别是Ruby）和脚本语言。Ruby On Rails 这个web 框架的出现，让Ruby鲤跃龙门。2006年，我们开始在一些项目里使用Ruby平台。到了2009年的今天，Ruby平台占了我们一定的工作量，虽然没有Java或C#那么多。


在这3年里，我们掌握了不少Ruby的实践经验。2009年初，我被邀请去QCON作一个关于我们Ruby经验的演讲。为了准备这个演讲，我对这些项目作了详细的调查，而我们的Ruby专家们也分享了他们的意见和经验。为了写本文我花了比预期长的时间，但毕竟也总算完成了。

我把本文分为3个部分。第一部分我会看看我们Thoughtworks的各个Ruby项目的纲要，让读者对我们做过什么项目，有一个笼统的概念。之后，我会带出关于Ruby的几个常见问题，并根据我们的经验作出回答。最后，我会讨论一下我们对使用Ruby学到的一些教训。


我们各项目的外貌

从2006到2008年，Thoughtworks参与了41个Ruby项目。我把“Ruby项目”界定为一个以Ruby作为主要语言的项目。在其他项目，Ruby也有出现，例如最近有不少Java项目也使用了Ruby，将构建自动化，或作功能性测试。差不多所有的Ruby项目都同时用Rails，大部分都是web项目，所以Rails起码和Ruby有着同样的重要性。

[http://martinfowler.com/articles/rubyAtThoughtWorks/projectScatter.png]

图1：2006至2008年Thoughtworks的Ruby项目里，各团队的高峰人数和项目为期的散布图

图1展示了我们各Ruby项目的大小。这里的人数（headcount）是团队最高峰时期的人数（包括Thoughtworks和客户员工；开发人员，项目经理，分析师，等等）。为期是Thoughtworks参与在项目里的时间。

表面上看，Ruby项目比起其他项目，规模比较小，而为期也比较短。有点遗憾的是我没有其他非Ruby项目的数据来作比较。但是肯定的说，我们可以看到大多数Ruby项目都是在20人以下，1年之内。
 
当中有几个项目比较突出。显然我们最大的项目是在此称为Atlanta的项目，高峰人数超过40人。另一个为期长而人数多的项目是Jersey项目。这两个项目有一些关联：基于人手的调配，我们很多比较有经验的Ruby人员都在这两个项目里工作过。

 

第三个值得一提的项目是Mingle。它是一个Thoughtworks Studios的软件产品，所以比起客户的项目，我们可以更加畅所欲言。Mingle为期比较长，而且是一个跨国的项目：从澳大利亚开始，搬到北京，现时分布在北京和旧金山两地。

  
[http://martinfowler.com/articles/rubyAtThoughtWorks/yearStrip.png]

图2：每年各项目的人力投入-带状图
 
图2换了一个不同的角度，来看我们每年对各项目的投入。每一点代表在那一年，对某一个项目投入的人力。这图可以显示了我们过去三年以来，Ruby项目的增长。

 
[http://martinfowler.com/articles/rubyAtThoughtWorks/countryStrip.png]

图3：每个国家的人力投入-带状图

大家用图3来看看我们在每个国家的Ruby项目。我没有尝试去特别处理一些在多地开发，或者是迁移过的项目，所以这图的数据比较粗略。（比如说，我把Mingle归纳为中国的项目，尽管它的历史比较复杂。）
</ins>
</pre></description>
	</item>

	<item>
	  <title>Main page</title>
	  <pubDate>Sun, 26 Jul 2009 17:13:26 -0400</pubDate>
	  <link>http://rickylui.com/lionwiki/index.php?page=Main+page</link>
	  <description><pre id="diff"><ins>Thoughtworks 从2006年就开始在一些项目的生产环境里用Ruby。到2008年底为止，我们已经作了41个Ruby项目。为了准备一个QCON的演讲，我对这些项目作了一个调查，总结我们吸取了的经验。我会讨论一些常见的问题，例如Ruby的生产力，速度和可维护性。到现在为止，我们的结论是：对于多种形式的应用软件，Ruby都是一个可行的平台 - 尤其是用Ruby On Rails开发web应用。我也会说一下技术上的教训，还有一些对于测试ActiveRecord的感想。</ins>
</pre></description>
	</item>











</channel>
</rss>