play frameworkはscalaのweb frameworkとしてデファクトスタンダードの位置にあります。
しかし、かなり古参のフレームワークであることもあって今日scalaを書く上で良いとされているpracticeやマナーに反する点も多くあります。
この記事では私が個人的にbad partsだと思う点とその回避策を挙げます。
Play2のbad parts一覧
activator(旧play)コマンド
play frameworkのチュートリアルではactivatorコマンドのインストールを要求されます。
activatorコマンドはscalaを書く上で必要不可欠なビルドツールsbtのラッパーですが、追加されている機能は使われているのを聞いたことがないactivator uiとプロジェクトの新規作成テンプレートのみです。
play framework初心者でプロジェクトのテンプレートがほしい人がプロジェクトの新規作成をactivatorコマンドでやることは有益ですが、初心者(特にsbtコマンドにも不慣れな人)がactivatorを使い続けると何がactivatorの機能で何がsbtの機能なのかあやふやになりがちでよくありません。
対策: 直接sbtコマンドを叩きましょう
activatorコマンドが便利なのはほぼ新規作成時のみです。
またこちらを参考にすればactivatorコマンドを使用せずに1からplayプロジェクトを作成することもできます。
※2017/04 追記 activatorの開発が終了しました
開発元がやっとactivatorの失敗を認めたようで、2017/05/24を持ってactivatorプロジェクトは終了しました。
テンプレートなどを引き続き使いたい方はリンク先のガイドラインに従ってgiter8などから利用しましよう。
play-json
play framework付属のデフォルトのjsonライブラリですが、お世辞にも使いやすいとは言いがたいです。
一例
対策: 補完ライブラリを使用しつつ使い続ける or 代替ライブラリを使う
play-json-zipperなどの補完ライブラリを使えばある程度は不便さを緩和できます。
もしくは別のjsonライブラリを使う手もあります。個人的にはargonautがおすすめです。
ドキュメントが比較的少なく公式サイトのドキュメントもとっつきにくいですが、非常に筋のいいライブラリだと思います。
config(hcon)
このconfig関連のエラーは非常に発見が難しいです。
書式が間違っている、値が存在しない、そもそもファイルが存在しないなどの場合でも標準ではなんのエラーも吐きません。
そのためfalse positiveや原因不明の不具合の元になりやすく、信頼性が低いです。
対策: なし
play framework自体がhconに不可分に依存しているので避ける手段はありません。
play framework固有の設定以外でそれでもhconを使いたくない場合はtwitter社のutil-evalをおすすめします。hconのように曖昧な領域がなく非常に快適です。
specs2
play 2.2までは標準のテストスイートだったspecs2ですが、はっきり言ってまったくオススメできません。
2種類のテスト記述方式をサポートするため、より簡略化して記述するため、など複数の理由によりそのコードは非常にデバッグ・拡張しづらいものになっています。
開発サイクルは早いのですが、変更点の記述が甘くライブラリの更新によりnotesに書かれていない理由でコンパイルできなくなることもあります。
またテスト結果の出力も改行の位置にバグがあったりと、複雑すぎる機能をメンテナンスしきれていない印象を受けます。
(play frameworkの標準テストスイートから外れたのはその辺りの問題があったためと推測します)
解決策: scalaTestを使いましょう
play推奨test frameworkのもう一方であるscalaTestを使用しましょう。
specs2より構造がシンプルながら記述方法にも柔軟性があり、周りの複数のscalaプロジェクトではこちらを使用/specs2から移行することが多く評判も良いです。
プラグイン機構(play 2.4で廃止されました)
プラグインの仕組みが悪いのか、テスタビリティ低下の主要な原因の1つになっています。
テスト中でWithServer, WithApplicationを使っていると、プラグイン周りで問題が発生してテストが正常に実行できないことがあります。
解決策: できるならプラグインの使用を避ける
避けられるようであれば使わないようにしましょう。
2.4ではプラグインは廃止され、プラグインを改良したモジュールになったそうです。
なのでこちらを使う手もあります。
(ただ私はモジュールをそれほど使っていないので、問題がないかはわかりません)
ws(websocketライブラリ)
2.3未満ではwsはplay frameworkへ依存性べったりの機能でした。
2.4までにライブラリとしての切り出し・global stateへの依存性の切り離しなどで単体としてもかなり使いやすくはなりましたが、それでもまだ単体で快適に使えるライブラリとはいえません。
解決策: dispatchを使う
scala用http clientライブラリのデファクトスタンダードであるdispatchを使いましょう。
これなら単体でも非常に楽に使用することができ、ドキュメントも比較的豊富です。
2018/07/26追記
dispatchより使いやすいsoftwaremill/sttp: The Scala HTTP client you always wanted!が最近出ました。こちらが今はおすすめ。
外部DSLであるroutesファイル
scalaのroutesファイルは外部DSL(言語外DSL)であり、正規表現によるroutingなどかなり複雑なこともできます。
が、routesファイル内で改行ができない、引数の書式がscalaでもjavaでもなく混乱を引き起こしやすいなど欠点が多いです。
解決策: routesに複雑な設定を書かない
正規表現やOption、デフォルト値などの複雑な処理はroutesに書かないようにしましょう。
それらはコントローラでもできます。コントローラ内であればscalaコードで書けますし、frameworkへ過度に依存せずにすみます。
play独自のディレクトリ構造
sbtはmavenと同じディレクトリ構造を採用しています。
しかしplayはそれを独自に変更しており、sbt標準のそれとは違います。
解決策: 諦める or 2.4以降なら対策を入れる
build.sbtでplayframeworkが書き換えた設定を元に戻すこともできますが、
煩雑なので基本的にはplayの方式に慣れざるをえません。
・・・と思っていましたが、play2.4でsbt標準に戻す方法が提供されました。