Android らしい Java - Part.1
仕事で Android アプリのコードを触り始めはや数ヶ月。少しは理解が進んだ。
今の仕事のコードは、残念ながらそれほど素晴らしくない。その昔 Android Java にまだ慣れていなかった人々が書いたであろう古いコードが目につく。そして古いコードの昔ながらな残念さは、従来の Java とは違う Android Java の「らしさ」を描き出す。そんな話を数回にわけて書いてみたい。
第一回は非同期性のはなし。
Android のアプリはメインスレッドをブロックしてはいけない。だから色々と非同期に書く。ところが従来の Java は非同期がさほど得意でない。多くの API がブロックする。
ブロックする処理は別のスレッドに追い出せばいい。ただし結果はイベントループを通じてメインスレッドに戻さないといけない。これを綺麗に書くイディオムが、Android では最近まで確立されていなかった(AsyncTask は綺麗でない)。成熟した JavaScript の非同期プログラミングと見比べてがっかりする。
JavaScript の非同期イディオムは関数が一級市民である利点を生かしている。従来の Java はそこも弱かった。今やコモディティ化した関数的イディオムの不在と復権も、従来の Java が浮き彫りにする Android らしさだ。でもその話はまた今度。
さて、非同期性をモデル化する方法は大きく分けて二つある。要求への応答を待つ「リクエスト/レスポンス」スタイルと、一方的に物事が伝えられる「イベント/ストリーム通知」。この違いはコードの上で明らかにしてほしい。RxJava も最近の版で Single という Promise 的、つまりリクエスト/レスポンス志向のクラスを追加し、この区分を強調した。
非同期性への意識が弱いとこの区別…以前に非同期に何かしているという自覚が曖昧で、「協調しているオブジェクトのメソッドがそのうち呼ばれるかも」みたいなぼんやりした抽象が持ち込まれる。
これは JavaScript にちょっと前まであったコールバック地獄に似ているけれど、呼ばれる先が関数でなくオブジェクトのメソッドなぶん性質が悪い。関数的イディオム不在の辛さがある。
従来の Java も悪いところばかりではない。非同期の世界で Java らしさが生きる場面もある。たとえばスレッド。Java の Concurrency API はそれなりによく出来ている。CPU のクロックが遅くコア数ばかり増える昨今、スレッドが使いやすいのはいい。ただメインスレッドやイベントループの概念がないのはいまいち。
非同期イディオムは RxJava や周辺のモダンな子たちを使えばだいたい片付く。古いコードは、モダンなライブラリが解決した問題をリアルに伝える。それが辛くも面白い。