(译)为什么我从 Java 迁移到 Dart

翻译自 Why I moved from Java to Dart

听说有些人是 从 Javascript 转到 Dart,而我的经历有些不同:我是从 Java 转到 Dart。并且,我将adwords.google.com 部分功能用
Dart 改写。

AdWords 是 Google 的现金流的核心 ,现在正在用 Dart 重写。但 AdWords 中由我负责的一部分,即在 YouTube 中出售可跳过广告,早在 2014 年就是运行在 Dart 上的。

最有意思的是我们并没有被要求使用 Dart,也没有主动要求使用 Dart。我们看到了 Dart 提供的能力,然后决定尝试一下。

重要的是,我们并不是完全重写。我们最初使用 Java/GWT,可以在浏览器中将其跟 Dart 集成,以便渐近式地迁移到 Dart。随着我们起来越熟悉 Dart,我们爱上了这门语言。最终我们几乎重写了所有的浏览器代码,从 Java/GWT 迁移到了 Dart。

以下是我觉得 Dart 优于 Java 的几个原因。

Dart SDK

你写过很多 Java 代码后最大的抱怨之一可能是 SDK 库。JDK 中一些关键决定发生在若干年前,无法做出改变。你只需要看看 Java 的 Iterable 和 Dart 的 Iterable 有多大不同。

最 Java 的最好方法是引入第三方库。Google 内部使用 Guava。这个库非常棒,它提供 FutureIterable。但这个类并不在 JDK 中,所以它仍然不过是二等公民。

而 Dart 则有机会重头开始。以下这段 Dart 代码在 Java 中需要借助 FutureIterable 才能实现。

1
2
3
4
print(
[1, 2, 3].where((x) => x.isOdd).map((x) => x + 10));
-->
(11, 13)

异步回调

你写了大量 Java/GWT 代码后很可能对 “callback” 有种不自觉的反应。The merest mention brings you out in a cold sweat.

我个人写过和维护过非常恐怖的嵌套回调代码,用于处理 RPC 链中的各种条件。

这是一个相对易懂的示例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public void getFoo(AsyncCallback<List<String>> callback) {
getThenFilter("foo", callback);
}

private void getThenFilter(
final String parameter,
final AsyncCallback<String> callback) {
makeRequest(new AsyncCallback<List<String>>() {
void handle(List<String> values) {
List<String> filtered = new ArrayList<>();
for (String value : values) {
if (value.startsWith(parameter)) {
filtered.add(value);
}
}
callback.handle(filtered);
}
}

Dart 提供 Future 类,并且 SDK 的设计也是围绕这个类展开的,让异步回调变得简单。This is when it immediately became clear Dart was talking to me, personally. 它提供的东西让我的工作变得更轻松:

1
2
3
4
5
6
7
8
9
Future<List<String>> getFoo() {
return _getThenFilter('foo');
}

Future<List<String>> _getThenFilter(String parameter) {
return makeRequest().then((result) =>
result.where((string) => string.startsWith(parameter))
.toList());
}

还不止于此。await/async 关键字让 Dart 中使用 Future 变得更简单。对于可能阻塞的异步代码块,你只要写上 await 关键字即可,剩下的 Dart 帮你处理好。

使用 await/async 关键字后的代码变得更干净:

1
2
3
4
5
6
7
8
9
Future<List<String>> getFoo() {
return _getThenFilter('foo');
}

Future<List<String>> _getThenFilter(String parameter) async {
var unfiltered = await makeRequest();
return unfiltered.where(
(string) => string.startsWith(parameter)).toList();
}

去掉样本代码

从 Java 迁移到 Dart 后有如此多的特性让工作更简单:

  • 缺省的 public 访问修饰符,_ 前缀表示 private
  • 集合字面量
  • 一切皆对象,没有原型类型
  • 属性。不再需要到处写 get 方法
  • 级联。一切皆 builder
  • 强类型下的类型推断。局部变量只用写 var
  • 命名构造函数,自动给字段赋值
  • 字符串操作。多种字符串字面量
  • dartfmt。 worries about formatting dartfmt 让你不必再担心代码格式问题

语言进步

Dart 语言的进步并不只停留在添加 await/async 关键字。Dart 最近还新加了泛型方法语法以及非空类型尝试。Dart 的类型系统正在修改成强类型。

Dart 语言以实用主义方式演进,所有的新特性必须在实际代码中有用。

面向 Web

Dart 提供面向 web 的 UI 框架。实际上我们使用过 Web UI,AngularDart 以及 AngularDart2。它们的相同点是:轻量、类似 HTML 模板。这被证明是构建 UI 的好方式。

The Search for Immutability

我个人认为 Dart 最大的问题是对不可变集合以及不可变值的支持。所以我自己花时间写了两个开源库 built_collectionbuilt_value

Dart 可以用来构建大型的关键 web 应用,就像我们在 AdWords 中那样。也可以使用 Flutter 来为 Android 和 iOS 来构建移动应用。