Playframework 2.0 Javaのこと

こんにちは。小西です。
今回Play1とPlay2の比較記事を書くにあたり、Play2をJavaで使用するという選択肢はアリなのか?という点についても調べてみました。
なにしろJavaの方がScalaよりも圧倒的に技術者の数が多いので、Play2がScalaだけでなくJavaからも(まともに)使用できるならばそれはとても価値のあることだと思うからです。

で、とりあえずExcel2CanvasのサイトをJavaに移植してみたのですが。。。。

う~ん、ないですね。これは。。。

Play2をJavaで使おうなどとは未来永劫考えない方が良いでしょう。(--

一応できるはできるんですが、Scalaをまったく知らないJava技術者がこれを使うのは正直かなり苦しいと思います。
そして当たり前ですが、Scalaを知っているなら絶対にScalaを使った方が素直にコードを書けるわけです。

以下、ScalaコードをJavaに移植してみて感じたことをいくつかのポイントに分けて書いてみます。

1、Play2のベースコードはScala
Play2自体のコードにはJavaで書かれたコードとScalaで書かれたコードの両方が含まれています。
パッケージで言うと

・play.api.xxxがScalaコード
・play.xxx(「api」パッケージ以外)がJavaコード

となっており、自前のコントローラを書く際にもそれぞれのクラスをimportして使用することになります。

Java、Scalaのどちらを使う場合でもコントローラは「Controller」クラスを継承したクラスであり、コード中では「Request」とか「Response」などのオブジェクトを扱いますが、それらはパッケージも書かれた言語さえも異なる全く別のクラスです。

そして、Play2のベースとなるコードはおそらく全てScalaで書かれておりJavaAPIでは内部的にScalaAPIをコールしたり、それが不可能な場合は新たに書き直されたりしています。

Play2のドキュメントには「JavaをベースとしながらScalaのパワーを解放するのは難しい」というようなことが書かれていますが、「ScalaをベースにJavaでも使用できるライブラリを作成する」ということはもっと難しいだろうと感じましたね。。

ソースを見ていたのは1日2日ですが、それでもそこかしこにいびつさを感じます。(主たる原因はやはりJavaにはない関数リテラルがScalaでは多用されるためかと思います。)

2、テンプレートはどちらもScala
Scalaを使用する場合でもJavaを使用する場合でもテンプレートの仕様は共通でどちらもScalaになります。(厳密に言えばScalaベースの独自仕様で、テンプレート内でScalaコードを自由に記述することができます)

実際、今回ScalaコードをJavaに移植してみたわけですが、テンプレートのコードは1行たりとも修正していません。

Scalaベースといっても単純に文字列内に埋め込まれたパラメータを置き換えたいだけのようなケースではScalaの知識は特に必要なく、 ここまでならJavaから使う分にも特に問題はないんですが、Listなどのコレクションを使用してテンプレート内で繰り返し処理を行いたいような場合はちょっと困ったことになります。

そう。ベースがScalaなのでコレクションもScalaのコレクションにしないとJavaのままでは使いにくいのです。
もちろんテンプレートの内側でも外側でもScalaのJavaConversionsを使用して変換することはできるんですが、かなり「なんだかな。。。」という気分になります。(--

また、細かいところですがScalaではデフォルト引数とパラメータの名前渡しが使えるのでテンプレートのパラメータで下記のようにデフォルト値を宣言しておけば選択的にパラメータを渡せますがJavaから使う場合は全てのパラメータを明示的に指定する必要があります。

@(name: String, data: String, download: Boolean = false, version: String = "", 
strs: Seq[String] = Nil, pictures: Seq[(String, String)] = Nil)

3、バグ多し
これは1とも関係することですが、ScalaのコードとJavaのコードは別に書かれているので、Scala側に問題がなくてもJava側でバグが混入する可能性はあります。というより、現状ではかなり多そうな印象です。

わずか1日の移植作業で遭遇しただけでも、

・WS(HttpClientラッパー)のレスポンスからバイナリデータを取得する方法がない  
  (Scala版のWSにあるメソッドがJava版にない)
・日本語を使っているわけでもないのに何故かエラーメッセージがもれなく文字化け
・割と頻繁にエラーメッセージに表示される行番号が正しくない。

などがあります。
さらっと書いてますがわりと致命的です。(--

Scalaでコードを書いている時にはそれほど困った記憶がないので、これらはおそらくJavaだけにある問題です。
開発者の力のかけ方の差を感じます。

本筋とは関係ありませんがPlay2のWSではPlay1の時にあった同期APIがなくなり非同期APIのみになっています。
今回バグ回避のためにWSがラップしているningのHttpClientを直接使用しましたが、同期処理の場合は多分そうした方が素直に作れます。

4、Scalaはやっぱり便利
今回ScalaのコードをJavaに書き換えるにあたって面倒を感じたのは以下の点です。

・Tupleが使えないのが少し。。。
・List処理を全部forに修正するのがかなり。。。
・XMLリテラルでやってたことをStringベースにするのはとても。。。

これらは色々なところでScalaの利点として語られているので、ここでは多くを述べませんが一度Scalaに慣れてしまった技術者がJavaをおっくうに感じる気持ちはとてもよくわかります。

以上が、Play2のScalaコードをJavaに移植して感じたことです。
こうして改めて書いてみるとPlay2はまだまだこなれていない印象を強くします。

バグは直せば良いだけですけど、1や2は根源的な問題なのでそう簡単には解決しないでしょう。
また、現在Play2を開発している人たちの意識もそこには向いていないと思います。
個人的にはもうJavaのサポートは止めちゃっても良いぐらいだと思いますがこれからどうなっていくでしょうね。

いずれにせよPlay2を使うのであればがんばってScalaを覚えましょう!(^^)/

コメント(0)