Benefits of Applying Software Design Patterns to Backend Rust Applications
本文通过实证评估了将 typestate 和 newtype 设计模式应用于生产级 Rust 后端程序的影响,发现虽然 typestate 以牺牲可读性为代价显著提升了无错性和可测试性,但 newtype 模式通过防止无效运行时状态,以较低的投入提供了高质量的回报。
原始论文采用 CC BY 4.0 许可(http://creativecommons.org/licenses/by/4.0/)。 这是对下方论文的AI生成解释。它不是由作者撰写或认可的。如需技术准确性,请参阅原始论文。 阅读完整免责声明
想象一下你正在建造一台复杂的机器,比如一台高端咖啡机。你希望它既快速、可靠,又在出现问题时易于维修。在计算机软件的世界里,Rust 语言就像一位非常严谨、注重安全的工程师,他拒绝让你制造出任何以后可能会泄漏或损坏的东西。但即便有了这样一位严谨的工程师,你仍然需要一份优秀的蓝图,以确保机器易于理解和修改。
这篇论文是一项关于使用特定的“蓝图”(称为设计模式)是否能让 Rust 软件变得更好的研究。作者 Leon Heuer 通过将德国零售商(OTTO)的三个真实世界软件组件进行重构,并使用了两种特定的蓝图:Typestate 模式和 Newtype 模式,来验证这一观点。
以下是他研究结果的简单拆解,使用了日常类比:
1. 问题所在:“洗水池”式代码 (The "Kitchen Sink" Code)
在进行更改之前,软件看起来就像一个把所有东西都堆在一起的巨大洗水池。
- 问题: 一个单一的函数试图完成所有事情:检查用户是否已登录、获取数据、验证数字以及保存结果。它冗长且混乱,如果你修改了其中一部分,可能会意外破坏远处不相关的部分。
- 风险: 很容易犯错,比如尝试打开一扇尚未解锁的门。计算机不会阻止你,直到你实际运行程序并导致崩溃为止。
2. 解决方案:两种新蓝图
蓝图 A:Newtype(身份识别证/标签)
类比: 想象你有一盒乱七八糟的钥匙。有些开前门,有些开后门,有些只是装饰用的。如果你把一把“前门钥匙”递给“后门”锁,什么都不会发生,直到你尝试使用它,然后你就被卡住了。
修复方法: Newtype 模式就像是在每一把钥匙上贴上独特的标签。你创建一个专门的“前门钥匙”盒子。你不能误把“后门钥匙”放进这个盒子里。
- 发生了什么: 作者将原始文本(例如一串数字)包装在一个特殊的“已验证 (Validated)”盒子中。如果文本无效,这个盒子就无法关闭。
- 结果: 这是一个巨大的胜利。它的成本很低,使代码更易读,并防止了无效数据进入系统。这就像是在门口设立了一名保安,在任何人进入之前都会检查身份证件。
蓝图 B:Typestate(流水线)
类比: 想象正在制造一辆汽车。你不能在组装好车架之前就给车喷漆,也不能在车架准备好之前就把发动机装进去。在旧代码中,程序员可能会在车架存在之前就尝试喷漆,而计算机直到喷漆失败时才会阻止他们。
修复方法: Typestate 模式将代码变成了一条严格的流水线。
- 第 1 步: 你从一个“原始车架 (Raw Frame)”状态开始。
- 第 2 步: 只有当你拥有“原始车架”时,你才能执行“安装发动机 (Build Engine)”的操作。一旦完成,原有的车架就会消失,变成一个“带发动机的车架 (Frame with Engine)”。
- 第 3 步: 只有当你拥有“带发动机的车架”时,你才能进行“喷漆 (Paint)”。
- 结果: 计算机在物理层面上阻止你以错误的顺序进行操作。如果你尝试为一个不存在的车架喷漆,代码甚至无法通过编译(它无法构建出该软件)。
- 权衡: 这使得代码极其安全且易于测试,但也增加了大量的“样板代码 (Boilerplate)”(额外的编写工作)。这就像为了流水线的每一个步骤都必须填写一份表格。它更安全,但需要更多的文书工作。
3. 研究结果:奏效了吗?
作者通过三种方法测试了这些更改:运行代码以观察其速度、使用自动化工具统计复杂度,以及采访专家程序员。
- 速度: 这些更改并没有减慢软件的速度。新蓝图带来的“额外文书工作”处理得极快,以至于计算机甚至察觉不到。
- 安全性(无故障性): 这一点得到了巨大的提升。新的蓝图使得创建“无效状态”(如一辆没有轮子的车)变得不可能。过去在软件运行时发生的错误,现在在软件构建之前就能被发现。
- 测试: 代码变得更容易测试了。你不再需要测试整个巨大的洗水池,而是可以单独测试流水线中的每一个小步骤。
- 可读性: 结果褒贬不一。
- Newtype(身份识别证)让事情变得更清晰。
- Typestate(流水线)让事情变得更安全,但一些专家认为额外的代码在初看之下会让代码难以阅读。然而,一旦你理解了这种模式,逻辑其实变得更容易遵循了。
4. 底线结论
研究得出结论:
- Newtype 是一个“无需多言的选择 (No-brainer)”。它是一个微小的改变,却能带来安全性与清晰度的巨大收益。每当你处理需要验证的数据(如电子邮件地址或价格)时,都应该使用它。
- Typestate 功能强大但较重。它最适合用于那些操作顺序至关重要的复杂规则场景(如多步骤结账流程)。如果流程简单且是直线型的,那么额外的代码可能并不值得。
简而言之,在 Rust 中使用这些模式,就像是从一个杂乱的作坊升级到了一个配备了安全防护装置和严格流水线的工厂。虽然前期需要更多的规划,但最终的产品更难损坏,也更容易维修。
您所在领域的论文太多了?
获取与您研究关键词匹配的最新论文每日摘要——附技术摘要,使用您的语言。