引入新编程语言的经验教训
openkk 13年前
<p> 英文原文:<a title="permanent link" href="/misc/goto?guid=4958331733826037653">Lessons Learned while Introducing a New Programming Language</a></p> <p> <strong>引言:</strong>这些年我(在工作中)使用过很多编程语言:(马上能够想到的有)Cold Fusion、HTML、Javascript、php、 SQL、 CSS,、ASP(经典 ASP 和 .net)、C#、Ruby、Flex、Java 以及 Clojure。每个语言都有自身的优缺点。作为一名程序员,你可以很容易地指出这些缺点——概括起来就是一句话:</p> <blockquote> <p>我痛恨所有的编程语言—— Matt Foemmel</p> </blockquote> <p> 我认为一开始就考虑到这个问题很重要。在某些时候,你会对现在提倡的东西开始厌恶,所以请想象一下别人对它的感受。</p> <p> 在 2008 年,我在 DRW 的一个代码库中引入 Clojure 语言。这篇博客讨论了过去几年中,我在引入新语言的过程中得到的经验和教训。</p> <p> <strong>选择语言</strong></p> <p> 在组织里引入一门新的语言并非易事。如果你想要成功,你需要选择一门编程语言,它不但能够满足广泛的技术要求同时还要得到大家的认可。在加入 DRW 的时候,我 100% 用 Java 编程,尽管事实上我编写的大部分代码只需要在眨眼之间运行完成(250毫秒)。我们编写代码要求运行时间比眨眼还要短,Java 是绝对正确的选择,但使用 Java 编写其他代码让我感觉 Java 成为了一种负担。</p> <p> 偶尔我会抱怨这种负担,我的老板开始对 JRuby 发生了兴趣。我认为选择 JRuby 对我们已经是一个胜利,但就我个人而言更想听到支持非 Java 语言的呼声。如果考虑 JRuby,那么我认为任何高级的动态类型语言都可以胜任。</p> <p> 然而,在我对 JRuby 生成好奇心之前,我已经开始学习 Haskell 了。总的说来,在贸易公司使用的软件要求运行“快速”。如果我要成功地引入一门新语言,它必须运行得“几乎和 Java 一样快”。Haskell 执行速度很快我已有所耳闻,它同时也满足了我的另一个选择条件:</p> <blockquote> <p>一门编程语言,如果不能对你思考编程的方式产生影响,就不值得去学习。—— Alan Perlis</p> </blockquote> <p> 我认为,如果我发现一门编程语言“性能足够好”,发布程序速度更快,并且能够提高我们的编程水平,那么在它上面花时间就是值得的。</p> <p> 我玩过一点 Haskell,但是学习曲线似乎太陡峭。学习 Haskell 需要一些时间,但更重要的是:我们的产品已经运行在 JVM 上。如果我需要得到任何帮助,应该能够轻易地融入现有的基础设施。想想 Clojure,它的性能足够好,比 Java 更简洁,并且比我之前用过的其他语言更加有效。 Clojure 同时也是动态类型的高级语言(像 Ruby 一样),所以我希望能够得到老板的支持。</p> <p> 让同事们尽可能地减少学习的痛苦是一个很大的要求——我认为这是接受新语言的关键。Clojure 看上去是最佳的选择,因为我们现在已经在工作中已经使用下列工具:</p> <blockquote> <p>整天使用 IntelliJ</p> <p>使用 JUnit 运行所有测试</p> <p>使用 TeamCity 创建 CI 和 artifact</p> <p>在服务器上运行 JVM</p> <p>使用 Yourkit 进行动态分析</p> </blockquote> <p> Clojure 能够满足我的所有条件,其他同事接受起来也会更容易。</p> <p> 作为学习,我更推荐 Haskell 或者 OCaml,但他们并不适合在实际中选用——我怀疑是否能够成功地将他们应用到开发中。当我需要在 Clojure 方面给与专业指导时,我会依赖其他人认可的“最佳”JVM 服务器设置。如果一旦选择了 Haskell 或者 OCaml,我将需要在更多方面成为专家(例如部署、内存模型、函数库、新开发工具等等)。</p> <p> 不论是当时还是现在,我都认为 Clojure 是在技术要求和公司环境下的最佳选择。</p> <p> <strong>Hello World</strong></p> <p> 引入一门新的语言是一个微妙的行为。你需要兼顾很多的相关内容。我不确定同事们会对使用 Clojure 作何反应,所以我在家里预先写好了代码。虽然大家都需要集成测试,然而没有人积极行动。于是我开始用 Java 编写集成测试,然后写出了 Clojure 的版本。我非常了解 Clojure 并能够向其他人展示它的简洁——这是团队在集成测试中最看重的东西。除此之外,因为测试并不是实际产品运行的代码,因而并不真正需要考虑实际执行速度。</p> <p> 集成测试是一个引入新语言的好地方,其实任何非产品代码都是好的选择。例如,你也可以选择数据库迁移脚本、日志文件解析器、第三方软件模拟器或者软件部署。只要你的选择不会马上带来痛苦,你应该能够很容易地从任何迁移到新语言的失败中恢复过来。</p> <p> 当我完成了 Java 和 Clojure 版本的测试以后,我给开发组里的其他人展示了这两个版本。我告诉他们为什么我推荐 Clojure 版本,并询问他们能不能用 Clojure 做一次尝试。我也做出承诺,让他们很难拒绝做这样的实验。</p> <p style="text-align:center;"><a title="hello world bread" href="https://simg.open-open.com/show/ee61375cd5e34aad12bf2398d2f85611.jpg" rel="lightbox[13401]"><img style="width:547px;display:block;height:410px;margin-left:auto;margin-right:auto;" title="hello world bread" alt="引入新编程语言的经验教训" src="https://simg.open-open.com/show/ee61375cd5e34aad12bf2398d2f85611.jpg" /></a></p> <p>( Credit: <a href="/misc/goto?guid=4958331734666787132" rel="nofollow" target="_blank">Windell Oskay</a>)</p> <div> <p> <strong>你的使命</strong></p> </div> <div> <p> 为了让我的伙伴们减少接受新语言的恐惧,我做出了下列承诺:</p> </div> <div> <blockquote> <p>如果你想要编写代码,我会和你一起做(假如你想要和我一起工作的话)</p> <p>如果你不想编写代码,我会将缺失的部分补上</p> <p>如果你觉得用新语言写代码让你难以接受,我会在我的个人时间将所有的内容重新用 Java 写一遍</p> </blockquote> </div> <div> <p> 很明显地,你需要在使用新语言编写很多代码之前让团队接纳——否则你会独自一个人在晚上和周末加班。</p> </div> <div> <p> <strong>工具支持</strong></p> </div> <div> <p> 运气好的话,你的团队已经有了一套他们喜欢的工具。不论工具是什么,你的新语言应该能够很好地被支持。对我而言,这就意味着在 IntelliJ 上 Clojure 应该像 Java 一样被执行。很大程度上 La Clojure 插件完成了这项重任;然而,我需要编写一个而是框架让我能够运行指定的测试并且无缝地将现有 JUnit 测试集合集成进去。这里要说的是,请为团队成员消除所有新语言可能带来的阻力。学习一门新语言的要求是合理的,但仅仅为了适应一个(在那个团队里)未经实 际验证过的语言而改变团队的工作,这也许是一个过分的要求。</p> </div> <div> <p> 你也可能需要作出一些牺牲。我喜欢在 emacs 中编写 Clojure;然而我宁愿在 IntelliJ 中编写 Clojure 而不是 Java。在转向新语言刚开始的脆弱时期,你会是需要作出妥协最多的人。</p> </div> <div> <p> <strong>寻找同盟军</strong></p> </div> <div> <p> 对新语言热爱程度的不同会让事情的发展也有所不同。当别人开始感兴趣的时候,你应当尽己所能地鼓励他们。然而,不要强迫别做事情——这是最容易 树敌的办法。希望你能找到一些和你一样对新语言感兴趣的伙伴——与他们一起紧密工作并提高你的水平。你需要寻找更多的支持者,否则你会成为团队中唯一强迫 别人做他们不喜欢事情的人。</p> </div> <div> <p> 你不可避免地需要做一些调研,需要相关工具的支持,而且需要处理比开始预期更多的问题。当你发现自己捉襟见肘的时候,会需要其他人来助你一臂之力。即使一切运转正常,你也会发现需要一些支持者来帮助你维护日益增多的新语言代码。</p> </div> <div> <p> 最后,最糟糕的情况是当你离开团队时没有一个留下的人愿意维护这些代码。当人员发生调整时,采纳新语言会很容易成为大问题。</p> </div> <div> <p> <strong>了解所有事情</strong></p> </div> <div> <p> 很明显地你不可能确切地了解所有的事情,但当问题出现时你需要能够马上给出或想出一个答案。在将新语言放进如何代码库之前,你一定要通读几本新 语言的书,因为代码库是你的同事赖以工作的基础。这样还不够,你还要知道如果遇到问题你能够去哪里寻求帮助。对于 Clojure,得到问题回复方式就是 IRC,如果问题不是很紧急或者需要详细描述你的问题,你可以通过邮件列表来寻求答案。如果你真的想要掩盖自己的不足,你需要和语言的作者或者社区的领袖 人物建立某种关系。</p> </div> <div> <p> 一旦人们接受了你介绍的新语言,他们会开始做一些你意想不到的事情。你需要了解语言的缺点,并想到可能因此带来的后果。你还需要成为一名专家,通晓内存分配、性能、部署、工具集成、函数库支持、升级计划以及除了语言文法之外的所有问题。</p> </div> <div> <p> 你的支持者越多,需要“知道所有事情”的情形就越少。然而,在每天完成工作以后,你还是应当尽可能地去了解相关的技术。如果出现问题,所有人都会认为这是你的错。这就是引入新语言应当承担的责任,所以你应当更好地理解你正在做什么。</p> </div> <div> <p> <strong>获得帮助</strong></p> </div> <div> <p> 如果你的公司愿意让你引入新的语言,那它一定愿意提供支持。有可能你已经得到了一些培训预算。看看有没有机会能够让语言作者或者社区领袖和你一 起工作,或是提供相关的培训。如果你在新语言的各个方面都有问题,那么让语言的作者和你一起工作会带来巨大的好处。当然一切进展顺利的时候,如果团队中其 他对新语言感兴趣的同事能够从语言作者(或者某个社区领袖)那里学习,那么将预算投给这样的培训会给你带来巨大的好处。无论是你自己或是感兴趣的支持者, 利用公司的培训预算来推广新语言都是有益的事情。</p> </div> <div> <p> <strong>成为拥护者而不是狂热分子</strong></p> </div> <div> <p> 每天结束工作的时候,并非每个人都能会妥协。 这没有关系。不要将自己的观点强加给对此没有兴趣的人。最有可能的情况是,总会有人对“正确”选择充满热情。也许你对自己推荐的语言报以热情,但你的队友 可能非常喜欢之前的语言。你们不必为此分出谁对谁错。人们只会用自己喜欢的语言编程,任何试图让他们尝试别的方式都会弊大于利。喜欢用新语言的人们会聚集 在一起,而不喜欢的人也会如此。没有任何理由强迫别人接受。</p> </div> <div> <p> 起初我对这个问题的看法是“如果我提出一个好的办法,那么所有人都会接受它。”事实并非如此,所以我写了一篇软件开发中的妥协。我了解到一个人 眼中“更好的办法”在另一个人看来却是“更糟糕的选择”。最后,团队分成了用 Clojure 编程和不用 Clojure 两个小组。这对两方都有好处,想要用 Clojure 的人会有更好的环境,而其他人也不用强迫使用 Clojure.</p> </div> <div> <p> 这种划分当然只是私下的,在公司里我们仍然是“一个团队”。但我们开发不同的应用程序,通过发消息交流或者不沟通。我强烈建议一个小组按照不同 的想法和规模分开(7个人的团队,我认为分成 4 人和 3 人两个小组是可以接受的),但永远不要在公司里公开。逐渐的,其他因素会让团队规模缩小,这种划分会变得多此一举。如果团队没有因为其他原因重组,我仍然 坚信组内划分是最好的选择。</p> </div> <div> <p> <strong>尾声</strong></p> </div> <div> <p> 引入一门新语言对于任何上规模的组织都是一件需要多年才能完成的事情。自打引入新语言开始,你的责任就永远不会“结束”。反过来说,你已经开始 使用适合这项工作最好的工具。希望所有说过和做过的事情都是值得的。就自己而言,我对自己的选择感到高兴,但我也期待未来的几年里在“引入新语言”这个话 题上能有更多的收获。</p> </div> <div> <p> 编译:<a href="/misc/goto?guid=4958185140659301754" target="_blank">伯乐在线</a> – <a href="/misc/goto?guid=4958327305355149094">唐尤华</a></p> </div>