「テストでは品質は上がらない」のは確かにそうなんだけど、品質を上げるためにテストは不要かというとそうではない
はじめに
まあ私も咳さんから学んだのですけどね! https://t.co/O1NtxxMB2a pic.twitter.com/wUCCU0dT1X
— Takuto Wada (@t_wada) 2024年10月26日
という古くから伝わる名言に関して、個人的にもかなり「なるほど」という学びがあり、頭が整理されたきっかけになった記憶があります。
ただ、この名言がうっかりすると全然違う結論を導くために使われうるなぁという危うさを感じていて、久しぶりにツイッター(X)で目にしたタイミングでふと思い出したので、その気持ちを記しておきたい所存です。
どこに危うさを感じているのか
まず気になるのはこれ。
- (A) この言説が品質テストをdisるために誤用されてはいないか
あと、ふわっと気になるのは、以下の2点です。
- (B) テストで見つかった問題に対してどう対処(=プログラミング)するのかが重要だという話がわかっているのか
- (C) テスト前の実装作業(=プログラミング)においてどうやってるのかが死ぬほど重要だという話がわかっているのか
個人的な解釈
元の発言の正しいお気持ちは直接伺ったことはないのでわかりませんが、個人的には次のように理解しています。
- テストとは実装された振る舞いを観測をしつつ、期待される挙動との差分がないかをチェックすることなので、いくらどのような観測をしたところで、対象物が改善されることはない
- テストという観測手段によって、期待とは異なる挙動が見つかった時に、それを修正する作業(=プログラミング)を通して、対象は改善される
- (さらに追加するとすれば) 元々の実装作業として、適切なスキルを持った人が実装しているか、だったり、よりよいプラクティスを導入しているか、だったり、実装(=プログラミング)上の頑張りによってテストで観測されても問題が見つからないように品質をあらかじめ確保しておくのが重要である
それを踏まえた上での解釈上の危うさ
(A) この言説が品質テストをdisるために誤用されてはいないか
「チェックのためにテストは当然必要なんだけど、品質を上げる作業自体はプログラミングにあるんよ?」という話のはずが、「品質を上げるためにプログラミングを頑張ればテストなんて不要になるんや」と誤解されてないですよね、という話です。
これは単純に国語的な読解力に対する懸念です。
「いや、そんな解釈をする人なんて普通いないでしょ」と思いたいところですが、最近ではそういう解釈も個人ごとに色々多様性がある世の中ですし、あまり楽観的にはいられないのでは...という懸念がある、という心配性おじさんの妄想なのですが、いや意外と危うい気がしているので書いておきたいなぁ、というそういう気持ちです。 完璧に理解されているみなさまは生暖かくスルーしていただいていいんですよ...。
(B) テストで見つかった問題に対してどう対処(=プログラミング)するのかが重要だという話がわかっているのか
たとえば、見つかったバグに対してその場しのぎのワークアラウンドコードを仕込むことで指摘された事象自体は改善されたように見えるかもしれません。 しかし、そのコードがたとえば「ひどい変数/関数名を使っている」「概念上無関係な関数に意図のわかりづらいコードを追加している」とかの問題を孕んでいると、最終的なソースコードとしての品質が上がったのか?という点でかなり疑問がある結果になってしまいます。 そのバグは修正されたかもしれないけど、コードの可読性が低下して(品質的な用語でいえば)保守性が低下してしまった、という見方もありえます。
つまり、テストで発見された品質上の問題を解消するための修正作業(=プログラミング)で下手を打ったら、それは品質が向上したとは言い難い別の世界線に遷移してるだけという可能性もある、という話ですね。
(C) テスト前の実装作業(=プログラミング)においてどうやってるのかが死ぬほど重要だという話がわかっているのか
これについては、本質的にはもっとも重要な話で、基本的にこのレベルで成果物の最終的な品質が決まる、という風に個人的には思ってますが、じゃあ何をすればそこがいい感じになるのか、というのは観点が多岐に渡るので、今回はスルーします。
おわりに
というわけで、テストでは直接品質はあがらないのですが、テストで問題を見つけることで品質を上げるための修正(=プログラミング)をするチャンスは生まれますし、そこで品質を上げることができるかはその修正(=プログラミング)の内容による、という話でありつつ、そもそもテスト以前の実装フェーズでのプログラミングで品質を上げるというのが実は一番重要なんですよね、という構造になっているというその辺りの気持ちが伝わればうれしいです。
補足
元のTwitter(X)の議論は「テストコードの存在が直接品質を担保しているわけではないので、テストコードがたくさんある=品質を向上させている、ではない」「バグの検出に役立たない冗長なテストコードはむしろ害悪」という話だと思っていて、今回の記事はそこは全然否定していないというか、全面的に同意です。
Groovy 2.5.0で追加されたgroovy.transform.AutoFinalを試してみた
最新のGroovy 2.5.0から、groovy.transform.AutoFinal
というAST変換が追加されていたらしい。
ついさっきPaul King氏のツイートを目にして初めて知った。
I agree with you. In Groovy, we added @AutoFinal to add them implicitly for those that want them but don't want to see them.
— Paul King (@paulk_asert) 2018年9月13日
気になったので早速試してみた。
まずは@AutoFinal
なし。
class Person { String firstName String lastName Person(String firstName, String lastName) { lastName = lastName.toUpperCase() // あえてパラメータに再代入する(普通はこんなことしちゃダメ) this.firstName = firstName this.lastName = lastName } String toString() { "$firstName $lastName" } } def p = new Person("Nobunaga", "Oda") assert p.toString() == "Nobunaga ODA"
普通に実行できる。
で、クラスに@AutoFinal
アノテーションをつけてみる。
import groovy.transform.* @AutoFinal // <--- これを追加しただけ class Person { String firstName final String lastName Person(String firstName, String lastName) { lastName = lastName.toUpperCase() // あえてパラメータに再代入する(普通はこんなことしちゃダメ) this.firstName = firstName this.lastName = lastName } String toString() { "$firstName $lastName" } } def p = new Person("Nobunaga", "Oda") assert p.toString() == "Nobunaga ODA"
これを実行しようとすると、
1 compilation error: The parameter [lastName] is declared final but is reassigned
と、コンパイルエラーになった。
というように、@AutoFinal
をつけると、AST変換によって全てのコンストラクタ引数、メソッド引数、クロージャ引数に暗黙のfinalが付与されて、コンパイルチェックされるようになる。
これはいいかもしれない。
(おまけ) プロパティのfinal
化=不変化
なお、
import groovy.transform.* @AutoFinal class Person { String firstName String lastName Person(String firstName, String lastName) { //lastName = lastName.toUpperCase() // このエラーは今は興味ないのでコメントアウト this.firstName = firstName this.lastName = lastName } String toString() { "$firstName $lastName" } } def p = new Person("Nobunaga", "Oda") assert p.toString() == "Nobunaga Oda" // プロパティは再代入可能 p.firstName = "Nobunari" assert p.toString() == "Nobunari Oda"
は普通に実行できる。つまりプロパティは再代入可能なままなので注意。
プロパティを再代入不可能にするには、groovy.transform.Immutable
という前からあるAST変換を使えばOK。
簡単に不変オブジェクトにできる。
import groovy.transform.* @Immutable class Person { String firstName String lastName // @Immutableを使った場合は、Mapを受け取るコンストラクタと // プロパティ定義順にしたがって全部受け取るコンストラクタが自動生成される。 // 明示的なコンストラクタを実装するとエラーになる。 // Error during ImmutableBase processing. Explicit constructors not allowed for class: Person // //Person(String firstName, String lastName) { // //lastName = lastName.toUpperCase() // このエラーは今は興味ないのでコメントアウト // this.firstName = firstName // this.lastName = lastName //} String toString() { "$firstName $lastName" } } def p = new Person("Nobunaga", "Oda") assert p.toString() == "Nobunaga Oda" // プロパティは再代入不可能になる p.firstName = "Nobunari" assert p.toString() == "Nobunari Oda"
groovy.lang.ReadOnlyPropertyException: Cannot set readonly property: firstName for class: Person
コンパイルエラーではなく、実行時に例外が発生する点がちょっと違う。
Gaiden Filters/Extensions活用のススメ
はじめに
久しぶりのブログ記事です。 この記事は、G* Advent Calendarの13日目として書いています。 昨日はきょんさんによるGroovyのAST変換事情で、明日もきょんさんの予定です。
Gaidenとは?
数年前にGaidenというドキュメント作成ツールひっそりとリリースして、弊社の社内ではそこそこ活用していたりします。
特徴は、↓という感じです。
- Markdownでソースを執筆する
- Sphinxライクな複数ページのHTMLドキュメントを生成できる
- Gaidenラッパーという仕組みで自動インストールできるので、Javaさえあればすぐにビルドできる
- Gaiden Extensionという仕組みで、自由にシンタックスを拡張できる *1
Gaiden自体のホームページもGaidenで生成しています。 ちなみに、拙作のGroovyServのホームページも同じくGaiden製です。
Markdownの記述力って低いんでしょ?
確かにGFM(Github Flavored Markdown)でさえも相当シンプルなので、そこそこの分量のドキュメントを執筆するにはMarkdownの記述力だと不足ガチかもしれません。 その点、Asciidocはかなり機能がリッチなので、昨今、人気が高まってきている感じがあります。
しかし、個人的にはMarkdownのプレーンテキストフレンドリなシンプルさが好きなので、なんとかMarkdownで書きたいわけです。
そこで、Gaiden Filtersの出番です。
Gaiden Filters
簡単にいうと、簡単なGroovyコードを書くだけで、自由にシンタックスを増やしたり拡張したりし放題できる仕組みです。
以下の3つのタイミングで自由に介入して、自由にテキストが置換できます。
before
: Markdownソースのテキストafter
: Markdownソースから変換されたHTML断片のテキストafterTemplate
: テンプレートを使ってレンダリングされた最終的なHTMLのテキスト
サンプル: バージョンを設定ファイルに外だしして、ビルド時に置換する
config.groovy
に、以下のように記述するだけです。
before
に代入したクロージャの戻り値のテキストが次のフェーズ(この場合はMarkdowのレンダリング)に渡されます。
// in config.groovy ... version = "1.0.0" // Filters filters = { expandVersion { before = { text -> text.replaceAll(/(?m)<VERSION>/, version) } } }
あとは、Markdownで以下のようにVERSION
という文字を使ってドキュメントを書きます。
このドキュメントのバージョンはVERSIONです。
これでgaiden build
を実行すると、生成されたHTMLドキュメントでは
このドキュメントのバージョンは1.0.0です。
と、バージョン番号が展開されます。 とてもわかりやすいですね。
Gaiden Extensions
Gaiden Filtersが相当便利なので、ドキュメントプロジェクトごとに色々フィルタ実装を追加しまくっていると、汎用性の高いフィルタができたりして、他のドキュメントプロジェクトでも同じフィルタを利用したくなってきます。
config.groovy
のフィルタ実装をコピペしてもよいのですが、そこで一歩進んで、再利用可能なモジュールであるGaiden Extensions形式にしてみましょう。
と言っても大したものではなくて、config.groovy
と必要なリソースを特定のディレクトリに放り込んだだけの構造です。
先ほどのサンプルのように他のリソースが不要なら、次のようにとてもシンプルな構造になります。
extensions/ └── expandVersion └── config.groovy
// in extensions/expandVersion/config.groovy filters = { expandVersion { before = { text -> text.replaceAll(/(?m)<VERSION>/, version) } } }
先ほどのサンプルからだと、以下の3手順で移行できます。
extensions/expandVersion
ディレクトリを生成する。- 直下の
config.groovy
をextensions/expandVersion
配下にコピーする。 extensions/expandVersion/config.groovy
を編集して、必要なfilters
以外のソースをすべて削除する。
Gaidenはexntensions
ディレクトリ配下の各ディレクトリの中のconfig.groovy
も順番に評価してくれるので、先ほどと全く同じように動作します。
Gaiden ExntensionsでAdmonitionを実現してみる
さて、再利用性の高いオレオレシンタックスの作り方がわかったところで、Asciidocの素敵機能のひとつである Admonition (アドモニション)をGaiden Extensionsで実現してみましょう。
こういうヤツです。
Markdownの良いところはプレーンテキストとしてみてもそこそこ良い感じに読める、という点なので、そこは譲れません。 つまり、プレーンテキストでも良い感じに読めるような特殊なシンタックスを決めて、それをGaiden Filtersの仕組みでAdmonition表現に置換するようなGaiden Extensionsを作る必要があります。
ここでは、以下のようなシンタックスを導入してみます。
> **NOTE**: This is title! > > This is an admonition with title.
いかがでしょうか。 個人的にはそんなに醜くないし、普通のMarkdownとしてレンダリングされた結果としても割と良い感じなのではないかと思いますが、最終的には個人の主観にお任せします。
あとは、これをビルドすると上の画像のようなレンダリング結果が得られるように置換ロジックを書けばOKです。
で、できあがったGaiden Extensionsが、こちらのGaiden Extension: Admonitionになります。
filterの実装はこんな感じです。
filters = { admonition { before = { text -> def converter = { all, type, title, lines -> def header = title ? """<div class="admonition-caption">$title</div>""" : "" return """<div class="admonition admonition-${type.toLowerCase()}"> | <div class="admonition-icon"> | <i class="fa"></i> | </div> | <div class="admonition-content" markdown="1"> | $header | ${lines.replaceAll(/(?m)^\s*>\s*?/, '')} | </div> |</div>""".stripMargin() } text. replaceAll(/(?ms)^> \*\*(NOTE|TIP|WARNING|IMPORTANT)\*\*(?::(.*?))?$(.*?)(?:^$|> ----)/, converter). // block replaceAll(/(?ms)^\*\*(NOTE|TIP|WARNING|IMPORTANT)\*\*:()(.*?)$/, converter) // inline } } }
なお、CSSファイルもassetsとして追加してあります。
extensions/admonition ├── assets │ └── css │ └── admonition.css └── config.groovy
NOTE
だけではなく、
など複数種類に対応してたり、一行でシンプルに書いたり、タイトルをつけたり、などそこそこリッチな感じです。 詳しくはREADMEを読んでいただければ、使い方やサポートするシンタックスなどがわかるかと思います。
個人的には、これを大変便利に色々なドキュメントプロジェクトで使いまくってます。
おわりに
オレオレシンタックスを増やしたら、学習コストやメンテナンスコストが大変なのでは、という懸念もあるでしょうが、あーあー聞こえない聞こえない。 ではなく、まあ節度を持って活用すれば良いんじゃないでしょうか。
というわけで、巷では非常にレアなGaiden活用テクニックをお送りしました。
参考リンク
*1:なお、現在のバージョンではWindowsのGaidenラッパーによるインストール時にファイルパーミッション関連のエラーが発生してしまいますが、インストール自体は成功してるはずなのでエラーにめげずにもう一度Gaidenコマンドを実行すると動くんじゃないかと思います。たぶん。
JavaOne 2017 レポート 10/6 Day-6 帰国日&総括
さて、帰国日。 JavaOne 2017レポートも今回で完結です。
観光ウォーキング
今回の往復空路は羽田発着JAL便。 出発は16:05 SFO発なので、飛行機の時間まで結構時間があります。 ホテルのチェックアウトリミットは12:00ですが、ギリギリまで引きこもってるのも勿体無いですし、今回は全然観光してなかったので、チャイナタウン経由のフィッシャーマンズワーフ往復ウォーキングを強行してみました。
ユニオンスクエアの横、ケーブルカーの通る道路を北に向かいます。
チャイナタウン。時々道端にウ○コがあるので注意が必要。
途中にある公園にある綺麗な建物。
フィッシャーマンズワーフ到着。アシカや遊園地のあるPier 31から、
西の方に歩いて行って、
お昼はIN-N-OUTで。 激混みでしたが、なんとかゲット。チーズバーガー美味しいです。
IN-N-OUTの待ち時間でだいぶ時間を消費したので急いで戻ります。
なんか上の方を指さしてる家族連れがいたので、つられて見たら飛行機パラシュート部隊らしき何かがクルクルしてました。1
歩いた軌跡はこちら。
現地に溶け込むスキル高い方とのご挨拶
ホテルに戻ってスーツケースを受け取って空港へ向かおうとホテルを出たところで、通りの反対側で上下スウェット姿でタバコを吸っている現地の人に「ナカノサーーン」と声をかけられましたが、よくみたら寺田さんだったのでおつかれさまのハグをしてお別れしました。
ホテルを出たところで現地の人のように道端でタバコを吸うてらださんと偶然遭遇してさよならのご挨拶をした
— Yasuharu Nakano (@nobeans) 2017年10月6日
一発逆転のコイン消費行
アメリカのコインですが、種類も多いし、大きさと価値が比例してないし、数字が書いてないやつもあるし、書いてても小さくてみづらいしで、いつみても全く使える気がしません。 今回の滞在ではクレジットカードをメインに使いましたが、どうしても現金が必要な場面では紙幣を使っていたので、やはりそれなりに小銭ができてしまいます。
最終日の朝に少しは消費してみようと、スタバで朝食買うときにコインを出してみましたが、$8.50 (うろ覚え)に対して、紙幣で$8と5セントコインを出してみましたが($8.05)当然たりず2、店員のお姉さんに「この中から選んでくれ」とコインを一通り出してみたら、よりによって一枚だけ紛れ込んでいた1ドルコイン3をピックアップされてしまいました($9.05)。 お釣りは55セント。これがジャラジャラとコインで帰ってきます。 使うどころかむしろ増えました。なぜだ。
小銭を使おうとするけどまた失敗
— Yasuharu Nakano (@nobeans) 2017年10月6日
次のコイン消費チャンスは、クリッパー(SUICA的なやつ)への帰りのBART代チャージ。 しかし、BARTの券売機が史上稀に見るひどいUIなのと、後ろに並ぶ人たちのプレッシャに耐えかねて、適当に入れてチャージしたら、なんとお釣りで大量のコインがジャラジャラと出てきてしまいました。 実は焦って1枚多めに1ドル紙幣を入れてしまったのですが、チャージ指定した金額をさっ引いた額が全部小銭で帰ってくるというミラクル。ジャックポットかよ。 合計1ドル以上のクォータ(25セント)コイン+αがジャラジャラと釣り銭口に溢れ出して泣きそうです。 財布もパンパンです。
帰りのBART分の代金をクリッパーに入れようとして小銭が倍増してしまった
— Yasuharu Nakano (@nobeans) 2017年10月6日
小銭を使おうとしても使えないしむしろ増えるしでミラグロマンの気配を感じる
— Yasuharu Nakano (@nobeans) 2017年10月6日
もうダメかと諦めてましたが、飛行機のチェックインが早く終わり、ふと見ると保安ゲートの前にコーヒー屋さんがあります。
ここで可能な限りコインでコーヒを買えれば勝つる。 正直なところ店員さんにとっては迷惑な話ですが、レジも空いてたし、先に「全部コインで払ってもいいですか?」と聞いたら笑顔でOKしてくれたので大丈夫なはず。 結論としては、手持ちのコインをほぼ全部つかってコーヒー一杯の購入に成功しました。
保安ゲート前のコーヒーショップで全ての小銭をコーヒーに変換することに成功した
— Yasuharu Nakano (@nobeans) 2017年10月6日
小銭かき集めたら$2以上あったわ
— Yasuharu Nakano (@nobeans) 2017年10月6日
コーヒー美味しい (勝利の味がする)
— Yasuharu Nakano (@nobeans) 2017年10月6日
最後まで残ったdimeという謎コインは店員さんへの感謝を込めてレジのビンに入れて、晴れて全てのコインを消費しました! なお、あとで調べたらdime=10セントでした。何度調べても覚えられない。
なお、イマイチ使い道のわからないdimeはコップの中に入れてみた
— Yasuharu Nakano (@nobeans) 2017年10月6日
総括
さて、今回のJavaOne全体をざっくりまとめてみます。
技術
気になったキーワード
- Jigsaw
- Project Amber
- パターンマッチっぽいシンタックスとか、またベイパーウェア的な感じかと思いきや普通に18.3から一部入ってくるっぽいしヤバい
- Graal
- 日本語情報早よ
- TestContainers
- docker-compose使ってテスト環境作ることが多いですが、今の「先に手動で
docker-compose up
してからテスト」みたいなやり方を全部テスト側からコントロールできるっぽいので便利そう。
- docker-compose使ってテスト環境作ることが多いですが、今の「先に手動で
- Microservices/Container/Kubernetes
- とりあえずこの辺に関するセッション数はかなり多かったし人気だったし、やたらと単語が登場したので今ホットらしい(今頃かよ的なツッコミもあるとは思うけども)
Groovy/Grails
今年はGrailsのセッションはありませんでした。 というか、Webアプリケーションフレームワーク自体のセッションがほとんどないです。 見かけたのはVaadinぐらいかな? ふつーのWebアプリフレームワークについては、もう一通り落ち着いた感じがしますね。
Groovyの方は、タイトルに冠したセッションは3つで、そのうち2つ聞きましたが、セッション内容については前日までのレポートの通りです。
一方、Kotlinをタイトルに冠したセッション数は9件で、ALT Java言語系ではダントツだった気がします4。 セッション的には、Kotlin >>>> Scala >= Groovy 的なイメージ。 Android勢の基盤を確固たるものにしつつ、この勢いでどこまでいけるのか健闘を祈っております。
食
今回は大山さん・櫻庭さんとご一緒させていただくことが多くて、美味しい食事が楽しめました。 一人でレストランとかバーとかにいくのが難しいハート弱い系なので、大変助かりました。 あと、色々ごちそうさまでした。 なお、今回ビールについては、IPAを中心に攻めましたが、いずれもたいへん美味しかったです。
英語
6年ぶりのJavaOneは相変わらず楽しかったですが、自分の英語力のアレさ加減に打ちのめされて帰るという定番コースは今年も覆せませんでした。 以前よりも聞く方はだいぶマシになってきたなぁという実感はありますが5、ある一線を越えないと五十歩百歩感が否めないというか、「英語聞けますよ枠」に行くにはまだまだ努力が必要です。 しゃべる方はむしろ全然練習してないのでまあボロボロです。 頑張ろう。
その他
今回、JavaOneのレジストレーション後にもらえるオマケが、毎年恒例のリュック&Tシャツ、の2つだけでなんだか寂しい感じです。 JavaOneとして独立した会場&野外ラウンジがないとか、食事と一緒にドリンクがつかないとか、コーヒーとドリンクが午後1回の配給だとか、無限ビールが一晩だけとか、経費削減感がそこかしこに感じられて若干不安な気持ちが頭をもたげます。 ただ、ランチの味は以前の記憶よりもマシになってる感じがしました。 サンドイッチ系はパンがごつくてつらいこと以外は味は普通に楽しめた気がします6。 なんとなく。
さいごに
というわけで、総評として大変楽しいJavaOneでした。 また来年も行きたい!
JavaOne 2017 レポート 10/5 Day-5 千秋楽はMariottホテルで
いよいよ正真正銘JavaOne最終日です。
会場もMoscone WestからMariottホテルに場所を移して、なんとなくもう終わるんだよ感が漂ってきます。
今年は最終日のランチチケットがついてなかったので、参加者同士で「コスト削減でランチ配給もないのか!」などとぼやいていたら、単にチケットのモギリがなくなっただけでブツはきちんと配給されました。 なお、味はいつも通り。
Java Community Keynote
今年のテーマは「Community Keynote Reloaded」。 要するに「Matrix Reloaded」1 になぞらえて、各地のコミュニティの人たちで寸劇を披露しつつ普段の活動を紹介する、みたいな流れです。
なんだかんだで毎年来日されてる親日家のStephen Chin氏がディレクター的な役柄で、JOnsenのSebastian Daschner氏がNEO役になって話が進みます。
グリーンバックのクロマキー合成でバイクを乗り回してみたり、
日本オラクルの伊藤さんが日本古来より伝わるSpirits of Jigsawの教えを説いてみたり、
javajoのカラテマスターよこなさんがカラテキックを教えたり2、
マスターオブマスター(?)のskrbさんのマスター感が半端なかったり、
と、想像していたよりも楽しめました。よかったよかった。
A RESTful Java Framework for Asynchronous High-Speed Ingest
サーバ側の処理が結局DBへの更新系処理がボトルネックになってスケールしない問題を、NIOのSelector APIとステートマシンアルゴリズムを使って、非同期かつノンブロッキング処理として解決してみたよ、みたいなセッション。
Java 8: The Good, the Bad, and the Ugly
https://www.slideshare.net/BrianVermeer/java-8-the-good-the-bad-and-the-ugly-jbcnconf-2017
Java 8のラムダとかストリームとか良し悪し、ワークアラウンド的なノウハウなどを紹介するセッション。 資料もスタイリッシュっぽいし、話も軽快そうだし、割と実践的な内容だった気がします。
ただ、隣の人が「半ケツかよ!」というぐらいこっちのイスの座面を占有するわ、そこからさらに足を広げるわ、定期的に足の上下運動をするわで、セッション内容が全く頭にはいらず無念。
狭いし見えないし隣のオッサン足広げすぎ&接触型貧乏ゆすりするしで、全く内容が頭に入ってこない
— Yasuharu Nakano (@nobeans) 2017年10月5日
まあ、資料を読めばいいかと。
Vectors with Values on the JVM
Project Panama / Valhalla系の低レイヤのセッション。 へーとかふーんとか聞いてましたが、メモを取ったり説明するほど理解できてません。 とりあえず、リンクだけ貼ってお茶を濁します。
- JavaOneサンフランシスコ 2017 5日目 -- きしだのはてな
- Java VMの改善案が楽しそう -- きしだのはてな
- Project Panama: Interconnecting JVM and native code
- Vector API Developer Program for Java* Software
Changes to the JDK Release Model
物議を醸しているリリース/サポート話ですね。 きしださんをはじめ他の方がまとめてくださってるのでまとまった情報としてはそちらをご参照ください。
- Oracle Java SEサポート・ロードマップ
- 新しいリリースモデルはJavaを使う人 全員要注目だった
- [Java] Faster and Easier Use and Redistribution of Java SE
- Javaのリリースは6ヶ月ごととなる
あと、個人的にTwitterに流したツイートを載せておきます。
日本オラクルの人から、詳細は未定だけど「今までは、OpenJDK=ソースで、Oracleやディストリビュータでバイナリを提供してた」けど「今後は、今までOracleJDKを提供していたプラットフォームについてはOpenJDK自体からバイナリが提供される予定」という話を聞きました
— Yasuharu Nakano (@nobeans) 2017年10月10日
なので、有償LTS以外のバイナリは「OracleJDK」という名目で提供しない可能性もなくはない感じ
— Yasuharu Nakano (@nobeans) 2017年10月10日
単にビルド実施組織が変わるだけで提供はOracleサイトから今まで通りという話なのか、OpenJDKでビルド&提供するのか(Oracleは表に立たない)は、これから調整っぽいふいんき
— Yasuharu Nakano (@nobeans) 2017年10月10日
どちらにせよ、騒ぐとしたら「バイナリが手に入る入らない」ではなくて「LTS(有償OracleJDK)を使わない場合は半年以上経ったら独立のセキュリティアップデートは手に入らなくなって、色々てんこ盛りのメジャーバージョンにアップデートしないダメ」というのを呑めるかどうか、ですね
— Yasuharu Nakano (@nobeans) 2017年10月10日
あと、独立したディストリビュータが特定プラットフォーム向けに無償LTS的なJDKバイナリ提供をする余地もあるし
— Yasuharu Nakano (@nobeans) 2017年10月10日
OpenJDK/OracleJDKを含めて、メジャーどころのJDKバイナリ提供者がどういった提供サービスを打ち出してくるかはまだしばらく様子を見るしかないかなと
— Yasuharu Nakano (@nobeans) 2017年10月10日
もちろん、みんなだいすき「塩漬け」(=アップデートしない)という選択肢もあるわけです
— Yasuharu Nakano (@nobeans) 2017年10月10日
本日のディナー
最終日のディナーはもちろん、日本人参加者によるJavaOneの締めとして毎年恒例になっている、通称「蟹One」です。
日本的な蟹料理に慣れ親しんだ人間として、蟹への冒涜かと憤ってしまう勢いで油まみれにこってり炒められた蟹を、手を油だらけにしながら一人一杯いただきます。 手がありえないほど油だらけでベタベタになるのでビールはほぼ進まないけれども、これ以上ないぐらいビールのお供的な味である、というダブルバインドに苛まれながら、ひたすら蟹を貪ります。 油が冷えたら負けなので、ヤケドに留意しつつ熱々のうちにただひたすらに貪るのがポイントです。
これにて全日程終了です。
JavaOne 2017 レポート 10/4 Day-4 Moscone会場最終日
翌日の最終日(Day-5)はMariottホテルの会議室がセッション会場となるので、Moscone Westに通うのはこの日が最後です。 そろそろ終わりもみえてきて、並行して会場撤収なども始まるので、この辺りからだんだん寂しい雰囲気が漂い始めます。
Polyglot Adventures for the Modern Java Developers
モダンなJava開発プロジェクトを進めるために色々な言語を適材適所で使おう、という言語/ツールの紹介セッション。
- どの言語がベストというのはない。それぞれが特定の領域で強みを持っている、というだけ
- だから、適材適所で臆せずに混ぜ込んで使おう
- Setup-as-code
- シェルスクリプトよりも、Gradleタスク/Groovyが便利
- Build-as-code
- Mavenは良い。ただし、Gradleは100倍速い(?)
- Gradleはとても柔軟で、なんでもビルドできる
- 色々な言語を混ぜ込んだプロジェクトでもビルドが簡単
- Mavenは良い。ただし、Gradleは100倍速い(?)
- Main-as-code
- Frontend-as-code
- JavaScript一択
- TypeScript or (ECMAScript2015 + Babel)
- node + npm + webbpack
- JavaScript一択
- Test-as-code
- Pipeline-as-code
- Jenkins 2からJenkinsfileにGroovy DSLでかけるようになった便利になった
- Infrastructure-as-code
- Documentation-as-code
- Asciidoc + AsciidoctorJ + Gradle
- Architecture-as-code
- Presentation-as-code
- 「色々な言語やツールを使おうとすると学習コストがーという人がいるけど、実際やってみたら確かにそういう面もあるけど、トータルでハッピーでしたよ」
How Languages Influence Each Other: Reflections on 14 Years of Apache Groovy
我らがGroovyのProject Lead(Apache配下になってからは正確にはPMC Chair)であるGuillaume Laforge氏による、Groovyが誕生してから14年間における、他の言語との影響の相互作用について紹介するセッション。 なお、あくまでセッションメモなのでそれは事実と違う!などクレームはご遠慮ください。
- Groovy
- Groovyが他の言語から受けた影響
- Groovyから他の言語に与えた影響
- 言語同士はインスパイアしあう関係にある
- パーフェクトな言語はない
- でもみんな改善し続けてるよ
- Q&A
- Q: Groovyのswitchは、Java 7でやっと対応したString以外にもなんでもマッチングできて便利だけど、あれが各言語でのパターンマッチングに影響を与えたのかな?
- A: わかりません。ちなみに、Groovyでもここ10年くらいパターンマッチング実現しようと頑張ってるけど、全然完成してないです。
- Q: GroovyのJava 8シンタックスへの追随はいつになる?
- Q: Project Amberとかで、6ヶ月ごとに新しいシンタックス出てきたら追随大変じゃない?
- A: わかりません。まあ、新しいシンタックスへの対応はすぐには難しいかもだけど、動かすこと自体はできるんじゃないかと(よく聞き取れず)
- Q: データサイエンス分野ではPythonが大人気だけど、なんでGroovyはその分野で使われないの?
- A: (よく聞き取れず)
- Q: Jigsaw対応はどうなってるの?
- A: これはかなりの難題です。Jigsaw対応第一弾は2.6としてリリース予定ですが、一応動くけど警告が出る、という段階です。完全な対応にはGroovy自体のモジュール構成を破壊的に変更しないといけません。なので、メジャーアップデートとなる3.0での完全対応を目指すことになるでしょう。その辺も含めて今まさに検討&対応中です。
- Q: Groovyのswitchは、Java 7でやっと対応したString以外にもなんでもマッチングできて便利だけど、あれが各言語でのパターンマッチングに影響を与えたのかな?
Graal VM: High-Performance Polyglot Runtime
Graal(グラール)というHotspotの代替的な(?)実行環境の説明セッション。 JavaOneで初めてGraalという単語自体を認識した程度の情弱なのですが、なんだか一部の日本人参加者的に要注目らしいので、急遽聴講してみました。 そのうちJJUGとかで他の参加者の人から詳しい日本語情報が出てくるようなので正座してお待ちしております。
- Graal=Polyglotからinteroperableな実行環境
- Streamを使ったベンチマーク例
- mapを1つ使ったコード
- Hotspot: 40ns
- Graal: 11ns
- mapをさらに2つ追加すると
- Hotspot: 200ns
- Graal: 11ns (!!!!!)
- mapを1つ使ったコード
- npm, ruby, node, scalaとかもサポート
- ineroperableなので、JavaScriptからJavaやRなども呼べる
- Rを呼ぶ場合、初回は裏でRプロセスを起動するので遅いけど、2回目以降は速くなる
- JavaScriptの場合、Chromeの開発者ツールでDebugできる
- (仕組みよくわからず)
- Visulal VMが同梱されてる
- SubstrateVM
- すでにTwitterでは本番運用に投入してる
- Finagle/Thrift
Testing Containers with TestContainers: There and Back Again
Dockerなどを使ってインテグレーションテストをする場合に便利なTestContainersというライブラリを紹介するセッション。 興味のあるセッションが見つからず苦し紛れで選択してみました。 が、昼ごはん食べながら気を抜いて聞いてた&あまり興味持ってなかった&「テストとは〜」みたいな前置き話が長くて小難しく聞こえた、のでメモはあまり取ってません。
- development, production, integration-testで環境が違うの大変
- そこでDocker!
- でも、内部ポートが毎回違うとか大変なことがある(?)
- そこでTestContainers
- Spockサポートはこれから (?)
- (と思ったら誤解だったらしく、すでに普通にSpockで使えますよ、とTwitterで教えてもらいました)
TestContainers: Integration Testing Without the Hassle
https://www.slideshare.net/arhan/javaone-2017-testcontainers-integration-testing-without-the-hassle
なぜか2連続でTestContainersのセッションがあったのですが、ついうっかり聴講しました。 内容的には重複しているというか、むしろこっちの方がわかりやすくて、こっちだけでよかった感があります。 おかげでだいぶ理解できた気がします。
- ユニットテストだけではなく、インテグレーションテストも重要だよね
- (文脈的に、インテグレーションテスト=NWやノード構成を含めた環境上でのシステムテストを指しているっぽい雰囲気)
- でも、インテグレーションテストには問題もある
- 時間がかかる
- セットアップが大変
- インテグレーションテストに求められる6つのこと
- Reproducible environment
- Both for development and CI
- Isolated
- As real as possible
- Cross-platform
- Easy to set up, use & maintain
- そこで、docker&docker-compose!
- but
- サーバのポート番号がdocker-compose.ymlにハードコードされる
- テスト実行時に別途起動しないといけない
- but
- そこで、TestContainers!
- 挙動イメージ
- インストール済みのdocker環境を見つけて、
- docker-composeを使ってコンテナを起動して、
- テストを実行して、
- テスト終了時にコンテナも終了する
- ポート番号問題の解決
- コンテナの内部ポートをexposeするポート番号は空いているところを自動的に使ってくれる
Container#getMappedPort()
で実際にexposeされたポート番号が取れる
MockServerContainer
を使うと任意のサーバのモックを実装できる- Javaagentのバイトコード変換で色々できる
- JettyHandlerに介入して、独自ヘッダを入れるようにしたり
- Q&A
- Q: コンテナの起動コストは?
- A: どのイメージを使うかによります。
- Q: docker in dockerの環境で使える?
- A: yes. ドキュメントに書いてます。
- Q: コンテナの起動コストは?
Jump-start Your Microservices Development with Java EE
とりあえずJava EE系の何かを聞いてみようぐらいのモチベーションで入ってみました。 混んでいた&集中力が低下していたので、内容はあまり頭に入っていない&メモがありません。
どうやら、EclipseのMicroProfileに関する紹介セッションだった雰囲気。
Best Practices for Developing and Deploying Java Application with Docker
開発時や本番運用でDockerコンテナ上でJavaアプリケーションを実行する場合のベストプラクティスを紹介するセッション。 具体的なパラメータは参考になるところもありましたが、あまり目新しいものはなかったので、メモは省略。
Building and Testing Java 9 Applications with Gradle
- 資料: https://melix.github.io/javaone-2017-jigsaw/#/
- GitHub: https://github.com/melix/javaone-2017-jigsaw
Cedric氏による2つ目のGradleセッション。 Jigsaw対応のプロダクトをGradleでビルドする方法の説明です。
現状ではまだGradle側のJigsawサポートも限定的で、 相当なバッドノウハウを駆使しないとビルドができないようです。 正直、ややこしいわ&めんどくさいわで、相当ツラそうな感じです。 最初はメモを取ってましたが「色々大変そう」「実際に手を動かす時に資料を見ればいいか」という気持ちになり後半いい加減です。
- Jigsaw
- Reliable config --- "Good-bye classpath"
- Strong encupsulation --- "Good-bye com.sun"
- 移行時の注意
- 2つのモジュールが同じパッケージをexportできない
- 2つのモジュールが同じパッケージを内部パッケージとして持ってもいけない
- GradleのJigsaw対応状況
- Gradleを使ったプロダクトのJigsaw対応のサンプル
- 課題
- テストでのモジュールの依存関係が問題になる
- loadClassしたらモジュール内のprivateなクラスもロードできる?
- Gradleのapi/implementationコンフィギュレーションとJigsawのrequiresなどの依存性定義をうまく合わせる必要がある
- テストでのモジュールの依存関係が問題になる
- モジュールを今のGradleでビルドするにはトリッキーなバッドノウハウが必要
- テストはコンパイルでmainmジュールに結合(patch)するのが楽&早い
- テスト実行時に
ALL-MODULE-PATH
- (......色々面倒なことはわかった......)
- 課題
- 実験的にJigsawプラグインを作ってみた
- クラスパスを強引にモジュールパスとして扱う(?)
- Multi-release JAR
- Java 8/9のそれぞれで動くJARを生成するには、さらに色々仕込みが必要
- 1つのJARないに別のターゲットのクラスを共存できる(?)
- (......まだまだ色々地獄だなぁという印象.....)
- Java 8/9のそれぞれで動くJARを生成するには、さらに色々仕込みが必要
- Minimal Runtime Image
- jlinkを使って最小限の実行イメージを作る
本日のディナー
JavaOneチケットに含まれる今年のOracle主催パーティは、メジャーリーグのサンフランシスコ・ジャイアンツの本拠地であるAT&Tパークでの野外ライブでした。 以前はトレジャーアイランドでしたが、昨年度からAT&Tパークになったそうです。
普通に野球の試合があるとき用の売店で、無限ホットドッグ・ナチョス・ビールが振る舞われます。
おまけ
セッションの合間に会場をうろついてたDukeを発見して初のツーショット記念写真の撮影に成功しました(photo taken by skrbさん)。