Scribd 在全球所有使用 Rails 网站中,做到了流量排行第三,最近该网站的创始人 Jared Friedman 写了一篇文章,告诫所有初创公司为什么他不会在选择 Rails:
作为国内最早的一批 Ruby 程序员,RubyChina 社区的管理员,目前仍然靠写 Ruby/Rails 代码混饭吃的人,当我看到这篇文章,内心其实是拒绝的。但是静下来想了想,文章中的观点并非不可接受,这取决于你选取的角度。对方站在自己的角度表达了观点,想法,看这个技术世界的样子,那么如果不能尝试理解对方思考的角度,就自燃无法接受对方的观点了。
我试着不带有价值判断的眼光,去尝试理解 Jared 的角度,然后在作出自己对事实的判断。Scribe 创建于 2006 年,基于 Rails 0.7 创建。2006 年的 Rails 远远没有现在的成熟度,在当时选择 Rails 意味着:
Jared 认为这三点中,第三点是最重要,之后的结果是:
Jared 在 2006 年选择站在技术的风口浪尖,作了个赌博,于是才有今天这样一个多赢的结果。所以作者角度是从赌博出发,建议初创的技术型公司把眼光放长远,不要去选择今天看起来很安全的技术,应该选择未来三年可能会成长起来,且会有大量有天赋的开发者未来三年内会选择并切换过去的技术,在这个过程中,你要保证团队能够跟随技术发展同步成长即可。
我觉得这个观点挺开脑洞的,不能说没有道理,但是我所了解的大多数技术公司通常不会从这个角度去做决策,可能也不是没有,比如七牛云存储的老大许式伟一直就是国内最主要的 Golang 布道者之一,Strikingly 的 CTO 郭达峰,一直活跃在国内推广 React.JS 的一线。这就要看你信什么了,不管你信奉乔帮主,还是其它什么人,能做成一家公司从来都不是那么简单的事,所以有信念很重要,还是得选择信奉一些什么。
其实并没有明确的建议。Jared 提出了三个 Ruby/Rails 的问题:1) 语言的运行效率很慢 2) 框架发展到了瓶颈期,优势不再 3) 对开发者的吸引力下降。然后通过 Google Trends 展示出一些新语言,以及工作职位的趋势,
从当前的数据和趋势看 Node.JS 目前正处于领导位置,可是选择 Node.JS 或者 Golang 或者其他新兴的语言框架,就如同 2006 年的时候选择 Ruby/Rails 么?这里提到的每一个,其实都不是。
Jared 在文章中说的其实都是对的,这些都是事实,必须要承认。Ruby is slow,Jared 知道,我知道,你知道,所有的 Rubyist 都知道,问题是性能真的那么重要么?
抛开具体的场景谈问题,都是耍流氓!如果你要处理的是 CPU Intensive 的问题,那么你应该用 C 语言(或者 C++)。如果你面对的问题是 I/O Intensive 的话,那么语言的性能并不是问题的关键,编程范式和架构才是。在 Web 应用的场景下,大家其实应该关心的问题是如何把 HTTP 请求处理的平均时间优化到 200ms 以内,如果你对 Rails 处理 HTTP 请求的过程非常熟悉的话,你还会仅仅纠结于 Ruby 语言的性能么?如果你已经充分优化了架构,缓存,数据库访问后,仍然对 Ruby 的性能感到沮丧的话,我真的要恭喜你,你已经成功了!此时你的项目应该已经 C 轮了吧,赶紧用钱去砸,不要纠结。
Scribd 在 2006 年用的 Ruby 比现在的版本要慢得多,那个时候的 Scribd 看重 Ruby/Rails 的到底是什么?我猜答案应该是 Just Enough -- 在平衡性能的同时,给了你极佳的开发效率,完整的生态系统,帮助你实现各种可能性,以期应对快速的发展和变化。这本质是一种 Tradeoff,是一种折衷,优先确保开发层面上的效率,而后才是性能。那么用性能换开发效率是不是一个最优决策?答案是看场景,在场景合适的情况下,这就是最佳策略。当时间推移,场景变迁后,是否还应该继续坚持这个策略,答案当然是 NO!
当业务发展需时,其他语言或者框架更加符合场景的话,Go for it!
当年 Rails 升级到 3.0 的时候,我们称其为 The Great Rails Refactor ,这一次升级的改变幅度巨大,以至于 Rails 3.0 发布后很久,大量的项目都无法及时跟进。在这之后的 Rails 每一个版本更新依然保持废弃掉一些老旧功能并同时带来新的东西,但是向后兼容问题已经大幅改善了:
高速发展的事物其本身都承载着一种叫做 growing pains 的东西,我们姑且称之为成长期阵痛。这是一个好东西,如果一个事物的这种 pains 在削减,那么我们会认为它变得成熟。受到这种成长期阵痛影响最典型的可能是 Github,直到 2014 年底,Rails 3 发布四年后,Github 终于把项目代码从 2.3 升级到了 4.1,整个升级过程耗时 6 个月。
有一种观点认为像 Gihtub,Twitter,或者 Scribd 等都不是 Rails 应用的典型项目,这些项目体量巨大,为了满足自身需要,对 Rails 本身做了大量的扩展与二次开发,导致因为无法跟随一些 Rails 开发的最佳实践,于是每次当考虑升级的时候,发现升级所耗费的成本远远高于新版本所带来的好处。我认同这个观点,这本质仍然是一个 Tradeoff,是一种折衷。选择始终遵循 Rails 的一整套最佳实践,会给你的项目带了较好的向后兼容性,降低升级的成本。为了解决具体场景下的问题作一些特化处理,从而增加升级的成本。Rails 给出的建议是选择前者。
选择对的框架去解决对的问题就不会错。Rails 仍然是流行的 Web 开发框架之一,作为一个现象级的框架,被其他框架争相模仿,这些框架不仅仅克隆了 Rails 的功能,还克隆了 Rails 框架背后的思想,经过经年累月的发展,这些框架相对于 Rails 的差距在缩小,因为后发优势的原因,在 API 向后兼容方面做得比 Rails 更出色。
如果另外一种框架比 Rails 更稳定,优秀,且更符合你的需求的话,Go for it!
Ruby/Rails 一度能成为硅谷湾区初创公司的 Default Web Application Stack 其实并不仅仅是因为技术本身,语言框架背后的设计思想和哲学给开发者带来的影响其实更大。
Ruby somehow enables programmers in a special kind of way that is so hard to explain to the ‘unwashed masses’.
体验过 Rails 开发的人,特别是从其他语言转过来的开发者,比如 Java,ASP.NET,甚至 Python 开发者,在学习 Ruby/Rails 的第一感受往往是能感受到某种快乐。感到快乐非常重要,这种快乐来自语法层面赋予开发者最大限度的自由和灵活,以及 Rails 框架深层的 DNA 中包含的对代码品质优雅的追求,以及想方设法集成大量的最佳实践,让开发者在使用框架过程中感受到方便快捷,和无微不至的实用主义。于是很多开发者尝试过 Ruby,写过 Rails 之后发现再也回不去了。
有人说 Ruby/Rails 自带鸡汤,效果肯定不会长久,兴趣和偏好必须能经受市场考验。话没错,那就不撒鸡汤,回归现实。对于每一个开发者来说,拥有,维持自己的核心竞争力很重要,先掌握一技之长,然后最大限度的发展自己的技能树之外,另外一件重要的事情就是能有效的把握市场需求,Rails 虽然已经不是当下最热门的技术,但是其市场需求依然非常旺盛,掌握良好的 Ruby 编程经验和技巧依然可以确保你衣食无忧。接受并认可 Ruby/Rails 背后的哲学思想的价值,并不妨碍你学习新的东西,所以为了维持自己的核心价值,应该不断发掘并学习你感兴趣的新东西。
当另外一种语言更加能激发你的兴趣,并让你相信值得为之投入的话,Go for it!
其实 Ruby 是一门非常保守的语言,近些年 Ruby 最大的变化来自于从 1.8 升级到 1.9 这一版升级,包括重写了底层虚拟机,系统原生线程支持,新的字符 Coding 处理,更好的 GC,以及一些向后不兼容的语法变化等等,这一步 Ruby 用了五年,相对于 Perl 5 到 Perl 6 用了 15 年,Python 2.7 到 Python 3.x 目前看来仍然遥遥无期。
1.9 之后的节奏是小步快速迭代,并尽可能向后兼容,尽可能不引入任何破坏性的变化,所以整个社区都推荐直接用最新的 Ruby 稳定版,不纠结。目测 Ruby 未来仍然会坚持把满足语法设计作为第一优先级,其次才是性能。从过往的经验看,这个策略是 Ruby 成功的要素,所以 Matz 才会一直坚持 20 年不动摇。
现在市场上很难买到单核 CPU,连手机都进入了 8 核时代,人们比以往任何时候都更加关心 Ruby 的 Concurrency 能力。回到 2012 年 Ruby 2.0 正式发布的时候,大家欢欣雀跃因为 Ruby 抛弃了多年的 Green Thread,取而代之的是直接使用操作系统原生线程,似乎原生多线程编程的威力终于要被释放了,当时 Matz 被问到何时能去掉 GIL 时,Matz 很腼腆的回答 I don't consider myself as the threading guy
。就是否移除 GIL 这个问题到现在已经三年过去了,Ruby 的核心团队已经明确的表示不会移除,于是人们批评核心团队在 GIL 问题上太过保守,可是核心团队决定保留 GIL 其实是为了最大限度的保护程序员,保护程序代码的安全。
Ruby 会继续打磨并引入新的语法,性能会持续得到优化,但是在 Concurrency 这个方向上何去何从呢?Matz 最新的公开演讲提到,会引入更多的抽象并发模型,可能会尝试性的把 Actor model / Event-driven loop 引入到语言核心中,也可能会引入 Ownership model 以确保并发中的共享内存安全问题,Matz 的新语言 Stream 则在尝试通过管道的方式实现并发,会支持更多的 immutable 类型的对象,但是这一切都仍然处于试验中,核心团队不承诺任何东西,我们只能拭目以待。
如果你为了追求更好的 Concurrency 编程选择其他语言,Go for it!