Taste of Tech Topics

Acroquest Technology株式会社のエンジニアが書く技術ブログ

RxJavaを使ってCallback Hellから脱出する( Java8 ラムダ編 )

id:KenichiroMurata(@ )です。

f:id:acro-engineer:20131206014754j:plain

皆さん、RxJava 使っていますか?

前回はVert.xのmod-rxvertxを使い、RxJavaによってCallback Hellから脱出する方法を説明しました。本記事は、せっかくなのでJava8のラムダを使ったらさらにどのようになるのか?を試してみた補足記事です。

目次は以下の通りです。

  1. 環境
  2. Java8 ラムダによってCallback Hellはいかに解決されたか
  3. まとめ

1. 環境

本記事で試した環境について説明します。

  • Vert.x 2.1M1
  • mod-rxvertx 1.0.0-beta2
  • RxJava 0.15.1
  • Java 1.8.0-ea(build 1.8.0-ea-b118)
  • IntelliJ IDEA 13 CE

Java8を試すために、IntelliJ IDEA 13 CEを使いました。Java8をインストールし、IDEAを使う場合は以下のように初期化してください。

ken@vertx-test $ ./gradlew test
ken@vertx-test $ ./gradlew copyModJson
ken@vertx-test $ ./gradlew idea

2. Java8 ラムダによってCallback Hellはいかに解決されたか

まずは、通常のVert.xで書いた場合のコードのJava8 ラムダ版は次のようになります。例を分かりやすくするために、JSONメッセージの生成部などは外部メソッド化しました。

J8BusModVerticleTest.testSerialAction

  @Test
  public void testSerialAction() {
    final EventBus eventBus = vertx.eventBus();
    final ConcurrentMap<String, String> map = vertx.sharedData().getMap("muraken720.testexample");

    JsonObject req1 = createAddRequest("@muraken720");

    // リクエスト1
    eventBus.send("muraken720.vertx.mod.testexample", req1,
        (Handler<Message<JsonObject>>) reply -> {
          assertEquals("ok", reply.body().getString("status"));
          assertEquals("@muraken720", map.get("name"));

          JsonObject req2 = createAddRequest("Kenichiro");

          // リクエスト2
          eventBus.send("muraken720.vertx.mod.testexample", req2,
              (Handler<Message<JsonObject>>) reply1 -> {
                assertEquals("ok", reply.body().getString("status"));
                assertEquals("Kenichiro", map.get("name"));

                JsonObject req3 = createAddRequest("Murata");

                // リクエスト3
                eventBus.send("muraken720.vertx.mod.testexample", req3,
                    (Handler<Message<JsonObject>>) reply2 -> {
                      assertEquals("ok", reply.body().getString("status"));
                      assertEquals("Murata", map.get("name"));

                      testComplete();
                    });
              });
        });
  }

ラムダ式により、無名クラスの部分がスッキリしていますね。

それではこれをRxJavaを使ってコードを書くと次のようになります。

RxJ8BusModVerticleTest.testSerialAction

  @Test
  public void testSerialAction() {
    final RxEventBus rxEventBus = new RxEventBus(vertx.eventBus());
    final ConcurrentMap<String, String> map = vertx.sharedData().getMap("muraken720.testexample");

    JsonObject req1 = createAddRequest("@muraken720");

    // リクエスト1
    Observable<RxMessage<JsonObject>> obs1 = rxEventBus.send("muraken720.vertx.mod.testexample", req1);

    Observable<RxMessage<JsonObject>> obs2 = obs1.flatMap(reply -> {
      assertEquals("ok", reply.body().getString("status"));
      assertEquals("@muraken720", map.get("name"));

      JsonObject req2 = createAddRequest("Kenichiro");

      return rxEventBus.send("muraken720.vertx.mod.testexample", req2);
    });

    // リクエスト2
    Observable<RxMessage<JsonObject>> obs3 = obs2.flatMap(reply -> {
      assertEquals("ok", reply.body().getString("status"));
      assertEquals("Kenichiro", map.get("name"));

      JsonObject req3 = createAddRequest("Murata");

      return rxEventBus.send("muraken720.vertx.mod.testexample", req3);
    });

    // リクエスト3
    obs3.subscribe(reply -> {
      assertEquals("ok", reply.body().getString("status"));
      assertEquals("Murata", map.get("name"));

      testComplete();
    });
  }

Java8のラムダ式を使うことにより、RxJavaのAction1、Function1といった無味乾燥なクラス名も登場しなくなり、非常にスッキリしました。コード自体も縦には長くなっていますが、ネストが深くならないことがよく分かると思います。

3 まとめ

いかかでしょうか?Java8のラムダを使うことで、Callback Hellから脱出するだけでなく、その記述方法のシンプルになることがご覧頂けたと思います。Java8の正式リリースは3月?だったと思いますが、そのJava8に向けて、RxJavaもVert.xもさらに進化していくと思います。今後どのようになるのか?を想像しながら、あれこれ試してみると面白いと思います。

See also

Acroquest Technologyでは、キャリア採用を行っています。


  • 日頃勉強している成果を、Hadoop、Storm、NoSQL、HTML5/CSS3/JavaScriptといった最新の技術を使ったプロジェクトで発揮したい。
  • 社会貢献性の高いプロジェクトに提案からリリースまで携わりたい。
  • 書籍・雑誌等の執筆や対外的な勉強会の開催を通した技術の発信や、社内勉強会での技術情報共有により、技術的に成長したい。
  • OSSの開発に携わりたい。

 
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
 キャリア採用ページ