Architecture Decision Record

Active theme: Light

← 决策记录示例

编程语言

目录:

摘要

问题

我们需要为软件选择编程语言。我们有两大需求:一门适合 Web 应用的前端编程语言,以及一门适合服务器应用的后端编程语言。

决策

前端我们选择 TypeScript。

后端我们选择 Rust。

状态

已决定。对出现的新备选方案持开放态度。

详情

假设

前端应用是典型的:

  • 典型的用户和交互

  • 典型的浏览器和系统

  • 典型的开发和部署

前端应用很可能会快速演进:

  • 我们希望确保快速、轻松的开发、部署、迭代等。

  • 我们重视可证明性,例如类型安全,并且愿意为此多做一些工作。

  • 我们不需要遗留兼容性。

后端应用的要求高于典型水平:

  • 对质量的目标高于典型水平,尤其是可证明性、可靠性、安全性等。

  • 对近实时性的目标高于典型水平,也就是说,我们不希望出现因虚拟机垃圾回收造成的停顿。

  • 对函数式编程的目标高于典型水平,尤其是在并行化、多核处理和内存安全方面。

我们接受较低的编译速度,以换取编译期安全性和运行时速度。

约束

我们对可用于主要云服务提供商的函数服务(例如 Amazon Lambda)的语言有很强的约束。

立场

我们考虑了以下语言:

  • C

  • C++

  • Clojure

  • Elixir

  • Erlang

  • Elm

  • Flow

  • Go

  • Haskell

  • Java

  • JavaScript

  • Kotlin

  • Python

  • Ruby

  • Rust

  • TypeScript

论证

各语言总结:

  • C:因安全性低而被否决;Rust 几乎在所有方面都能做得更好。

  • C++:因其混乱而被否决;Rust 几乎在所有方面都能做得更好。

  • Clojure:建模能力出色;最接近的 Lisp 近似实现;在 JVM 上拥有出色的运行时。

  • Elixir:运行时出色,包括可部署性和并发;开发者体验出色;生态系统相对较小。

  • Erlang:运行时出色,包括可部署性和并发;开发者体验具有挑战性;生态系统相对较小。

  • Elm:看起来非常有前景;IBM 正在发布效果良好的重要案例研究;生态系统较小。

  • Flow:对 JavaScript 的有趣改进;然而,开发者正在逐渐放弃它。

  • Go:开发者体验出色;并发出色;但有一系列严重削弱该语言的糟糕决策的记录。

  • Haskell:最好的函数式语言;开发者社区较小;尚未取得足够多已公开的生产环境成功案例。

  • Java:运行时出色;生态系统出色;开发者体验欠佳。

  • JavaScript:有史以来最流行的语言;最广泛的生态系统。

  • Kotlin:修正了 Java 的许多问题;有 JetBrains 的有力支持;有良好的从 Java 移植到 Kotlin 的公开案例。

  • Python:系统管理方面最流行的语言;出色的分析工具;良好的 Web 框架;但已被 Google 弃用而转向 Go。

  • Ruby:有史以来最好的开发者体验;最好的 Web 框架;最友善的社区;但非常慢;打包有些困难。

  • Rust:最好的新语言;强调零抽象代价;强调并发;然而生态系统相对较小;并且对某些类型的编译器加速有刻意的限制,例如直接内存访问需要显式标记为 unsafe。

  • TypeScript:为 JavaScript 增加了类型;出色的转译器;开发者越来越重视从 JavaScript 移植到 TypeScript;有 Microsoft 的有力支持。

我们认为虚拟机(VM)有一系列我们目前不需要的权衡,例如为提供运行时能力而带来的额外复杂性。

我们认为,我们的核心决策由两个贯穿性的关注点驱动:

  • 为了获得最快的运行时速度和最紧密的系统访问,我们会选择 JavaScript 和 C。

  • 为了获得接近最快的运行时速度和接近最紧密的系统访问,我们选择 TypeScript 和 Rust。

荣誉提名授予那些在我们想要选择 VM 语言时会选用的 VM 语言和 Web 框架:

  • Clojure 和 Luminus

  • Java 和 Spring

  • Elixir 和 Phoenix

影响

前端开发人员需要学习 TypeScript。如果开发人员的主要经验是使用 JavaScript,学习曲线可能比较容易。

后端开发人员需要学习 Rust。如果开发人员的主要经验是使用 C/C++,学习曲线可能为中等;如果开发人员的主要经验是使用 Java、Python、Ruby 或类似的内存托管语言,学习曲线可能较难。

TypeScript 和 Rust 都相对较新。这意味着许多工具尚未提供针对这些语言的文档。例如,DevOps 流水线需要为这些语言进行设置,而到目前为止,我们正在评估的 DevOps 工具都没有针对这些语言的默认示例。

TypeScript 和 Rust 的编译时间相当慢。其中一部分可能是由于这些语言较新。我们可能需要研究如何缓解缓慢的编译时间,例如按需编译、并发编译等。

对这些语言的 IDE 支持尚未普及,也尚未达到一流水平。例如,JetBrains 销售对 Python 提供一流支持的 PyCharm IDE,但没有销售对 Rust 提供一流支持的 IDE;相反,JetBrains 可以使用一个 Rust 插件,它提供的 Rust 语言支持相对于 Python 语言支持大约为 80%。

相关内容

相关决策

我们将致力于做出与这些语言相一致的生态系统选择。

例如,我们想选择对这些语言具有良好支持能力的 IDE。

例如,对于我们的前端 Web 框架,我们更有可能选择倾向于 TypeScript 的框架(例如 Vue),而不是倾向于纯 JavaScript 的框架(例如 React)。

相关需求

我们的整个工具链必须支持这些语言。

相关制品

我们预计可能会将一些密钥导出到环境变量中。

相关原则

三思而后行(Measure twice, build once)。我们将一定的安全性置于一定的速度之上。

运行时比编译时更有价值。我们优先考虑客户的使用,而不是开发者的使用。

备注

此处填写任何备注。