ikeike443のブログ

ソフトウェアビジネスに関心がある系のブログ

Play! on Heroku 翻訳

HerokuがJavaのみならず、Playframeworkをネイティブにサポートすると発表しました
以下はその翻訳です。一部意訳したりしてます。翻訳の間違いなど、是非ご指摘ください! Play!いいよね!


Play! on Heroku
by Jesper - 8 hrs ago


JavaRubyの両方を経験しているWeb開発者はしばしば疑問に思うことがある。なぜJavaのWeb開発はこんなにややこしいんだ? Ruby, 特にRailsで開発するとこんなにシンプルなのに。
この疑問に答える方法はたくさんある。しかし重要なのは、Java言語そのものに問題があるわけではないということだ。Play! Frameworkの中の人たちが、RubyにおけるRailsのように、エレガントで生産的なWebフレームワークを作り、そのことを証明してみせた。


ここに、Play! on Herokuのパブリックベータをアナウンスできることを大変嬉しく思う。


Play! on Heroku クイックスタート


Play!のver.1.2.3以降をダウンロードし、Play!アプリケーションを新規作成してみよう:

$ play new helloworld
~        _            _ 
~  _ __ | | __ _ _  _| |
~ | '_ \| |/ _' | || |_|
~ |  __/|_|\____|\__ (_)
~ |_|            |__/   
~
~ play! 1.2.3, http://www.playframework.org
~
~ The new application will be created in /Users/jjoergensen/dev/tmp/helloworld
~ What is the application name? [helloworld] 
~
~ OK, the application is created.
~ Start it with : play run helloworld
~ Have fun!
~
$ cd helloworld

次にProcfileを作成する:

web: play run --http.port=$PORT $PLAY_OPTS 

Gitにコミットし、Cedarにアプリを作成し、デプロイする:

$ git init
$ git add .
$ git commit -m init

$ heroku create --stack cedar

$ git push heroku master
Counting objects: 30, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (22/22), done.
Writing objects: 100% (30/30), 35.95 KiB, done.
Total 30 (delta 1), reused 0 (delta 0)

-----> Heroku receiving push
-----> play app detected
-----> Installing Play!..... done
-----> Building Play! application...
       ~        _            _ 
       ~  _ __ | | __ _ _  _| |
       ~ | '_ \| |/ _' | || |_|
       ~ |  __/|_|\____|\__ (_)
       ~ |_|            |__/   
       ~
       ~ play! 1.2.3, http://www.playframework.org
       ~
       1.2.3
       Play! application root found at ./
       Resolving dependencies: .play/play dependencies ./ --forceCopy --sync --silent -Duser.home=/tmp/build_2rgcv7zjrtyul 2>&1
       ~ Resolving dependencies using /tmp/build_2rgcv7zjrtyul/conf/dependencies.yml,
       ~
       ~
       ~ No dependencies to install
       ~
       ~ Done!
       ~
       Precompiling: .play/play precompile ./ --silent 2>&1
       Listening for transport dt_socket at address: 8000
       16:14:33,716 INFO  ~ Starting /tmp/build_2rgcv7zjrtyul
       16:14:34,372 INFO  ~ Precompiling ...
       16:14:37,656 INFO  ~ Done.

-----> Discovering process types
       Procfile declares types -> web
-----> Compiled slug size is 26.2MB
-----> Launching... done, v5
       http://blazing-water-545.herokuapp.com deployed to Heroku

デプロイできたら、URLにアクセスして、Herokuの上でPlay!が動いていることを確認しよう。


ラジカルなアプローチ


JavaでWebアプリが書かれれば書かれるほど、Web開発を簡単にしようと試みるフレームワークが増殖していく。しかしこの問題にクリーンルームアプローチで取り組もうとするフレームワークは存在しなかった。皆、サーブレットコンテナやJSPとの互換性を保たないといけないと思い込み、スタンダードなJavaのWebアプリ構成に準拠しようとし、Javaオブジェクト指向の原則に適合させようとしてきた。時にはそれが無理なことだと分かっていても。


Play!はフレッシュな状態から書かれた最初のJava Webフレームワークだ。Railsから多くのアイディアを拝借し、built-for-deploymentなフレームワークとして作られている。Play!アプリケーションはパッケージにしたり、配布したり、といったことは意図されていない。そのままデプロイ出来るように作られている。これはJavaのネストしたパッケージ構造や、XMLによる制御を捨てることが出来、WARファイルのことを忘れることができ、代わりに分かりやすく、生産的なプロジェクト構造を保つことが出来る。


例えば、helloworldアプリは一個のJavaクラスからなるコントローラによって作ることが出来る:

package controllers;

import play.*;
import play.mvc.*;

import java.util.*;

import models.*;

public class Application extends Controller {

    public static void index() {
        render();
    }

}


このクラスはindex()というメソッドによってHTTPのエントリポイントを定義している。このメソッドはindex.htmlというテンプレートファイルに対して、render()というメソッドでレンダリングを行っている。


定型的なクラスもなければ、XMLの設定ファイルも必要ない。Play!は規約をフレッシュなアプローチで提供している。そして意味の有るところではStaticコードを使う。例えば、コントローラのエントリポイントはステートレスであり、オブジェクト指向であるよりもHTTP指向であるべきなので、Staticメソッドとして実装されているのだ(上記index()メソッド)。


他にも、開発者にとって嬉しい機能が付いている。例えば開発時の自動コンパイルだ。君も、他のJavaのWebフレームワークに比べて、Play!のドラマチックとでも言うべき生産性の高さを目のあたりにすることになる。

コンテナレス


Jettyと言えばコンテナレス開発の筆頭だった。ただ、十年以上もの間、たった一人でその場に立ち続けていた感じだ。
その使い勝手はちょっと悪いことがあった。なぜなら、コンテナレス開発をしていることを意識しないといけないからだ。Play!はコンテナレス開発およびデプロイのやり方をシンプルかつエレガントに提示してみせた。プロダクションで使うには、プロジェクトを丸ごとアップロードして、play run --%prod を実行するだけだ。


Herokuはまさにこのやり方にあうようにデザインされていた。Play!アプリは自然なホームをHerokuの上に見出したことになる。Herokuの上で開発するには、ローカルでplay runしてテストまたはforman startすればいい。デプロイの準備が出来たら、プロジェクト全体をそのまままるごとgit push heroku masterするだけだ。するとHerokuはそれをプロダクションモードでplay runする。このデプロイ方法はシンプルで、開発とプロダクションの差異も理解しやすいものだ。実際、ローカルで実行したのと全く同じ方法でHerokuの上でも実行される。環境の違いによる問題は発生しない。


簡単なだけじゃない


ここまで読んで、Play!は使いやすさによるコストパフォーマンスとロバストネスに過度にフォーカスしたものなんだと結論づけたくなる人もいるだろう。結局、他のフレームワークで構築されたアプリや、高度に最適化されたライブラリを置き換える理由になるの? と。


Play!について調べると、スクラッチから作るやり方が最もパフォーマンスがいいことに気づくだろう。Play!はリクエストの非同期処理のサポートについて、一から考えてデザインされている。この技術はNode.jsやPythonのTwisted、RubyのEventMachineなどで広く採用された技術だ。


Play!はNettyを使っている。NettyはJBossチームによって開発されたノンブロッキングI/Oライブラリだ。Play!はノンブロッキングI/Oと継続プログラミングモデルを統合し、リクエストの非同期処理を実現している。

例えば、PDFのレンダリングはリクエストをサスペンドしておいて、バックグラウンドで行われる。こんなふうにシンプルに:

public static void generatePDF(Long reportId) {
    Promise<InputStream> pdf = new ReportAsPDFJob(report).now();
    InputStream pdfStream = await(pdf);
    renderBinary(pdfStream);
}

Play!はJavaのWebフレームワークにはつきもののステートフルなセッションも捨て去った。シェアナッシングモデルを取り入れることで、Play!は、ノードを追加するだけでアプリケーションを水平にスケールアウトさせることに成功した。


さらに詳しく


ここまで読んできて、Play!はただ生産的なだけではなく、楽しいものだってことが分かったと思う。すぐにアプリ作りを始めよう!

Special Thanks


ZenexityのPlay! Frameworkチームに感謝したい。特にGuillaume Bortには大変お世話になった。またErwan Loisantにはいくつかの機能要望を受け入れてもらい、Herokuに統合してもらった。

*1:[http://playdocja.appspot.com/documentation/1.2.3/5things:title=ここ]に日本語訳があります。