JavaOne 2017 レポート 10/3 Day-3 技術セッション+謎のキーノート

さて、もう10日は経っていますが、粛々と3日目のレポートです。

Refactoring Design Patterns the Functional Way (in Scala)

ちょっと最初の15分ほど遅刻してしまいました。 GoFデザインパターンをいくつかピックアップして、関数型言語として良い書き方にリファクタリングしよう!という話です。

  • 良い書き方とは?
    • 以下の4つを満たす書き方
      • No Side-effects
      • No Mutation
      • No mutable SZtate
      • Declarativity
  • GoFデザインパターンリファクタリングしよう
    • Mutable Stateを取り除くケース
      • Singleton
        • Global Access → Local化
        • Mutable State → Immutable化
      • Builder
      • Chain of Responsibility
    • Mutatorを取り除くケース
      • @tailrecとか使う(?)
    • Side Effectsを取り除く
      • Observer
        • 副作用を分離するとテストが簡単になる
    • Declarative(宣言的)なコード
      • アクションを呼ぶようなコード書かない

Immutable Collections

「不変コレクション」についてのディープ目のセッション。

まずは、Java標準APIやcommons系ライブラリ、Scala、Closureなどでの不変コレクションの現状を整理。 そのあとは、Hash Array Mapped Tries(HAMTs)というトライ木を使ったアルゴリズムで効率の良い不変コレクションを実装してみたよ、みたいな話でした。

Githubリポジトリは多分これ: https://github.com/PaulSandoz/per

Modules in One Lesson

JavaのプロジェクトリードであるMark Reinhold氏のライブコーディングセッション。

f:id:nobeans:20171003110106j:plain:w300

以下、ライブコーディングを見ながらとったメモ。

  • jlinkコマンドで必要最小限のJVMが作れる
    • --outputオプションで、bin配下に好きな名前のアプリ起動コマンドも作れる
  • 実行時例外
    • 依存先モジュールがモジュールパス上に見つからないと、FindExceptionがスローされる
    • 依存先モジュールで、使おうとしているメソッドがexportsされていない場合は、IllegalAccessExceptionがスローされる

Building from Minutes to Seconds: Maximizing Incrementality with Gradle

Groovyコミッタであり、@CompileStaticを始め数々の性能向上を実現してきた、現在はGradle, Inc.にお勤めのCedric氏のGradleセッション。

f:id:nobeans:20171003121146j:plain:w300

Gradleにおけるビルド時間短縮のための4つの機能について説明。

  • なぜビルド時間を短縮するのか
    • 1分でもビルドが早くなると、人件費とかコストに直結する
  • Incremental Builds (無駄なタスク実行を避ける)
    • ソースコードが変更されてない場合はcompileタスクやtestタスクを実行する必要はない
    • input/outputを明示すると、それらで変更有無を電波できるので最小限のビルドができる
    • タスクごとにinputs/outputsを宣言しておく
    • 自前でタスククラスを実装する場合は、executeメソッドの実装でinputsをチェックしてタスクの実行/スキップを分岐する必要がある
  • Compile Avoidance (無駄なコンパイルを避ける?)
    • コンパイル時の依存関係が漏れ出す問題
      • (例)あるライブラリで実装詳細としてguavaを使っている場合、compileコンフィギューレーションにguavaを依存関係として定義して使うと...
        • 下流(=利用する側)のcompileコンフィギュレーションに、推移的にguavaが漏れ出してくる
        • ライブラリの実装詳細として依存関係の変更で、下流の依存関係が破壊されるリスクがある
      • Gradle 3.4からapi/implementationという分け方を導入した
    • 依存関係においてコンパイル/ランタイムのクラスパスは異なるセマンティクスを持つ
      • コンパイル: publicのシグネチャだけあればOK
      • ランタイム: クラス&リソースの全てが必要
      • Gradleはこの違いを表現できる
      • プロジェクトをビルドするときに無関係な変更を無視する
  • Incremental Compilation (変更があったファイルとそれに関連する部分だけをコンパイルする)
    • どうやるかはコンパイル対象の言語依存
    • Gradleは、JavaのIncremental Compilationはサポートしてる(デフォルトOFF)
      • デフォルトでONにするのはGradle 5.xぐらいになりそう
    • Q: サードパーティライブラリの定数を使っているクラスがあったとして、定数の値が変わっていたら、利用側のコンパイルも必要だと思う?
      • A: 必要。実はクラスファイルには値自体が展開されて保持されている。
        • JLSでは「コンスタントプールに入れる必要はない」と書いてあるけど、実際現状では展開されている
        • このため、Gradleでは、全てのクラスのバイトコードを解析して変更必要性を検知している(力技)
      • (以降、時間切れで割愛)
    • Annotation Processor
  • Variant-aware dependency management

Migrating to Modules

再びMark Reinholdのライブコーディング。

以下、ライブコーディングを見ながらとったメモ。

  • Automatic Modules
    • モジュール対応していないサードパーティライブラリのJARファイルなどは「Automatic Modules」として扱われる
      • JARファイルの名前規約でモジュール名が決まる
        • foo-bar.jar → foo.barモジュール
      • 依存関係上に登場する全てのモジュールをrequiresしているものとして扱う
  • エンティティやDTOなど、データバインディングフレームワークなどに使われるクラスは自モジュール外であるフレームワークから使えるようにexportsする必要がある
  • 実行時にjavaコマンドに--show-module-resolutionオプションをつけると、モジュールの解決結果が標準出力に出力される
  • jdepsが便利
    • -s/-summaryオプションをつけて実行すると、そのモジュールが必要としている他のモジュールが出力される
    • モジュール非対応のJARファイルにjdeps --generate-module-info <出力するmodule-info.javaファイルのパス> <JARファイルのパス>を実行すると、指定したファイル名でmodule-info.javaの雛形が生成される
  • インタフェースに対する実装クラスはimplパッケージなどにひとまとめにしておくと、モジュール外から隠蔽しやすい
  • requires transitive
    • requires m1;という依存関係を持つモジュールm2を、モジュールm3からrequires transitive m2;と推移的に依存しておくと、モジュールm3でrequires m2;としたときに、m3はm1とm2に依存していることになる
    • m1で提供するインタフェースをm2で実装しているようなときに、m2だけ指定すれば良いので楽 (Mavenとかの推移的依存関係みたいな感じ)

JUnit 5: New Opportunities for Testing on the JVM

JUnit 5の概要説明のセッション。

  • 挙手コーナ
    • 「テストみんな書いてる?」→ほぼ全員書いてる
    • JUnit 4?」→ほぼ全員
    • JUnit 5?」→ぽつぽつと
    • TestNG?」→なぜか笑い
    • 「Spock?」→数名
    • (他、忘れた)
  • JUnit 5はクラウドファンディングで資金を募って一から再設計&実装された
  • Java 8以上サポート (Java 7以前は未サポート)

  • JUnit 5 = Platform + Jupiter + Vintage

    • 大きく分けて3つに分かれている
      • f:id:nobeans:20171003151237j:plain:w300
      • Platform
        • テスト自体の実行エンジン
      • Jupiter
        • JUnit 5としてのテストコードを書くためのフロントエンド
      • Vintage
        • JUnit 3/4を実行するためのレガシーサポートフロントエンド
    • 独自形式のテストコードをJUnit 5 Platformで実行させるためのフロントエンドをサードパーティで提供できる構造
  • Eclipseを使ったデモ

    • Ruleはpublicフィールドに
    • Tagを使ってテストメソッドを好きに分類して、タグの種類ごとに選択式に実行できる
    • テストメソッドの引数にTestInfoを受け取れる。テスト名とかタグ名とかを動的に取り出せる
    • @TestNameでテスト名がわりに任意の文章を記述できる
      • レポートではテストメソッドの代わりにこの文章が表示される
        • 日本語テストメソッド名の制約を気にしなくてよくなった(句読点、先頭数字、とか)
      • 絵文字も対応(なぜか超盛り上がる)
    • テストクラスがネストでかける
      • フィクスチャごとにグルーピングすると便利
      • 結果レポートでもネスト構造でドリルダウン表示できる
    • Jupiterが提供するパラメタライズドテストの記法は、Spock使いとしてはやはりうーんという感想

Developer Keynote

「Live for the Code」という題目での位置付けのよくわからないキーノート。

f:id:nobeans:20171003161717j:plain:w300

Oracleクラウドを使うとこんなに簡単にサービスできますよー的な感じだったっぽい。 いわゆるスポンサー枠というか宣伝メインっぽい枠でした。 みんな大好きSlackの人が壇上に登場してました。

Automated Functional Web Testing on the JVM with Geb

CERN(欧州原子核研究機構)の人による、ブラウザを使ったテストが簡単にかけるGeb(じぇぶ)の入門的な紹介セッション。 内容的には全部知っていますが、応援の気持ちで聴講してきました。

Gebについて気になる人は、ちょうど同じ頃に公開されたこちらの記事などがおすすめです。

本日のディナー

話題沸騰(?)のメキシカンファストフード「チポトレ」のブリトーボウル(丼)にチャレンジしてみました。

f:id:nobeans:20171003200310j:plain:w300

なお、実食した結果↓

その後、Westfield(Powell Station前のショッピングモール)の4Fにあるスポーツバー的なところで、ビールと軽食をいただきました。

f:id:nobeans:20171003203412j:plain:w300