Rails 教义。

大卫·海涅迈尔·汉森

Ruby on Rails 迅速崛起,其成功很大程度上归功于新技术和时机。但技术优势会随着时间的推移而逐渐消失,而良好的时机并不能长期维持运动。因此,需要更广泛地解释 Rails 如何不仅保持其相关性,而且如何扩大其影响力和社区。我认为,持续的推动力量一直是其有争议的教义。

这种教义在过去十年中一直在发展,但其最强大的支柱也是其创始支柱。我并不声称这些想法具有根本的原创性。Rails 最大的成就是将一群人团结起来,并围绕着一系列关于编程和程序员本质的异端思想培养了强大的部落。

话不多说,以下是本人认为的 Rails 教义的九大支柱。

  1. 以程序员的幸福为优化目标
  2. 约定优于配置
  3. 菜单是 omakase
  4. 没有单一范式
  5. 推崇优美的代码
  6. 提供锋利的刀具
  7. 重视集成系统
  8. 进步胜于稳定
  9. 撑起一个大帐篷

以程序员的幸福为优化目标

没有 Ruby 就没有 Rails,因此第一个教义支柱直接源于创建 Ruby 的核心动机,这再合适不过了。

Ruby 最初的异端思想确实是将程序员的幸福置于首位。这超越了之前驱动编程语言和生态系统的许多其他竞争和有效的关注点。

Python 可能吹嘘“做某事最好只有一种方法”,而 Ruby 则乐于表达和微妙。Java 竭力保护程序员免受自身伤害,而 Ruby 在欢迎套件中包含了一套锋利的刀具。Smalltalk 灌输了消息传递的纯洁性,而 Ruby 则以近乎贪婪的胃口积累了关键字和结构。

Ruby 与众不同,因为它重视不同的东西。而这些东西大多是为了满足程序员的幸福感。这种追求不仅让它与大多数其他编程环境格格不入,也与主流对程序员的认知以及他们应该如何行动的认知相冲突。

Ruby 不仅认识到程序员的感受,而且还适应并提升了这些感受。无论是自卑感、奇思妙想还是喜悦。Matz 克服了令人惊叹的复杂实现障碍,让机器看起来在向人类合作者微笑和奉承。Ruby 充满了视觉错觉,那些在我们眼中看起来简单、清晰、美丽的东西,实际上是引擎盖下的一团杂乱无章的电线。这些选择并非免费(问问 JRuby 团队尝试反向工程这个神奇的音乐盒!),这正是它们如此值得称赞的原因。

正是这种对编程和程序员的另一种愿景的奉献,让我爱上了 Ruby。这不仅仅是易用性,不仅仅是代码块的美学,也不是任何一项单一的技术成就。这是一个愿景。一种反文化。一个让现有专业编程模式中的不合群者找到归属感,与志同道合的人联系在一起的地方。

我过去曾将发现 Ruby 描述为找到了一只神奇的手套,它完美地契合我的大脑。比我曾经想象的任何手套都更合身。但它远不止这些。这是我个人从“因为需要程序而进行编程”转变为“因为爱上了编程作为一种智力练习和表达方式而进行编程”的标志性事件。它找到了一个心流之泉,并且能够随意开启它。对于任何熟悉 Csikszentmihalyi 作品的人来说,这种影响难以言喻。

我毫不夸张地说,Ruby 改变了我,并为我的人生工作指明了方向。这种启示是如此深刻。它赋予了我一种使命感,让我为 Matz 的创造服务。帮助传播这种深刻的创造及其益处。

现在我可以想象你们大多数人会难以置信地摇头。我不怪你们。如果有人在我还处于“编程只是一个工具”的范式下时向我描述了上面的经历,我也会摇头。然后我可能会嘲笑这种过度使用宗教语言。但为了让这成为一个真实的描述,它也必须诚实,即使这对某些人甚至大多数人来说都令人反感。

无论如何,这对 Rails 意味着什么,以及这个原则如何继续指导它的发展?为了回答这个问题,我认为看看另一个经常用来描述 Ruby 的原则很有启发性:最小惊讶原则。Ruby 应该按照你期望的方式运行。这很容易用与 Python 的对比来描述。

$ irb
irb(main):001:0> exit
$ irb
irb(main):001:0> quit

$ python
>>> exit
Use exit() or Ctrl-D (i.e. EOF) to exit

Ruby 接受 exit 和 quit 来满足程序员明显想要退出其交互式控制台的愿望。另一方面,Python 则迂腐地指示程序员如何正确地执行请求的操作,即使它显然知道是什么意思(因为它正在显示错误消息)。这是一个非常清晰的例子,尽管很小,但它体现了 PoLS。

PoLS 在 Ruby 社区中失宠的原因是,这个原则本质上是主观的。对谁来说最不令人惊讶?嗯,对 Matz 来说。还有那些和他一样感到惊讶的人。随着 Ruby 社区的壮大,以及那些对 Matz 以外的事物感到惊讶的人的比例不断增加,这成为了邮件列表中毫无结果的争论来源。因此,这个原则逐渐淡出人们的视线,以免引发更多关于 X 人是否对 Y 行为感到惊讶的无意义辩论。

那么,这与 Rails 有什么关系呢?嗯,Rails 的设计理念与最小惊讶原则(对 Matz 来说)类似。更大的微笑原则(DHH 的原则),顾名思义:API 的设计非常注重什么能让我更开心地微笑。当我这样写出来的时候,这听起来几乎是可笑的自恋,即使我自己也难以反驳这种第一印象。

但创造像 Ruby 或 Rails 这样的东西,至少在最初阶段,是一项极度自恋的努力。这两个项目都源于一个单独创造者的思想。但也许我只是将自己的动机投射到 Matz 身上,所以让我将我的声明范围缩小到我所知道的:我为我自己创造了 Rails。首先是为了让我微笑。它的效用在很大程度上服从于它让我更享受生活的能力。丰富我每天处理网络信息系统需求和请求的辛劳。

像 Matz 一样,我有时会为了我的原则而做出一些愚蠢的事情。一个例子是 Inflector,这是一个类,它对英语的模式和不规则性有足够的了解,可以将 Person 类映射到 People 表,将 Analysis 映射到 Analyses,并将 Comment 简单地映射到 Comments。这种行为现在被认为是 Rails 中不可质疑的一部分,但在早期,当我们还在整合教义及其重要性时,争议的火焰却燃烧得非常猛烈。

另一个例子需要更少的实现工作,但引发了几乎同样多的不安:Array#second 到 #fifth(以及为了更好的嘲讽而添加的 #forty_two)。这些别名访问器对那些大声疾呼反对这种臃肿(以及文明的终结,为了更好的衡量)的人来说是极其令人反感的,因为它们可以用 Array#[1]、Array#[2](以及 Array[41])来代替。

但这两个决定至今仍然让我感到高兴。我喜欢在测试用例或控制台中写 people.third。不,这不是逻辑的。它不是有效的。它甚至可能是病态的。但它仍然让我感到高兴,从而实现了这个原则,丰富了我的生活,帮助我为我持续 12 年的 Rails 服务找到了理由。

与优化性能不同,优化幸福感很难衡量。这使得它几乎成为一项本质上不科学的努力,对某些人来说,这使得它不那么重要,甚至令人沮丧。程序员被教导要争论并征服可衡量的事物。那些有明确结论的,并且可以明确证明 A 比 B 更好的。

但是,虽然追求幸福在微观层面上很难衡量,但在宏观层面上却很容易观察到。Ruby on Rails 社区充满了正是因为这种追求而来到这里的人。他们吹嘘着更美好、更充实的职业生涯。正是这种情感的总和,让胜利变得清晰。

因此,我们得出结论:优化幸福感也许是 Ruby on Rails 最重要的形成因素。它将继续保持这种状态。

约定优于配置

Rails 早期的生产力格言之一是:“你不是一个美丽而独特的雪花”。它假设,通过放弃虚荣的个性,你可以跳过平凡决策的困扰,并在真正重要的领域取得更快进展。

谁在乎你的数据库主键用什么格式描述?它是否真的重要,是“id”、 “postId”、 “posts_id” 还是 “pid”?这是一个值得反复考虑的决定吗?不。

Rails 的使命之一就是挥舞着大刀,砍伐开发人员为网络创建信息系统时面临的不断增长的重复决策的丛林。有成千上万这样的决策只需要做出一次,如果有人可以为你做,那就更好了。

将配置转移到约定不仅让我们免于反复考虑,而且还为更深层的抽象提供了肥沃的土壤。如果我们可以依赖 Person 类映射到 people 表,我们可以使用相同的词形变化将声明为 has_many :people 的关联映射到 Person 类。良好约定的力量在于,它们在广泛的应用范围内都能带来回报。

但除了为专家带来的生产力提升之外,约定还降低了初学者的入门门槛。Rails 中有许多约定,初学者甚至不需要了解,但可以在不知情的情况下从中受益。即使不知道为什么所有东西都是这样,也可以创建出很棒的应用程序。

如果你的框架只是一本厚厚的教科书,而你的新应用程序只是一张白纸,那么这是不可能的。即使是弄清楚从哪里开始以及如何开始,也需要付出巨大的努力。开始的一半挑战在于找到一根可以拉的线。

即使你理解所有部分是如何组合在一起的,也是如此。当每一次改变都有一个明显的下一步时,我们可以快速浏览应用程序的许多部分,这些部分与之前的所有其他应用程序相同或非常相似。每个东西都有一个地方,每个东西都在它应该在的地方。约束甚至可以解放最能干的头脑。

然而,与任何事物一样,传统的威力并非没有风险。当 Rails 使得做很多事情变得如此微不足道时,很容易认为应用程序的每个方面都可以通过预先切割的模板来形成。但大多数值得构建的应用程序都有一些在某种程度上是独一无二的元素。它可能只有 5% 或 1%,但它就在那里。

困难的部分在于知道何时偏离传统。何时偏离的细节严重到足以保证一次远足?我认为,大多数想要成为美丽而独特的雪花的想法都是经过深思熟虑的,而偏离 Rails 的成本被低估了,但其中足够多的想法不会让你需要仔细检查所有想法。

菜单是 omakase

当你不知道什么好吃的时候,你怎么知道在餐厅点什么?好吧,如果你让厨师选择,你可能可以假设一顿美餐,即使在你不知道“好”是什么之前。这就是 omakase。一种让你无需成为烹饪专家,也无需在黑暗中盲目选择就能吃得好的方法。

对于编程来说,这种做法的好处,即让其他人组装你的堆栈,类似于我们从约定优于配置中获得的好处,但处于更高的层次。CoC 关注的是我们如何最好地使用单个框架,而 omakase 关注的是 *哪些* 框架,以及它们如何组合在一起。

这与将可用工具作为个人选择呈现的传统编程传统相矛盾,并赋予个人程序员做出决定的特权(和负担!)。

你一定听说过,而且可能也点头同意,“使用最适合工作的工具”。这听起来如此基本,以至于没有争议的余地,但能够选择“最佳工具”取决于一个基础,它允许以信心确定“最佳”。这比看起来要难得多。

这就像餐厅里的套餐,与选择餐厅的菜肴类似。就像在一个八道菜的套餐中选择每一道菜一样,选择每个单独的库或框架不是一项孤立的工作。在这两种情况下,目标都是考虑整个晚上或整个系统。

因此,在 Rails 中,我们决定减少一个好处,即程序员选择工具箱中每个工具的个人特权,以换取一个更大的好处:为所有人提供更好的工具箱。红利很多。

  1. 众人拾柴火焰高:当大多数人以相同的方式使用 Rails 的默认设置时,我们拥有共同的体验。这种共同点让教学和帮助人们变得容易得多。它为方法上的辩论奠定了基础。我们昨晚 7 点都看了同一档节目,所以我们第二天可以谈论它。它培养了更强的社区意识。
  2. 人们正在完善相同的、基本的工具箱:作为全栈框架,Rails 有很多活动部件,这些部件如何协同工作与它们单独的功能一样重要。软件中的许多痛苦不是来自各个组件,而是来自它们的交互。当我们都致力于减轻来自以相同方式配置和失败的组件的共同痛苦时,我们都会体验到更少的痛苦。
  3. 仍然可以进行替换,但不是必需的:虽然 Rails 是一个 omakase 堆栈,但它仍然允许您用替代方案替换某些框架或库。它只是不要求您这样做。这意味着您可以推迟这些决定,直到您培养出清晰的个人口味,可能更喜欢偶尔的差异。

因为即使是最有学识和技能的程序员,来到 Rails 并留在 Rails 中,也不太可能反对菜单上的所有事项。(如果他们反对,他们可能就不会坚持使用 Rails。)所以他们会谨慎地选择自己的替代品,然后继续与其他人一起享受其余的策划的、共享的堆栈。

没有单一范式

选择一个中心思想并将其作为您的架构基础,并将其遵循到逻辑结论,这具有很强的感情上的吸引力。这种纪律中有一种纯粹性,因此很清楚为什么程序员天生就被这种明亮的光芒所吸引。

Rails 并不像那样。它不是一块完美的布料。它是一床被子。由许多不同的想法甚至范式组成。许多通常会被视为冲突的想法,如果单独对比,一个接一个。但这不是我们试图做的事情。它不是一个优越想法的单一冠军,其中必须宣布唯一的获胜者。

以我们在 Rails MVC 饼图中构建视图的模板为例。默认情况下,所有允许我们从这些模板中提取代码的助手只是一个大型函数库!它甚至是一个单一的命名空间。哦,多么令人震惊和恐惧,这就像 PHP 汤!

但我认为 PHP 在呈现很少需要交互的单个函数方面做得很好,就像视图模板中的许多抽象一样。出于这个目的,单一命名空间,一大堆方法,不仅是一个合理的选择,而且是一个很棒的选择。

这并不意味着我们在构建视图时偶尔不想寻求更面向对象的方案。Presenter 的概念,我们封装了许多相互依赖的方法以及它们下面的数据,偶尔可以成为解决方法混乱的完美解药,这些方法因依赖关系而变得混乱。但它通常被证明是罕见的,而不是常见的适合。

相比之下,我们通常将 MVC 层蛋糕中的模型视为面向对象优点的主要堡垒。为对象找到合适的名称,提高一致性,降低耦合是领域建模的乐趣。它与视图是截然不同的层,因此我们采取了不同的方法。

但即使在这里,我们也不赞成单一范式教条。Rails 关注点,Ruby 混合的专门化,经常被用来赋予单个模型非常广泛的表面积。这与 Active Record 模式很好地契合,因为它使关注的方法可以直接访问它们交互的数据和存储。

甚至 Active Record 框架的根基也冒犯了一些纯粹主义者。我们将与数据库交互所需的逻辑直接与业务领域和逻辑混合在一起。这种边界混淆!是的,因为它被证明是剥皮 web 应用程序猫的实用方法,这种猫几乎总是与某种数据库对话以持久化领域模型的状态。

这种意识形态上的灵活性使 Rails 能够解决如此广泛的问题。大多数单个范式在问题空间的特定切片内表现得很好,但在应用到其自然舒适范围之外时会变得笨拙或僵化。通过应用许多重叠的范式,我们覆盖了侧翼并守卫了后方。最终的框架比任何单个范式所能允许的都要强大得多,也更强大。

现在,这种与许多编程范式之间多情关系的代价是概念开销。仅仅了解面向对象编程不足以让你在 Rails 中玩得开心。最好也能很好地利用过程式和函数式经验。

这也适用于 Rails 的许多子语言。我们不会试图阻止你学习,比如,视图的 JavaScript 或偶尔复杂查询的 SQL。至少不会为了达到可能性顶峰。

减轻部分学习负担的方法是,简单地让入门变得容易,在理解框架的每一个方面之前,先做一些有价值的东西。出于这个原因,我们急于实现 Hello World。你的桌子已经准备好了,开胃菜也已经上桌了。

我们的想法是,通过早期提供真正有价值的东西,我们可以鼓励 Rails 从业者快速提升水平。将他们的学习之旅视为一种乐趣,而不是障碍。

推崇优美的代码

我们编写代码不仅仅是为了让计算机或其他程序员理解,而是为了沉浸在美丽的温暖光芒中。美观的代码本身就是一种价值,应该充满活力地追求。这并不意味着美丽的代码总是胜过其他考虑因素,但它应该在优先事项的桌子上占据一席之地。

那么什么是美丽的代码呢?在 Ruby 中,它通常位于原生 Ruby 习语和自定义领域特定语言的力量之间的交汇点。这是一条模糊的界线,但值得尝试去跳舞。

以下是一个来自 Active Record 的简单示例

class Project < ApplicationRecord
  belongs_to :account
  has_many :participants, class_name: 'Person'
  validates_presence_of :name
end

这看起来像 DSL,但实际上它只是一个类定义,其中包含三个类方法调用,这些调用接受符号和选项。这里没有花哨的东西。但它确实很漂亮。它确实很简单。它从这些声明中获得了巨大的力量和灵活性。

部分美感来自这些调用遵循先前的原则,例如约定优于配置。当我们调用 belongs_to :account 时,我们假设外键名为 account_id 并且它位于 projects 表中。当我们需要将 Person 的 class_name 指定为 participants 关联的角色时,我们只需要该类名定义。从它中,我们将再次推导出外键和其他配置点。

以下来自数据库迁移系统的另一个示例

class CreateAccounts < ActiveRecord::Migration
  def change
    create_table :accounts do |t|
      t.integer :queenbee_id
      t.timestamps
    end
  end
end

这是框架力量的本质。程序员根据某些约定声明一个类,例如实现 #change 的 ActiveRecord::Migration 子类,框架可以完成围绕该类的所有管道工作,并知道这是要调用的方法。

这使得程序员只需要编写很少的代码。在迁移的情况下,这不仅允许调用 rails db:migrate 将数据库升级以添加此新表,而且还允许它通过另一个调用以相反的方式删除此表。这与程序员自己完成所有这些工作并从他们自己调用的库中将工作流程缝合在一起非常不同。

不过,有时美丽的代码更加微妙。它不是关于尽可能地使某些东西变得简短或强大,而是更多地关于使声明的节奏流畅。

这两个语句执行相同的操作

if people.include? person
...
if person.in? people

但流向和重点却微妙地不同。在第一个语句中,重点在于集合。那是我们的主题。在第二个语句中,主题显然是人。两个语句的长度相差无几,但我认为第二个语句更美,更有可能让我在使用它来描述与人有关的条件时会心一笑。

提供锋利的刀具

Ruby 在其功能抽屉中包含了许多锋利的刀具。这并非偶然,而是有意为之。最著名的就是猴子补丁:修改现有类和方法的能力。

这种能力经常被嘲笑为对凡人程序员来说过于强大。来自更严格环境的人们曾经想象过各种灾难,这些灾难会因为 Ruby 语言对使用者赋予了这种能力而导致其毁灭。

如果你可以改变任何东西,还有什么能阻止你覆盖 String#capitalize,使“something bold”。capitalize 返回“Something Bold”而不是“Something bold”?这可能在你的本地应用程序中有效,但会破坏所有依赖于原始实现的辅助代码。

答案是,什么都没有。在 Ruby 中,没有任何程序化的东西可以阻止你使用它的锋利刀具来切断与理性的联系。我们通过约定、引导和教育来强制执行这种良好的意识。而不是禁止厨房使用锋利的刀具,并坚持每个人都用勺子切西红柿。

因为猴子补丁的另一面是能够完成像 2.days.ago 这样的奇迹(它返回从当前日期起两天前的日期)。现在你可能会认为这是一个糟糕的交易。你宁愿失去 2.days.ago,也不愿阻止程序员覆盖 String#capitalize。如果你的立场是如此,Ruby 可能不适合你。

然而,即使是那些为了安全而放弃这种自由的人,也很难争辩说修改核心类和方法的能力会毁掉 Ruby 作为一种语言。相反,这种语言之所以蓬勃发展,正是因为它对程序员的角色提供了不同的、激进的视角:他们可以被信任使用锋利的刀具。

不仅被信任,而且被教导如何使用这些功能强大的工具。我们可以通过假设大多数程序员都希望成为更好的程序员,能够熟练地使用锋利的刀具而不割伤自己的手指,来提升整个行业。这是一个非常有抱负的想法,它与许多程序员对其他程序员的直觉相悖。

因为当锋利刀具的价值受到质疑时,它总是与其他程序员有关。我还没有听到任何一个程序员举手说“我不能信任自己拥有这种力量,请把它从我手中拿走!”。它总是“我认为其他程序员会滥用它”。这种家长式做法从来不吸引我。

这让我们想到了 Rails。框架提供的刀具不像语言提供的那么锋利,但有些仍然足够锋利可以用来切割。我们不会为提供这些工具作为工具包的一部分而道歉。事实上,我们应该庆祝我们对同行程序员的抱负有足够的信心,敢于信任他们。

Rails 中的许多功能随着时间的推移而受到争议,被认为是“过于自由”。但目前流行的一个例子是 关注点功能。这只是对 Ruby 内置模块功能的一层薄薄的语法糖,旨在允许单个类封装多个相关但独立理解的关注点(因此得名)。

指责是,关注点为那些倾向于用对象膨胀的程序员提供了一套全新的抽屉来存放他们的杂物。这是真的。关注点确实可以这样使用。

但最大的谬误是认为,通过 *不* 提供像关注点这样的功能,即使是稍微有能力的人使用它也能优雅地部分分离概念,我们就能让程序员走上架构幸福的道路。如果你不能信任自己把厨房水槽从你塞满的关注点中拿出来,你可能不会以其他方式最终得到一个闪耀的优雅灯塔。

那些还没有学会使用锋利刀具的程序员还不会做蛋白酥皮。这里操作的词是:还。我相信每个程序员都有一个路径,如果不是一个权利,那就是成为一个完全有能力的 Ruby 和 Rails 程序员。而有能力,我的意思是足够了解何时以及如何根据他们的上下文使用抽屉里的不同且有时危险的工具。

这并不意味着放弃帮助他们到达那里的责任。语言和框架应该是耐心的导师,愿意帮助和指导任何人都能成为专家。同时认识到,通往那里的唯一可靠途径是通过错误之地:工具使用错误,一些血汗,也许还有一些眼泪。根本没有其他方法。

Ruby on Rails 是一个为厨师和那些希望成为厨师的人准备的环境。你可能一开始是洗碗,但你可以努力工作,最终管理厨房。不要让任何人告诉你,在通往成功的道路上,你不能被信任使用最好的工具。

重视集成系统

Rails 可以用于许多上下文,但它的初恋是制作集成系统:宏伟的整体!一个解决整个问题的完整系统。这意味着 Rails 关注从制作实时更新所需的前端 JavaScript 到如何在生产中将数据库从一个版本迁移到另一个版本的一切。

正如我们所讨论的,这是一个非常广泛的范围,但它并没有超出一个人能够理解的范围。Rails 的目标是让通才能够构建完整的系统。它的目的不是将专家细分为小的利基市场,然后要求整个团队来构建任何有持久价值的东西。

正是这种赋能个人的理念指向了集成系统。在集成系统中,我们可以消除许多不必要的抽象,减少层级之间的重复(例如服务器和客户端上的模板),最重要的是,在我们绝对必要之前避免将系统分散。

系统开发中的许多复杂性来自于在元素之间引入新的边界,这些边界限制了你在 A 和 B 之间进行调用的方式。对象之间的方法调用远比微服务之间的远程过程调用简单。对于那些冒险进入分布式领域的人来说,故障状态、延迟问题和依赖项更新时间表会带来一个全新的痛苦世界。

有时这种分布是必要的。如果你想为你的 Web 应用程序创建一个 API,让其他人可以通过 HTTP 调用,那么你就必须忍受这些问题(尽管处理传入请求比发送请求容易得多——你的停机时间是别人的故障状态!)。但这至少会对你的个人开发体验造成有限的损害。

更糟糕的是,系统被过早地分解成服务,甚至更糟糕的是,被分解成微服务。这种驱动力通常源于一个误解,即如果你想要一个现代互联网应用程序,你就必须多次构建系统:一次在服务器端,一次在 JavaScript MVC 客户端,一次用于每个原生移动应用程序,等等。这不是自然规律,不必如此。

完全有可能在多个应用程序和访问中共享整个应用程序的大部分内容。使用相同的控制器和视图来处理桌面 Web 和嵌入在原生移动应用程序中。尽可能地将所有内容集中在那个辉煌、宏伟的整体中:集成系统。

所有这一切都不会在速度、用户体验或其他属性方面付出太多代价,这些属性错误地吸引开发人员进行过早的分布。

这就是我们追求的“全能”:拥有独立调整和分布式应用程序的所有强大功能,同时又像一个单一的集成系统一样易于使用和理解。

进步胜于稳定

当系统像 Rails 一样存在了十多年后,它们自然会走向僵化。有无数的原因导致任何改变都可能成为某个地方某个依赖过去行为的人的问题。对于个人来说,这些都是合理的理由。

但如果我们过分倾听保守主义的声音,我们就永远看不到另一面。我们必须偶尔敢于打破和改变现状,才能进化和成长。正是这种进化将使 Rails 在未来十年(甚至更久)保持活力,并获得繁荣。

在理论上,这一切都很容易理解,但在实践中却很难接受。尤其是在你的应用程序因 Rails 主要版本中的向后不兼容更改而崩溃时。在那些时刻,我们需要记住这个价值观,即我们珍视进步胜过稳定,这将赋予我们调试故障、找出问题并与时俱进的力量。

这并不意味着可以肆意妄为地造成不必要的或过度的伤害。Rails 从 2.x 迁移到 3 的伟大迁移仍然留下了许多当时参与者的伤疤。那是一次艰难的迁移。这是一次重大的变革,让许多人长期滞留在 2.x 版本中,有些人甚至对此感到厌倦。但是,从宏观角度来看,它仍然是值得的。

这些是我们必须继续做出的艰难抉择。对于我们今天做出的改变,Rails 在五年后会变得更好吗?Rails 在未来几年会因为采用另一个问题领域,比如作业队列或 WebSockets,而变得更好吗?如果是的话,那么让我们咬紧牙关,完成这项工作。

这项工作不仅仅需要在 Rails 本身进行,还需要在更大的 Ruby 社区进行。Rails 应该走在帮助 Ruby 进步的前沿,推动其成员更快地采用更高版本。

到目前为止,我们在这方面做得很好。从我开始的时候,我们已经经历了 Ruby 1.6、1.8、1.9、2.0、2.1、2.2、2.3、2.4、2.5,现在又到了 2.6。一路走来,发生了很多重大变化,但 Rails 一直在支持 Ruby,帮助每个人更快地适应新版本。这在一定程度上是 Rails 作为 Ruby 主要推广者的特权和义务。

这对于链条中的辅助工具也是如此。Bundler 曾经是一个有争议的想法,但通过 Rails 坚持将其作为共享未来的基石,它今天已经成为理所当然的事情。资产管道和 Spring(持久命令进程)也是如此。这三者都经历过,或者仍在经历着成长的烦恼,但它们长期价值的明显性帮助我们克服了这些困难。

最终,进步主要取决于人,以及他们推动变革的意愿。这就是为什么像 Rails CoreRails Committers 这样的群体没有终身席位。这两个群体都是为那些积极致力于为框架做出贡献的人准备的。对于一些人来说,他们对这种进步的贡献可能只持续几年,我们将永远感谢他们的服务;而对于另一些人来说,这种贡献可能持续几十年。

同样,这也是为什么我们必须继续欢迎和鼓励社区新成员加入的原因。我们需要新鲜血液和新想法来取得更大的进步。

撑起一个大帐篷

Rails 有着如此多的有争议的想法,如果我们要求每个人始终对所有原则都表现出完全的敬畏,它很快就会变成一个思想封闭的隐士群体。所以我们不会这样做!

我们需要分歧。我们需要方言。我们需要思想和人的多样性。正是在这个思想的熔炉中,我们将获得最好的公共资源供所有人共享。许多人贡献自己的想法,无论是代码还是经过深思熟虑的论点。

因此,虽然这种教条描述了一种理想化的形式,但日常现实要微妙得多(也更有趣)。Rails 能够在一个帐篷下支持如此庞大的社区,正是因为几乎没有(如果有的话)试金石。

RSpec 的持续成功就是一个完美的证明,RSpec 是一个用于测试的 DSL,我经常表达我对它的强烈不满。我可以一直抱怨,说它不是正确的方法,但它仍然可以蓬勃发展。这一点才是最重要的!

Rails 作为 API 的出现也是如此。虽然我个人专注于包含视图的集成系统,但毫无疑问,Rails 有空间为那些希望提前分配客户端和服务器的人提供服务。我们应该拥抱这一点,因为它可以作为一项次要任务共存,我相信它一定可以做到。

拥有一个大帐篷并不意味着试图成为所有人的一切。它只是意味着你欢迎所有人参加你的聚会,并允许他们自带饮料。我们不需要通过邀请其他人加入我们而失去任何灵魂或价值观,我们甚至可能会学到如何调制一两种新的美味饮料。

这并非免费获得。它需要付出努力才能变得受欢迎。特别是如果你的目标不仅仅是吸引更多与现有社区成员相似的人。降低进入门槛是我们应该始终认真对待的工作。

你永远不知道下一个开始仅仅修正文档拼写错误的人最终会实现下一个伟大的功能。但如果你微笑并感谢任何微小的贡献,你就有机会发现这一点,因为这会激发他们的动力。