4997e6321dd06db9160dc733ea40c475.gif

摘要:近年来,Rust 绝对是一门成长速度飞快的编程语言,许多国内外大厂都开始关注这门年轻的语言,但本文作者表示,对于创业公司而言,Rust 可能并不是那么好。

链接:https://mdwdotla.medium.com/using-rust-at-a-startup-a-cautionary-tale-42ab823d9454

声明:本文为 CSDN 翻译,未经允许禁止转载。

作者 | Matt Welsh      

译者 | 弯月   责编 | 郑丽媛

出品 | CSDN(ID:CSDNnews)

老实说,写这篇文章时,我有点犹豫,因为我不想卷入编程语言之战。但是,有很多人问我关于使用 Rust 的体验,以及是否应该在项目中选择 Rust。因此,我想通过本文分享一些在创业环境中使用 Rust 的利弊。

我认为,从某些方面来看,Rust 确实很优秀。本文并不是要批评 Rust,我只是想说明 Rust 可能会对生产力造成重大影响,尤其是对于创业公司而言,速度是一个非常重要的考虑因素。你需要仔细权衡对公司和产品来说,选用这门编程语言带来的优势与其对产品开发速度的影响是否值得。

首先,我必须说明,Rust 非常出色地实现了其设计目标,如果你的项目需要 Rust 的特定优势(高性能、超强类型、不需要垃圾收集的系统语言),那么这将是一个不错的选择。但我认为,很多时候人们会在并不合适的情况下选用 Rust,结果导致团队因 Rust 的复杂性而付出沉重的代价,没有收获太大好处。

我有大约两年的 Rust 使用体验,主要来自于之前的一家创业公司。那是一个基于云的 SaaS 项目,产品本身基本算是一个传统的 CRUD 应用,由一组微服务构成,位于数据库前面,提供了 REST 和 gRPC API 端点,还有一些后台的微服务(实现结合了 Rust 和 Python)。我们选用 Rust 的主要原因是,公司的几位创始人都是 Rust 专家。随着时间的推移,我们的团队规模不断扩大,工程人员数增加了近 10 倍,代码库的规模和复杂性也大幅增加。

随着团队和代码库的增长,我感觉到我们为使用 Rust 付出的代价越来越沉重。开发的速度越来越迟缓,推出新功能所花费的时间也超过了预期,而且我们团队也感受到了选用 Rust 对生产力带来的负面影响。从长远来看,用另一种语言重写代码会提高开发的灵活性,并加快交付速度,但是腾出时间来重写核心代码的难度非常高。所以,我们陷入了僵局,要么继续忍受 Rust,要么硬着头皮重写大量代码。

可能你会问,Rust 应该是一门非常出色的编程语言,但为什么我们的使用感受并不好呢?

e76e672fa2fec85a761fe6c89222549e.jpeg

873ad442112d564014fb45ce570aae22.png

Rust 的学习曲线非常陡峭

纵观整个职业生涯,我使用过几十种语言,除了少数语言之外,大多数现代过程式语言(C++、Go、Python、Java 等)的基本概念都非常相似。

每种语言都有自己的特别之处,但通常你只需要学习不同语言的关键模式,就能迅速掌握并快速编写代码。然而,对于 Rust,我们需要学习许多全新的概念,比如生命周期、所有权和借用检查器等。对于大多数使用其他通用语言的人来说,这些概念都很陌生,即便是对于经验丰富的程序员来说,Rust 的学习曲线也相当陡峭。

当然,这些“新”概念原本就存在于其他语言中,尤其是函数式语言,但 Rust 将它们带入了“主流”语言环境,因此对于许多 Rust 新手来说很陌生。

尽管我的同事都是聪明且富有经验的开发人员,但团队中的许多人(包括我自己)在理解 Rust 的规范时都遇到了麻烦,比如编译器神秘的错误消息,以及如何掌握核心库。我们举办了每周例会,集体学习 Rust,以帮助大家分享知识和专业技术。随着开发速度的减慢,团队的生产力和士气都很低迷。

与之相比,我在 Google 工作时,团队采用的编程语言从 C++ 转变为 Go 只用了不到两周的时间。可这一次我们挣扎了数月,团队中的大多数人依然无法完全掌握 Rust。许多开发人员告诉我,他们经常感到很窘迫,因为开发新功能所需的时间超出了预期,而且他们需要花费大量时间思考如何使用 Rust。

4821b999dfe96a8f1de2dab5d2979c57.png

我们可以通过其他方法解决 Rust 试图解决的问题

如前所述,我们构建的服务是一个相当简单的 CRUD 应用,而且服务的负载只不过是每秒几个查询。服务背后是一个非常复杂的数据处理管道,需要数小时才能运行完成,因此服务本身不太可能成为性能瓶颈。我们不需要担心 Python 之类的传统语言会遇到的性能方面的问题。除了所有面向 Web 的服务都需要完成的处理之外,没有特殊的安全或并发要求。

我们使用 Rust 只有一个原因——因为最初编写该系统的开发人员是 Rust 专家,并不是因为 Rust 特别适合构建这种服务。

相较于开发人员的生产力,Rust 更重视安全性。在许多情况下,这种权衡并没有问题,比如构建 OS 内核代码,或者内存十分有限的嵌入式系统。但我认为并非在所有情况下这种权衡都是正确的,尤其是十分重视开发速度的创业公司。

我是一个实用主义者,我宁愿让团队花时间调试用 Python 或 Go 编写的代码偶尔出现的内存泄漏或类型错误,也不愿让团队中的每个人为了使用这种语言而导致生产力大幅下降。

如上所述,我在 Google 工作时,我们团队用 Go 构建了一项服务。过了一段时间后,该服务发展到为 8 亿用户提供支持,而且高峰期的 QPS(每秒请求数)是谷歌搜索的 4 倍。在构建和运行这个服务的那些年里,由 Go 的类型系统或垃圾收集器引发的问题,我用一只手就能数过来。

所以基本上,Rust 试图解决的问题都可以通过其他方式解决,比如良好的测试、linting、代码审查以及监控等。当然,并不是所有的软件项目都有这种奢侈的配置,所以我可以想象,在有些情况下 Rust 确实是一个不错的选择。

a3bf48f45e63e324d1334c1fac77d169.png

Rust 开发人员的招聘难度很大

在这家创业公司工作期间,我们招聘到了很多人,但在加入工程团队的 60 多人中,只有两三个人有 Rust 的使用经验——不是因为我们不想招 Rust 开发人员,而是招不到。近来,随着 Rust 的流行度增加,Rust 开发人员数量也有所增加,但在采用 Rust 时,你必须有心理准备:Rust 开发人员的招聘难度很大。

另一个你需要考虑的因素是,使用 Rust 时,团队内懂 Rust 的人和不懂 Rust 的人会分裂成两个阵营。由于我们选用了这种“深奥”的编程语言,公司内本来可以帮忙构建功能、调试生产问题的工程师也帮不上忙了,因为他们完全搞不清楚 Rust 代码。

当你需要快速开发,并将团队中每个人的力量都凝聚起来时,工程团队缺乏替补队员将成为一种巨大的劣势。根据我的经验,通常开发人员在 C++ 和 Python 等语言之间切换时没有什么困难,但 Rust 是一门新技术,而且非常复杂,因此会阻碍团队成员之间的相互合作。

a3041be3155433b90ab3022885bfd28a.png

库和文档不成熟

随着时间的推移,相信这个问题会得到解决,但与 Go 语言相比,Rust 的库和文档生态系统非常不成熟。

Go 语言的优势在于,这门语言由 Google 的整个专业团队开发和支持,因此文档和库都非常完善。相比之下,Rust 的库和文档尚在长期的开发中。许多流行库的文档非常罕见,人们常常需要阅读源代码才能了解如何使用。

团队中拥护 Rust  的开发人员经常说“async/await是一个新概念”,或者“这个库的文档很匮乏”之类的话,这些缺点对团队的影响非常大。比如,我们采用了 Actix 作为服务的 Web 框架,这是项目早期犯下了一个巨大的错误,这个决定为我们带来了巨大的痛苦,我们遇到了很多深埋于库中的错误和问题,但没有人知道如何修复。

当然,这种不成熟并不是 Rust 特有的,但这是选择 Rust 语言必须付出的代价。无论核心语言文档和教程多么出色,如果不知道如何使用这些库,一切都于事无补。

f8a889cdcb4c6b5b604da16351a6c959.png

使用 Rust 编写新功能非常困难

不知道其他人如何,但至少对我来说,在构建一个新功能时,一般我并不会事先准备好所有的数据类型、API 以及其他细节。通常,我会边想边写代码,实现一些基本的想法,然后检查我的假设是否正确。

用这种方式编写 Python 代码没有任何问题,因为你可以快速编写一些代码,诸如类型等要求,不需要担心特定的边缘情况会导致代码出错。你可以回头再整理代码,并修复所有类型错误,编写所有测试。

但是,你很难使用 Rust 编写出这种类似于“草稿”的代码,因为编译器会抱怨每一个没有通过类型以及生命周期检查的错误。如果是构建需要放入生产环境的代码,这种检查非常有意义,但我只是在测试一些想法,这些错误会打断我的思路。宏 unimplemented! 有一点帮助,但依然要求你确保所有的类型正确,不然连编译都无法通过。

当需要修改承载接口的类型签名时,虽然你只是想验证一下自己的想法是否可行,却发现需要花费数小时修改每一处使用该类型的代码,而且每一次修改,都需要检查一遍,真的很令人崩溃。

00923efe3b333543a03a4bdb36a8e34c.png

Rust 的优势

当然,Rust 也有一些我非常喜欢的优点,有一些特性我非常希望其他语言也借鉴一下。首先,match 很棒。其次,Option、Result 和 Error 特性非常强大。另外,运算符 ? 是一种优雅的处理错误的方式。可能其他语言中也有类似的特性,但 Rust 的处理尤为优雅。

如果是高度重视性能和安全性的项目,我绝对会选用 Rust。对于个人项目,或非常小的(比如 2~3 人)团队,Rust 也是一个很好的选择。最后,对于内核模块、固件、游戏引擎等项目来说,Rust 绝对是不二之选。

Logo

20年前,《新程序员》创刊时,我们的心愿是全面关注程序员成长,中国将拥有新一代世界级的程序员。20年后的今天,我们有了新的使命:助力中国IT技术人成长,成就一亿技术人!

更多推荐