舍弃Java模式,从头开始,用Rust书写编程的未来

沉迷于Rust之美:类型安全、内存安全、注重正确性,这叫人如何不爱呢?

在开发Apollo(一款Python应用)时,遇到了许多错误。如果我使用Rust,大多数错误都能被编译器捕获(虽然无法做到百分之百,但比例应该非常高)。一般来说,编译器可以捕获许多问题,而使用动态语言(如Python或Ruby)时,这些问题有可能进入生产环境。尽管并非所有编译器都能做到这一点,但Rust强调正确性,这正是最吸引我的地方。

我在工作中编写了大量 Java 代码。虽然 Java 不是我最喜欢的语言,但它的编译时检查很强大。在进行重大重构时,Java 没有使用 Python 或Ruby 那么可怕。有了这样的编译器,遇到不正确或遗漏的导入语句,程序在运行时就会停止。虽然我们通常会通过测试来发现这些问题,但是将这些检查融入到语言中还是很有必要的。

然而 Java 编译器并不完美。它无法防止许多种错误,其中最令人头疼的就是空引用。在Java 中几乎所有东西都可以为 ,相关的错误直到运行时你才能发现。与之相反,Rust 拥有适当的结构来引导你处理未知值。当然,你可以选择忽略此类提示,但编译器会强制你做出深思熟虑的决定。

那么,Rust 是否比 Java 更好呢?Rust确实有许多让我很喜欢的地方。Rust 的承诺对我来说非常有吸引力。但我的 Rust 之旅并不全是阳光和彩虹。尽管 Rust 与 Java 有相似之处,但二者并不一样。直到停止按照 Java 的方式编写 Rust,我才发现了编写 Rust 代码的乐趣。

一切必须是接口

对于 Java 开发人员(我就是这样的开发人员)来说,一切都是接口,虽然这个说法不完全准确,但也有一定的道理。Java 中的接口使用起来很有趣。应用程序由小的工作单元组成,每个工作单元都不了解另一个工作单元的内部工作原理。建立这样的依赖关系树需要在前提付出不少努力,但一旦完成,就能拥有一支独立服务的大军供你使用。

然而,Rust 中没有接口,有的是特征(trait)。这些特征在很多方面与 Java 中的接口很相似。然而,我们不应该将 Rust 中的一切都写成特征。记住,Rust 的内存安全是一个很强大的功能。而代价是无法轻松"注入"实现特征的代码。

上面的代码无法编译,因为编译时无法确定 Named 的大小。为了解决这个问题,我们可以将这个特征放入Box ,这样我们就可以指向堆上动态分配的内存(称为 trait 对象)。Box 本身的大小已知,因此程序就可以编译了。

Box不太方便使用,因此我不太喜欢这种模式。我会尽可能避开它们。我们可以使用泛型来指定 特征类型。

这两种方式有何不同?初看之下结果是一样的。实际上二者的差异在于动态调度与静态调度。对于特征对象,具体的类型是在运行时解析的,而泛型的具体类型是在编译时解析的。

实际上,这意味着只要我们可以在编译时推断所有类型,就可以不使用泛型。如果直到运行时才能推断类型,则必须使用 Box。

所有权

所有权的问题依然存在。如果上述 Named 特征是应用程序中其他服务的必需依赖项,该怎么办?我们是否需要创建一个主Named ,然后将 &Named 传递给每个依赖项,这样就会引入生命周期?

还是说我们应该使用 Arc,这样依赖服务就可以写为 Arc<Box<dyn Named>>,从而允许并发访问所拥有的资源?

两种方法我都尝试过了,虽然可行,但都不太理想,尤其是当应用程序中的每项服务都受到影响时。

纯函数

将 Rust 当成纯粹的面向对象语言并不合适。虽然我仍然像上面的例子一样编写"服务对象",但只在必要时使用它们,实际上我更推荐纯函数。

我们来考虑一个处理结账事件的函数,该函数会更新系统中的客户 ID。

虽然我们可以将这段处理编写为一个服务,其中的 UserRepo 是一个注入值,但上面我们已经探讨过了,这样做会带来一定的复杂性。此外,我们仍然可以轻松注入 UserRepo 的不同实现,例如提供不会访问生产数据库的实现,因此也没有理由将其编写为服务。缺点在于,我们的函数签名可能会有点"繁忙",不过这种程度的"痛苦"根本不算什么。

拥抱真正的 Rust

以前我深陷"Rust 语言很难"的误区不能自拔。一个重要原因是我坚持按照其他语言的方式编写 Rust 代码。虽然汲取以往的经验很重要,但拥抱 Rust 本身的惯用写法对于掌握这门语言也很重要。只有转变心态才能真正掌握 Rust。按照不适合的方式编写 Rust 会让我们陷入苦苦的挣扎,我们应该拥抱它本来的样子。

相关推荐
星栈独行2 小时前
我在 Rust 全栈项目里用 JWT 做无状态认证
开发语言·后端·rust·前端框架·开源·github·web
Lei活在当下2 小时前
先用起来,再理解,关于协程Coroutine应该知道的事
android·java·jvm
Java爱好狂.2 小时前
Java程序员体系化学习路线(2026最新版)
java·后端·java面试·java架构师·java程序员·java八股文·java学习路线
tongluowan0073 小时前
以ReentrantLock为例解释AQS的工作流程
java·模板方法模式·aqs·reentrantlock
身如柳絮随风扬4 小时前
Java 项目打包与部署完全指南:JAR vs WAR,从构建到运行
java·firefox·jar
云烟成雨TD4 小时前
Spring AI Alibaba 1.x 系列【62】时光旅行(Time-Travel)
java·人工智能·spring
浩少7025 小时前
【无标题】
java·开发语言
一棵白菜5 小时前
java 学习
java
卷毛的技术笔记5 小时前
Java后端硬核实战:用Spring AI Alibaba+Redis给LLM装上“超强记忆中枢”
java·人工智能·redis·后端·spring·ai·系统架构
Vallelonga5 小时前
Rust Conversion 工具 trait AsRef AsMut
开发语言·rust