2015/10/06
株式会社インタースペース
沖本 勇矢
 元々はSIerにてJava、C#を中心に開発
 Scala歴はまだ数カ月の駆け出し
 酒が大好き酒飲みエンジニア
沖本 勇矢(Yuya Okimoto)
 Playframeworkとは
 なぜPlayを選んだのか
 環境構築方法
 初歩的な使い方
 弊社導入事例
 バージョン2.4へアップデート
 まとめ
 ScalaとJava言語で書かれたオープンソースのWebア
プリケーションフレームワーク
 Ruby on Railsをご存じの方は、まさにそれと似た感
じのMVCデザインパターン
 Typesafe社がサポート(scala言語の開発を主導して
いる企業)
※参照 https://www.playframework.com/
 とにかく構築がかんたん(内蔵webサーバ、インメモリ
DB利用可)
 シンプルで軽量(リソース消費が最小限)
 scalaのwebフレームワークとしては一番メジャー
 弊社の現行システムで使用しているJava以外にも、
scalaという技術的資産を残したかった
 準備するもの
jdk8(事前にPATHは通しておく)
 Typesafe activatorのダウンロード
https://www.playframework.com/download
(任意のフォルダに解凍しておく)
 事前にダウンロードして解凍したフォルダから、
activator new <プロジェクト名> play-scala
C:¥Users¥public¥workspace>C:¥activator-1.3.5¥activator new sample-project play-scala
※Windowsの場合のパス表記ですが、コマンドはOSに差異はありません
 ステップ1で作成されたプロジェクトフォルダに移動し、
activator run
C:¥Users¥public¥workspace¥sample-project¥activator run
※Windowsの場合のパス表記ですが、コマンドはOSに差異はありません
 ブラウザでhttp://localhost:9000でアクセス出来
れば、環境構築完了です
※ただし初回は関連モジュールのDLで時間かかります
app → アプリケーションのソースコード(ここにすべてのソースコード配置)
└ controllers → アプリケーションのコントローラ
└ models → アプリケーションのビジネスロジック層
└ views → テンプレート
build.sbt → アプリケーションビルドスクリプト
conf → 設定ファイル
└ application.conf → メイン設定ファイル
└ routes → ルート定義
public → 公開アセット(静的なコンテンツはここに配置)
└ stylesheets → CSS ファイル
└ javascripts → JavaScript ファイル
└ images → 画像ファイル
project → sbt 設定ファイル
└ build.properties → sbt プロジェクトの基本ファイル
└ plugins.sbt → Play 自身の定義を含む sbt プラグイン
lib → 管理されないライブラリ依存性
logs → デフォルトのログ保存場所
└ application.log → デフォルトのログファイル
target → Play により生成されたファイル
test → 単体テストや機能テストのソースフォルダ
 controllerを作成
 ビジネスロジックを作成(model)
 テンプレートを作成(view)
 作成したcontrollerと、紐づけるURLを設定ファイル
(routes)に記述
今回はメッセージを表示するだけのごく簡単な一例
Playへのリクエストの玄関口
i18n対応の為、MessageApiをDIし、I18nSupportをmixin
※messagesを外部化しない場合は不要
package controllers
import play.api._
import play.api.mvc._
import play.api.i18n._
import javax.inject._
import models.SampleModel
class Application @Inject() (val messagesApi: MessagesApi)
extends Controller with I18nSupport {
def now = Action {
Ok(views.html.now(SampleModel.getDateTime))
}
}
ビジネスロジックを記述
ServiceやDAOを配置して処理を行う
ルール的に必ずしも分ける必要はないが、modelとして
切り離すのが一般的
package models
import org.joda.time.DateTime
object SampleModel {
def getDateTime(): DateTime = {
DateTime.now
}
}
プレゼンテーションレイヤー
暗黙パラメータとしてMessagesを受け取る
※Messagesを使用しない場合は不要
@import org.joda.time.DateTime
@(datetime: DateTime)(implicit messages: Messages)
<div>@Messages("message.now")</div>
<div>@datetime</div>
ルーティング処理の設定
この設定ファイルでURLとcontrollerを紐づけることで
リクエストの受け付けを行う
※リバースルーティングも可能
# Home page
GET / controllers.Application.now
# Map static resources from the /public folder to the /assets URL path
GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset)
 開発体制
人員:2名(内、協力会社1名)
期間:約5カ月
規模:10k弱(画面数で約30画面)
 開発内容
広告関連データをセグメント化して管理するに当たり、
マスタ登録、レポート表示といった機能を提供
※それほど大規模ではないアプリケーション(akka等
の並行処理は行っていない)
今回弊社としては初めてscalaとplayへの挑戦だった為、
いくつか問題点が浮かび上がる
 scala関数型プログラミングに難航
 Playの効果的な使い方がわからない(どういう構築&
開発方法がマッチベターなのか)
元々がJava使いだったので、どうしても関数型には
大きな戸惑いがあったが、その中で特に以下を
意識して実装した
 型を有効利用する
→Typeやclassなどで定義しておく(コンパイルエラーで拾える)
 副作用を避ける
→式を意識して、メソッドを実装するとreturnなども不要で簡潔に
 グッバイvar
→immutableな実装に努める為、極力val変数を使用
ある程度の使い方はわかるのだが、
どういう構築&開発方法がマッチベターなのか?
 とにかく公式ドキュメントを読み込む
→まずは基本はドキュメントが推奨している手法をベー
スにする
 勉強会やセミナーに参加
→他社事例を参考にし、別のアプローチがないか検討
今回弊社では、外部の経験豊富なエンジニアに
参画して頂き、先ほどからお話した問題も含め、
技術支援を頂きながら、すべての課題を解決し、
無事に開発&構築を行うこともできた
→独学でやることも大事だが、やはり有識者は必要
特にライブラリ周りなどの助言は非常に助かった
 構築が簡単で、モジュールのデプロイも楽
 シンプルを謳っているだけあって、動作的には軽さを
感じた
 ただしその一方でコンパイルの時間は少し長く感じた
 またはIDEにEclipseを使用していたが、プラグインが
事前コンパイルエラーを正しく検知しないなど、ちょっ
と使いづらさはあった(IntelliJも試したい所)
 scalikejdbc(データベースアクセス)
 play-flyway(データベースマイグレーション)
 play2-auth(認証ライブラリ)
 scalatest(テスト支援ツール)
 scoverage(カバレッジ取得ツール)
 scalaliform(ソースコードフォーマッタ)
 当初は2.3.7で構築
 今セミナーで何かしらの情報共有が出来るようにと、
早めにバージョンアップ作業をしてみた
 しかし、いきなりコンパイルエラーが500件以上出る
など、少し難航・・・
 対応した内容を簡単にご紹介します
 build.sbtの変更
 あとはひたすら置換
routesGenerator := InjectedRoutesGenerator
object Login extends Controller {
↓
class Login extends Controller {
 Messagesのインタフェースが変更になり、コンパイル
エラーの原因はこれが9割だった
 こちらはMessageApiのDIと、I18nSupportをmixin
し、テンプレートの引数をLangからMessagesに変更
import play.api.i18n._
import javax.inject._
class Login @Inject() (val messagesApi: MessagesApi)
extends Controller with I18nSupport {
 2.4から非推奨になったGlobalSettingsで使用して
いたCSRFFilterを、 HttpFiltersに移行
package global
import play.api.http.HttpFilters
import play.filters.csrf.CSRFFilter
import javax.inject.Inject
class Filters @Inject() (csrfFilter: CSRFFilter) extends HttpFilters {
def filters = Seq(csrfFilter)
}
play.http.filters = "global.Filters"
 application.confには以下を追記
 plugInが非推奨になり、使用していた外部ライブラリ
のmodule化に伴い、application.conf変更
 2.4対応のために更新しているライブラリも多い為、使
用しているライブラリは漏れなくチェック
play.modules.enabled += "scalikejdbc.PlayModule"
play.modules.disabled += "play.api.db.DBModule"
 logger.xml→ logback.xmlの置き換え
 application.confの設定値名変更(play.crypto.secret、
play.i18n.langsなど)
 controllers.Assets.at→controllers.Assets.versione
d
 play.PlayImport.PlayKeys.routesImport→
play.sbt.routes.RoutesKeys.routesImport
弊社システムで行った変更以外にも、数多くの
変更点があります。詳しくはマイグレーションガイドを
参照してください
 とにかく、まずはマイグレーションガイドを穴があくまで
読みましょう
 それでもわからないor私のように英語の読解が不得
意の方は、playのソースを見ましょう
※経験上、その方が解決が早い場合もありました
GithubのURL
https://github.com/playframework/playframework
 Play構築かんたん、シンプルで使いやすい
 知識ゼロベースで作る場合、ごくごくシンプルなシステ
ムなら問題ないが、凝ったことをする際は、無理せず
有識者に知見を求めましょう(gitter等のコミュニティも
あります)
 これから導入する方でplay2.4を使う場合、ネットの
情報が古い場合があるので、必ずバージョンを確認
株式会社インタースペース 沖本様 登壇資料

株式会社インタースペース 沖本様 登壇資料