私がJavaからDartに移行した理由

※ このポストは[David Morgan](https://twitter.com/__davidmorgan__ "David Morgan(@__davidmorgan__)さん | Twitter")の許可を得て[Why I moved from Java to Dart](https://hackernoon.com/why-i-moved-from-java-to-dart-8f3802b1d652#.2ks4i1nyr "Why I moved from Java to Dart")を翻訳し、投稿しています。

--------------

ある人は[JavaScriptからDartに移行した](https://hackernoon.com/why-i-moved-from-javascript-to-dart-9ff55a108ff4#.976tz1gzf "Why I moved from JavaScript to Dart")と聞いています。まあ、私の旅は少しばかり違いますが。私はJavaからDartに移行しました。そして、[adwords.google.com](https://adwords.google.com/home/#?modal_active=none "Google AdWords - Online Advertising For Your Internet Marketing Needs – Google")の一部も一緒に。

![App.java ⇒ app.dart.png](https://qiita-image-store.s3.amazonaws.com/0/37980/d9c69f9d-d9e0-c30b-51bc-392ccb912da7.png)

[AdWords](https://en.wikipedia.org/wiki/AdWords "AdWords - Wikipedia")はGoogleの収益の中心であり、今まさに[Dartで書き換え](http://news.dartlang.org/2016/03/the-new-adwords-ui-uses-dart-we-asked.html "Dart News & Updates: The new AdWords UI uses Dart — we asked why")つつあります。ところが、私が仕事しているAdWordsの一角(スキップ可能なYouTube広告を売る部分)は既に2014年からDartで動いていました。

我々のチームはDartを使うように指示されたわけではなく、そう頼まれたのでさえない、というところが面白いところです。我々はDartの能力を見出し、試す価値があると判断したのです。

重要なのは、ガラポン再構築を行わなかったことです。以前は[Java/GWT](http://www.gwtproject.org/ "[GWT]")を使っていましたが、Dart移行時には、ブラウザ上でDartと段階的に統合出来ました。Dartに精通し、またDartが成長するに連れDartに熱狂するようになり、最終的にはほぼ全てのブラウザ上のコードをJava/GWTからDartに書き換えました。

ここからが、DartがJavaよりも優れている主な理由です。

## 1. Dart SDK
あなたがJavaでコードを書いた経験が豊富なら、最も不満に感じる部分は標準ライブラリではないでしょうか。その鍵となる決断はずっと前に下され、もはや後戻りできません。Javaの[Iterable](https://docs.oracle.com/javase/7/docs/api/java/lang/Iterable.html "Iterable (Java Platform SE 7 )")とDartの[Iterable](https://api.dartlang.org/stable/1.21.0/dart-core/Iterable-class.html "Iterable class - dart:core library - Dart API")を比較するだけで、世の中がどれだけ進歩しているか理解できます。

つまり、Javaでのプログラミングの最良の方法はサードパーティーのライブラリを使うことです。Googleでは[Guava](https://github.com/google/guava "google/guava: Google Core Libraries for Java 6+")を利用していますが、かなり素晴らしいものです。例えば、Guavaには[FluentIterable](https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/FluentIterable.html "FluentIterable (Guava: Google Core Libraries for Java 19.0 API)")があります。それでも、SDKの一部ではなく、いまだに二級市民です。

Dartには全て最初からやり直すチャンスがあり、それを実践してみせました。JavaでならFluentIterableを使うであろう例を示します。

```dart
print(
    [1, 2, 3].where((x) => x.isOdd).map((x) => x + 10));
-->
(11, 13)
```
[DartPadで実行](https://dartpad.dartlang.org/53c91473ad1fa934f87959439da4f246 "DartPad")

## 2. コールバック、Future、async/await
あなたがJava/GWTでコードを書いた経験が豊富なら、「コールバック」という言葉に無意識に反応するようになっているのではないでしょうか。単にその言葉を聞いただけで冷汗をかいているはずです。

私個人は、一連のRPCの連鎖における異なるイベントを処理するためにコールバックのコールバックのコールバックの羅列である酷く恐ろしいコードを書き、メンテナンスしています。

これは比較的マシな例です。

```Java
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](https://api.dartlang.org/stable/1.21.0/dart-async/Future-class.html "Future class - dart:async library - Dart API")が有り、それに沿って標準ライブラリが設計され、全てが解消します。Dartが私に語りかけてきた瞬間でした。より良いコーディング生活のためにまさに必要なものが手に入ります。

```dart
Future<List<String>> getFoo() {
  return _getThenFilter('foo');
}

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

これに留まりません。Dartチームはasync/awaitキーワードというFutureをお洒落に使う方法を議論ていました。ただ"await"と書くだけで、あたかも同期型であるかのように非同期コーディングを進められて、すべては舞台裏で処理されるようです。

そして、[現実のものとなりました](https://www.dartlang.org/articles/language/await-async "Dart Language Asynchrony Support: Phase 1 | Dart")。長年Javaで開発してきた者として、単なる仮説による言語変更議論は自分の仕事の何の役にも立たない、と思えるようになった瞬間です。歓喜でした。

```dart
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();
}
```
[DartPadで実行](https://dartpad.dartlang.org/266eb17a9b99fdc60b61ad6c1a9002c9 "DartPad")

## 3. ナンセンス無用、ボイラープレート無用
JavaからDartに移行するとコーディング生活を楽にする非常に多くの機能に出会います。

- 標準でパブリック、"_"で始めるとプライベート
- コレクションリテラル ([お試しあれ](https://dartpad.dartlang.org/966a339d9bef24d546866f3e437e21e6 "DartPad"))
- 全てがオブジェクト (プリミティブ無し)
- 名前付きパラメタ、オプショナルパラメタ、デフォルト ([お試しあれ](https://dartpad.dartlang.org/13ab41b2107360973cfc6daee4c0768e "DartPad"))
- プロパティ ([至る所に"get"メソッドを書く必要なし](https://www.dartlang.org/resources/dart-tips/dart-tips-ep-10 "Classes: Setters & Getters - Dart Tips, Episode 10 | Dart"))
- カスケード ([全てがビルダー](http://news.dartlang.org/2012/02/method-cascades-in-dart-posted-by-gilad.html "Dart News & Updates: Method Cascades in Dart"))
- [Strong Mode](https://github.com/dart-lang/dev_compiler/blob/master/STRONG_MODE.md "dev_compiler/STRONG_MODE.md at master · dart-lang/dev_compiler")の型推論 (ローカルは単に"var"と書ける)
- 名前付きコンストラクタ、フィールドへの直接代入 ([お試しあれ](https://dartpad.dartlang.org/2378d6a79675b3f788889c1de5c798c3 "DartPad"))
- ストリング内挿、複数種のストリングリテラル ([お試しあれ](https://dartpad.dartlang.org/174ca86c2c49a3be3a44fa6237dfcfda "DartPad"))
- dartfmt (が[整形の面倒を見てくる](http://journal.stuffwithstuff.com/2015/09/08/the-hardest-program-ive-ever-written/ "The Hardest Program I've Ever Written – journal.stuffwithstuff.com")ので、あなたにその必要がない)

一つだけでもJavaプログラマーを笑顔にします。一度に全部なんてもう我慢できません、良い意味で。

## 4. さらに前へ
Dartの進化はasync/awaitで留まることはありません。最近は[ジェネリックメソッドの文法](http://news.dartlang.org/2016/12/dart-121-generic-method-syntax.html "Dart News & Updates: Dart 1.21: Generic Method Syntax")をサポートしました。非Nullタイプの試みも進められています。型システムは[Strong Mode](https://github.com/dart-lang/dev_compiler/blob/master/STRONG_MODE.md "dev_compiler/STRONG_MODE.md at master · dart-lang/dev_compiler")で改修されつつあります。

Dartは徹底的に実用本位に進化します。全ての機能は実用コードにおいて快適に動くことが求められます。なので、今後も新しい機能が登場するでしょう、良い機能だけが。

## 5. Web適正
最後に、DartにはWeb UIフレームワークがあります。実は我々はAngularDartの影も形もない時から[Web UI](https://pub.dartlang.org/packages/web_ui "web_ui 0.4.28+1 | Pub Package Manager")で始めています。その後AngularDartを利用し、現在はAngularDart 2です。全てに共通で、軽量、HTML風テンプレートがあります。

----
## 値不変性の探求
私の視点からはDartに唯一欠けていると思うものは、適切な不変コレクションと不変型のサポートです。なので、誰かが使えるパッケージを書いてくれることを期待しつつも、我々のチームで利用する何かしら動くものを急ごしらえしました。

でも、最終的にオープンソース公開に堪えるものの作成に時間を費やしました。[built_collection](https://github.com/google/built_collection.dart "google/built_collection.dart: Immutable Dart collections via the builder pattern.")と[built_value](https://github.com/google/built_value.dart "google/built_value.dart: Immutable value types, enum classes, and serialization.")の誕生です。

-----
以上です。Dartはプライムタイム出演の準備万端です。我々がAdWrod for Videoでしたように、巨大で、ミッションクリティカルなWebアプリケーションをDartで構築できます。または[Flutter](https://flutter.io/ "Welcome to Flutter! - Flutter")を手にAndroidとiOSのモバイルアプリ開発を始めることも出来ます。加えて、最近私が書いた記事のように、サーバサイドDartはクライアントサイドDartと共同して[非常に上手く](https://hackernoon.com/end-to-end-testing-in-one-short-second-with-dart-e699c8146fd6#.7vxjkync3 "End to End Testing in One Short Second with Dart")やります。

-----------

私自身の個人的な話について; Dart Developer Summitで公演を持った後間もなく、Dartチームに入りました。つまり、結果的に私そのものが「Dartに移行」しました。

## 追記
[Redditでの本記事に対する反応](https://www.reddit.com/r/programming/comments/5nrias/why_i_moved_from_java_to_dart/ "Why I moved from Java to Dart : programming")に対して幾つか注記します。

-----

SDKを補完する第三者ライブラリとして、Java 8でstreamがほぼ同じ機能を提供するFluentIterableは特段良い例ではありませんでした。
次に思い浮かぶSDKの比較例はファイル読み込みです。Dartでは単に `new File(‘foo.txt’).readAsStringSync()` とかくか、もし同期処理にしたくない場合 `await new File(‘foo.txt’).readAsString()` と書けます。Javaでは、最新の正しい書き方が何か、いつも探す必要があります。

他の例を挙げることは容易ですが、これは驚くべきことではありません。オブジェクト指向言語が辿った長い道のりの中で、DartのSDKはJavaのAPI設計よりもずっと後に構築されたのですから。

-----

この記事はブラウザ向けにJSにコンパイルするDartについて書いている、ということを強調しておきたいと思います。私が行った移行はJava/GWTからDartです。

-----

そして最後に、私が仕事で携わってきた数ある言語の中で、Javaは今でも2番めにお気に入りの言語であることを言っておきたいと思います。