Rails 学说 (2016)

2021-07-29 21:47:55

因此,对于 Rails,我们决定减少一个好处,即程序员在他们的工具箱中选择每个工具的个人特权,以获得更大的一个:更好的工具箱。好处很多:数字是安全的:当大多数人以相同的默认方式使用 Rails 时,我们就有了共同的经验。这种共同点使教导和帮助人们变得更加容易。它为讨论方法奠定了基础。我们昨晚 7 点都看了同一个节目,所以我们可以在第二天谈论它。它培养了更强烈的社区意识。人们正在完善相同的基本工具箱:作为一个全栈框架,Rails 有很多活动部件,这些部件如何协同工作与它们各自独立做什么一样重要。软件中的大部分痛苦不是来自单个组件,而是来自它们的交互。当我们都致力于减轻以相同方式配置和失败的组件带来的共同痛苦时,我们都会经历更少的痛苦。替换仍然是可能的,但不是必需的:虽然 Rails 是一个 omakase 堆栈,但它仍然允许您用替代品替换某些框架或库。它只是不需要你。这意味着您可以推迟这些决定,直到您开发出一个可能更喜欢偶尔出现的差异的清晰的个人调色板。因为即使是来到并留在 Rails 的最有学问和最熟练的程序员也不可能反对菜单的所有问题。 (如果是的话,他们可能不会坚持使用 Rails。)所以他们勤奋地挑选他们的替代品,然后继续与其他人一起享受其余的策划共享堆栈。选择一个单一的中心思想并根据它得出合乎逻辑的结论作为您的架构基础具有强烈的情感吸引力。这种纪律有一种纯洁性,所以很清楚为什么程序员会自然地被这种明亮的光芒所吸引。 Rails 不是这样。它不是单一的、完美的布料。是被子。许多不同想法甚至范式的组合。如果单独和一一对比,通常会在冲突中看到许多。但这不是我们想要做的。这不是一个必须宣布唯一获胜者的优秀想法的单一冠军。以我们在 Rails MVC 饼图中构建视图的模板为例。默认情况下,所有允许我们从这些模板中提取代码的助手只是一大堆函数!它甚至是一个单一的命名空间。哦,震惊和恐怖,就像 PHP 汤!

但是我认为 PHP 在呈现很少需要交互的单个函数时做得对,就像视图模板中的很多抽象一样。为此,单一的命名空间,一大堆方法,不仅是一个合理的选择,而且是一个很好的选择。这并不意味着我们在构建视图时不希望偶尔使用更面向对象的东西。 Presenters 的概念,我们包装了许多相互依赖的方法及其下面的数据,有时可以成为解决因依赖而变质的方法汤的完美解药。但它通常被证明是罕见的而不是常见的适合。相比之下,我们通常将 MVC 层蛋糕中的模型视为面向对象优势的主要堡垒。为对象找到正确的名称,增加一致性并降低耦合是领域建模的乐趣。这是一个与视图非常不同的层,所以我们采用了不同的方法。但即使在这里,我们也不认同单一范式教条。 Rails 关注点,Ruby 的 mixin 的特殊性,通常用于为单个模型提供非常广泛的表面积。这非常适合 Active Record 模式,让相关方法可以直接访问它们与之交互的数据和存储。甚至 Active Record 框架的基础也冒犯了一些纯粹主义者。我们将与数据库直接交互所需的逻辑与业务领域和逻辑混合在一起。如此混杂的境界!是的,因为它被证明是一种实用的方法来为 web 应用猫设置皮肤,它实际上总是与某种数据库对话以保持域模型的状态。在意识形态上如此灵活是使 Rails 能够解决如此广泛的问题的原因。大多数个人范式在问题空间的某个部分内表现得很好,但当超出其自然舒适范围时会变得笨拙或僵化。通过应用许多重叠的范例,我们覆盖了侧翼并保护了后方。最终的框架比任何个人范式所允许的都要强大得多。现在,这种与许多编程范式的多元关系的成本是概念上的开销。仅仅了解面向对象的编程就可以愉快地使用 Rails 是不够的。最好同时提供程序和功能体验。

这也适用于 Rails 的许多子语言。我们不会试图让您免于学习,例如,用于视图的 JavaScript 或用于偶尔复杂查询的 SQL。至少不会达到可能性的顶峰。减轻一些学习负担的方法是简单地让入门变得容易,在你理解框架的每一个方面之前,创造一些真正有价值的东西。出于这个原因,我们急于进入 Hello World。您的餐桌已经准备好,开胃菜已送达。我们的想法是通过尽早提供真正有价值的东西,我们将鼓励 Rails 的从业者快速升级。接受他们的学习之旅是一种乐趣,而不是障碍。我们编写代码不仅是为了让计算机或其他程序员能够理解,而且是为了沐浴在美的温暖光芒中。美观的代码本身就是一种价值,应该充满活力地追求。这并不意味着漂亮的代码总是胜过其他问题,但它应该在优先级表中占有一席之地。那么什么是漂亮的代码呢?在 Ruby 中,它通常介于原生 Ruby 习语和自定义域特定语言的强大功能之间。这是一条模糊的线,但值得尝试跳舞。这看起来像 DSL,但它实际上只是一个类定义,带有三个接受符号和选项的类方法调用。这里没什么好看的。但它肯定很漂亮。这当然很简单。它从这几个声明中提供了巨大的力量和灵活性。美的一部分来自于这些对先前原则的尊重,比如约定优于配置。当我们调用belongs_to :account 时,我们假设外键称为account_id 并且它位于projects 表中。当我们必须将 Person 的 class_name 指定给参与者关联的角色时,我们只需要该类名定义。我们将再次从中派生外键和其他配置点。

class CreateAccounts < ActiveRecord::Migration def change create_table :accounts do |t| t.integer :queenbee_id t.timestamps end end end 这就是framework power的本质。程序员根据某些约定声明一个类,例如实现#change 的 ActiveRecord::Migration 子类,框架可以完成所有相关工作,并且知道这是要调用的方法。这使得程序员只需编写很少的代码。在迁移的情况下,这不仅允许调用 rails db:migrate 来升级数据库以添加这个新表,它还允许它以另一种方式通过另一个调用删除这个表。这与让所有这些发生并从他们自称为库中将工作流拼接在一起的程序员大不相同。然而,有时漂亮的代码更微妙。与其说是制作尽可能简短或强大的东西,不如说是制作声明流程的节奏。但流程和重点略有不同。在第一条语句中,重点是集合。那是我们的主题。在第二个陈述中,主语显然是人。两个陈述之间的长度并不多,但我会争辩说,第二个陈述要漂亮得多,并且在与人有关的情况下使用时可能会让我微笑。 Ruby 在其功能抽屉中包含了许多锋利的刀具。不是偶然,而是设计。最著名的是猴子补丁:改变现有类和方法的能力。这种力量经常被嘲笑为对于普通的程序员来说太过分了。来自更严格环境的人们过去常常想象各种灾难会毁灭 Ruby,因为该语言向其演讲者展示了此功能的巨大信任。

如果您可以更改任何内容,有什么可以阻止您覆盖 String#capitalize 以便“something bold”.capitalize 返回“Something Bold”而不是“Something bold”?这可能适用于您的本地应用程序,但会破坏依赖于原始实现的各种辅助代码。没什么,就是答案。 Ruby 中没有任何编程方式可以阻止您使用其锋利的刀具来与理性断绝关系。我们通过惯例、推动和教育来强化这种良好的感觉。不是禁止在厨房使用锋利的刀具并坚持每个人都用勺子切西红柿。因为猴子修补的另一面是能够完成诸如 2.days.ago 之类的奇迹(从当前日期返回两天前的日期)。现在你可能会认为这是一笔糟糕的交易。如果这意味着阻止程序员覆盖 String#capitalize,你宁愿失去 2.days.ago。如果这是您的职位,Ruby 可能不适合您。然而,很难——即使对于那些会为了某种安全而放弃这种自由的人——争辩说改变核心类和方法的能力已经注定了 Ruby 作为一种语言。相反,该语言之所以蓬勃发展,正是因为它为程序员的角色提供了一种不同而激进的观点:他们可以用锋利的刀来信任。不仅值得信赖,而且还教他们如何使用这种功能强大的工具。假设大多数程序员都想成为更好的程序员,能够挥舞锋利的刀而不切断他们的手指,我们可以提升整个职业。这是一个令人难以置信的有抱负的想法,并且与许多程序员对其他程序员的直觉背道而驰。因为在争论利刃的价值时,总是与其他程序员有关。我还没有听到一个程序员举手说“我不能相信自己拥有这种力量,请把它从我身边拿走!”。总是“我认为其他程序员会滥用它”。那种家长式作风从来没有吸引过我。这将我们带到了 Rails。框架提供的刀具不像语言提供的刀具那么锋利,但有些仍然非常热衷于切割。我们不会为提供此类工具作为套件的一部分而道歉。事实上,我们应该庆祝对我们的程序员同行的愿望有足够的信心,敢于信任他们。

随着时间的推移,Rails 中的许多功能都被认为“太自由”了。但目前流行的一个例子是关注特征。这是围绕 Ruby 模块的内置特性的一层薄薄的语法糖,旨在允许单个类封装多个相关但独立理解的关注点(因此得名)。指控是担心为程序员提供了易于膨胀的对象,他们用一套全新的抽屉来塞满他们的杂物。这是真的。确实可以这样使用关注点。但是巨大的谬误是认为通过不提供像关注点这样的功能,即使是能力稍弱的人也可以使用它来雄辩地部分分离概念,我们会让程序员走上架构幸福的道路。如果不能信任您将厨房水槽排除在过度担心的问题之外,否则您可能不会最终获得优雅的闪亮灯塔。没有学会使用锋利的刀的程序员还不会制作蛋白酥皮。这里的操作词:然而。我相信每个程序员都有自己的道路,即使没有权利,也可以成为完全有能力的 Ruby 和 Rails 程序员。我所说的有能力,我的意思是知识渊博,知道他们应该何时以及如何,根据他们的情况,使用抽屉里不同的、有时是危险的工具。这并没有放弃帮助他们实现目标的责任。语言和框架应该是耐心的导师,愿意帮助和指导任何人成为专家。虽然认识到唯一可靠的路线是通过错误的土地:使用错误的工具,一点点鲜血,一点汗水,甚至一些眼泪。没有别的办法。 Ruby on Rails 是一个适合厨师和希望成为厨师的人的环境。您可能会从洗碗开始,但您可以逐步管理厨房。不要让任何人告诉您,作为该旅程的一部分,您不能信任行业中最好的工具。 Rails 可以在许多环境中使用,但它的最爱是集成系统的制作:雄伟的单体!一个解决整个问题的完整系统。这意味着 Rails 关注从进行实时更新所需的前端 JavaScript 到在生产中如何将数据库从一个版本迁移到另一个版本。

正如我们所讨论的,这是一个非常广泛的范围,但不会比对单个人的实际理解更广泛。 Rails 专门寻求装备通才的人来制作这些完整的系统。它的目的不是将专家分成小众的领域,然后需要整个团队来构建任何具有持久价值的东西。正是这种对赋予个人权力的重点指向集成系统。在集成系统中,我们可以删除许多不必要的抽象,减少层之间的重复(如服务器和客户端上的模板),最重要的是,避免在我们绝对必须之前分发我们的系统。系统开发中的大部分复杂性来自于在元素之间引入新边界来限制您在 A 和 B 之间进行调用的方式。对象之间的方法调用远比微服务之间的远程过程调用简单。等待着那些冒险进入分发巢穴的人在失败状态、延迟问题和依赖更新计划方面有一个全新的世界。有时这种分配是必要的。如果您想为您的 Web 应用程序创建一个 API,其他人可以通过 HTTP 调用它,那么您只需要解决它并处理其中的许多问题(尽管处理入站请求而不是将它们发送出站要容易得多——您的停机时间是其他人的故障状态!)。但这至少对您自己的个人发展经历造成了有限的损害。更糟糕的是,系统过早地分解并分解为服务,甚至更糟的是微服务。这个驱动经常源于这样一种误解,即如果你想要一个现代互联网应用程序,你只需要多次构建系统:一次在服务器端,一次在 JavaScript MVC 客户端,一次用于每个本机移动应用程序等。这不是自然法则,也不必如此。跨多个应用程序和访问共享整个应用程序的大块是完全可能的。为桌面 Web 使用与嵌入在本机移动应用程序中相同的控制器和视图。尽可能地集中在那个辉煌、雄伟的巨石中:集成系统。所有这一切都没有在速度、用户体验或其他错误地吸引开发人员过早发布的属性方面放弃太多。

这就是我们所寻求的最重要的东西:单独调整和分布式应用程序的所有功能,以及单个集成系统的易用性和理解能力。当系统已经存在了十多年时,就像 Rails 一样,它们的自然趋势是趋于僵化。对于依赖过去行为的某个人来说,每一次变化都可能成为问题的原因有一百万个。对于个人而言,这些也是合理的理由。但是,如果我们过于仔细地倾听保守主义的声音,我们将永远看不到另一边是什么。我们必须敢于偶尔打破和改变事物发展和成长的方式。正是这种演变将使 Rails 在未来几十年(s?)中适合生存和繁荣。这在理论上很容易理解,但在实践中很难接受。特别是当您的应用程序从 Rails 的主要版本中向后不兼容的更改中中断时。正是在那个时候我们需要记住这个价值观,我们珍惜进步而不是稳定性,给我们力量去调试被破坏的东西,弄清楚它并与时俱进。这不是随意造成不必要或过度伤害的许可。 2.x 到 3 的大 Rails 迁移仍然在许多为此而生的人的伤疤组织中徘徊。这是一场艰难的比赛。一场严重的剧变让许多人在 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 Core 或 Rails Committers 这样的团体中没有终身席位的原因。这两个组都是为那些积极致力于为框架取得进展的人准备的。对于某些人来说,他们在这种进步中的利益可能只会持续几年,我们将永远感谢他们的服务,而对于其他人来说,这种服务可能会持续几十年。同样,这也是我们继续欢迎和鼓励社区新成员如此重要的原因。我们需要新鲜的血液和新鲜的想法来取得更好的进展。有了这么多有争议的想法,Rails 可能很快就会成为一个孤立的意识形态隐士,如果我们要求每个人始终表现出对所有原则的完全尊重。所以我们不!我们需要分歧。我们需要方言。我们需要思想和人的多样性。正是在这个想法的大熔炉中,我们将获得最好的共享资源以供所有人分享。许多人在代码或经过深思熟虑的争论中花两分钱。因此,虽然这一学说描述了一种理想化的形式,但日常现实要微妙得多

......