play meetup-2-dev-best-practices

39
Play! framework を使用した 小規模プロジェクトにおける Best Practices () 鹿島和郎(かしまかずお)

Upload: k4200

Post on 14-Aug-2015

362 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Play meetup-2-dev-best-practices

Play! framework を使用した 小規模プロジェクトにおける

Best Practices ()!

鹿島和郎(かしまかずお)

Page 2: Play meetup-2-dev-best-practices

自己紹介• 鹿島和郎(かしまかずお)

• 家から出ないフリーのエンジニア。

• 同じく出不精のフリーエンジニア数人で 受託開発とかの仕事をしてます。

• リモート開発に最適化させた開発プロセスを作りたい と思って、いろいろやってます。

• GitHub: k4200, Twitter @k4200jp

Page 3: Play meetup-2-dev-best-practices

話す内容

• Play! framework + その他、で何か作ってます。

• その小規模開発プロジェクトでの Best Practices を公開します。

• 懇親会の時に、みなさんの事例も聞かせて下さい。

Page 4: Play meetup-2-dev-best-practices

こんなの作ってます

Page 5: Play meetup-2-dev-best-practices

こんなの作ってます

開発チーム向け内部文書検索エンジン

http://issf.hidebu.info/

Page 6: Play meetup-2-dev-best-practices

こんなの作ってます

自分達用に作り始めた。

結構便利になってきたのでひっそり一般公開(β版)。

http://issf.hidebu.info/

Page 7: Play meetup-2-dev-best-practices

こんなの作ってます

ひっそりすぎて殆ど誰も使ってくれません。

http://issf.hidebu.info/

Page 8: Play meetup-2-dev-best-practices

こんなの作ってます

興味のある方は声をかけてください。

m(_ _)m

http://issf.hidebu.info/

Page 9: Play meetup-2-dev-best-practices

こんなの作ってます

できること

http://issf.hidebu.info/

Page 10: Play meetup-2-dev-best-practices

こんなの作ってます

以下のものをまとめて検索できます。

• GitHub issues • GitHub wiki • Slack • Facebook groups • Gmail • 添付ファイル(pdf, docx, xlsx etc.) • その他、順次対応中です。

Page 11: Play meetup-2-dev-best-practices

こんなの作ってます

こんなことありませんか?

http://issf.hidebu.info/

Page 12: Play meetup-2-dev-best-practices

こんなの作ってます

あれー、この部分の仕様

前にどっかで教えてもらった

気がするなぁ。

http://issf.hidebu.info/

Page 13: Play meetup-2-dev-best-practices

こんなの作ってます

どのissueだっけなー

Slackだったかな

wikiだった気もするし・・・

http://issf.hidebu.info/

Page 14: Play meetup-2-dev-best-practices

こんなの作ってます

とか

http://issf.hidebu.info/

Page 15: Play meetup-2-dev-best-practices

こんなの作ってます

GitHub の wiki って

なんで検索できねーんだよ

http://issf.hidebu.info/

Page 16: Play meetup-2-dev-best-practices

こんなの作ってます

という悩みを解決します。

http://issf.hidebu.info/

Page 17: Play meetup-2-dev-best-practices

こんなの作ってます

デモ

http://issf.hidebu.info/

Page 18: Play meetup-2-dev-best-practices

小規模プロジェクトの開発環境

※全て個人的な意見です

Page 19: Play meetup-2-dev-best-practices

開発環境3つの環境

• ローカル開発 → Vagrant

• テスト → VM x 1 on Azure

• 本番 → VM x 3 on Azure

Page 20: Play meetup-2-dev-best-practices

開発環境ポイント

• Ansibleで一発で構築。

• Chef は小規模環境には向いていない気が。

• Puppet は使ったことない。

• Ansible Best Practices になるべく準拠。

• ディストリビューションは揃える。

Page 21: Play meetup-2-dev-best-practices

開発環境CI は CircleCI を使用

• Play (sbt) も当然使える。

• 主要なDBやキャッシュサーバーが最初から起動している。

• 小規模プロジェクトなら無料プランで十分。

Page 22: Play meetup-2-dev-best-practices

開発環境

Play! framework の話が出てこないんですけど・・・

Page 23: Play meetup-2-dev-best-practices

開発環境テクノロジースタック(DB周り)

• Play! framework 2.3

• Slick 2.1 (ScalikeJDBCじゃなくてすみません)

• Flyway SBT plugin

• PostgreSQL 9.3

Page 24: Play meetup-2-dev-best-practices

開発環境DB周りのポイント - テスト

• No inMemoryDatabase • あまりテストにならない。

• 違いを考慮したテストを書く必要があったり、 本末転倒。

• DBを使うテストは並列にしない。

• sbt でテストを動かす際の、3つのレベルの 並列性に注意。

Page 25: Play meetup-2-dev-best-practices

開発環境DB周りのポイント - マイグレーション

• Evolutions ではなく Flyway を使う。

• Flyway はシンプルにSQLで書けてよい。

• evolutions の嫌なところ。

• ファイル名が <数字>.sql

• よく inconsistent state になる。

Page 26: Play meetup-2-dev-best-practices

開発環境DB周りのポイント - マイグレーション

• Playアプリケーション起動時に勝手に起動する系は地雷。

• 設定でオフにしても、テスト時のFakeApplication で起動したりする。

• コマンドで手動実行、あるいはデプロイスクリプトに組み込む。

Page 27: Play meetup-2-dev-best-practices

開発環境DB周りのポイント - Flyway

• ファイル名は数字ではなくてタイムスタンプにする。

• 番号がかぶるのを避ける。

• 例:V201507051534__Create_foo.sql

• outOfOrder を有効にする。

Page 28: Play meetup-2-dev-best-practices

開発環境DB周りのポイント - Flyway

なぜ play-flyway ではなくてFlyway SBT plugin なのか?

• 後述のコード生成と相性が悪い。

• そもそも、起動するタイミングとかコントロールしたいし、プラグインを使う意味があまりない。

Page 29: Play meetup-2-dev-best-practices

開発環境

DB周りのポイント - boilerplate

• Slick の code generator が便利。

• DB構造を読み込んでScalaのソースを作成してくれる。

• sbtプラグインがあるらしい。

Page 30: Play meetup-2-dev-best-practices

開発環境

/** Entity class storing rows of table Conversation * @param id Database column id DBType(serial), AutoInc, PrimaryKey * @param dataSourceId Database column data_source_id DBType(int2) * @param lastUpdatedAt Database column last_updated_at DBType(timestamp) * @param status Database column status DBType(int2) */ case class ConversationRow(id: Int, dataSourceId: Short, lastUpdatedAt: DateTime, status: Short) /** GetResult implicit for fetching ConversationRow objects using plain SQL queries */ implicit def GetResultConversationRow(implicit e0: GR[Int], e1: GR[Short], e2: GR[DateTime]): GR[ConversationRow] = GR{ prs => import prs._ ConversationRow.tupled((<<[Int], <<[Short], <<[DateTime], <<[Short])) } /** Table description of table conversation. Objects of this class serve as prototypes for rows in queries. */ class Conversation(_tableTag: Tag) extends Table[ConversationRow](_tableTag, "conversation") { def * = (id, dataSourceId, lastUpdatedAt, status) <> (ConversationRow.tupled, ConversationRow.unapply) /** Maps whole row to an option. Useful for outer joins. */ def ? = (id.?, dataSourceId.?, lastUpdatedAt.?, status.?).shaped.<>({r=>import r._; _1.map(_=> ConversationRow.tupled((_1.get, _2.get, _3.get, _4.get)))}, (_:Any) => throw new Exception("Inserting into ? projection not supported.")) /** Database column id DBType(serial), AutoInc, PrimaryKey */ val id: Column[Int] = column[Int]("id", O.AutoInc, O.PrimaryKey) /** Database column data_source_id DBType(int2) */ val dataSourceId: Column[Short] = column[Short]("data_source_id") /** Database column last_updated_at DBType(timestamp) */ val lastUpdatedAt: Column[DateTime] = column[DateTime]("last_updated_at") /** Database column status DBType(int2) */ val status: Column[Short] = column[Short]("status") /** Index over (dataSourceId) (database name conversation_data_source_id_key) */ val index1 = index("conversation_data_source_id_key", dataSourceId) } /** Collection-like TableQuery object for table Conversation */ lazy val Conversation = new TableQuery(tag => new Conversation(tag))

1つのテーブルでこれくらい。

Page 31: Play meetup-2-dev-best-practices

使ってて便利なライブラリ

Page 32: Play meetup-2-dev-best-practices

便利なライブラリ

SecureSocial

OAuth を使っている各種SNS、webサービスへのログイン機能を簡単に作れる

Play用のライブラリ

Page 33: Play meetup-2-dev-best-practices

便利なライブラリ

SecureSocial

• 2月から更新されてない。

• 作者はやる気はあるらしい。

• Play 2.4対応とか。

Page 34: Play meetup-2-dev-best-practices

便利なライブラリSecureSocial

• その間、とりあえず fork したバージョンを使っている。

• Slack 対応などを独自で追加。

• 本家に PR は送っている。

• "tv.kazu" %% "securesocial" % "3.0.2"

Page 35: Play meetup-2-dev-best-practices

便利なライブラリscalacache

• 複数のバックエンドを透過的に扱える。

• memoize が簡単で便利。import scalacache._ import memoization._ !implicit val scalaCache = ScalaCache(new MyCache()) !def getUser(id: Int): User = memoize { // Do DB lookup here... User(id, s"user${id}") }

Page 36: Play meetup-2-dev-best-practices

便利なライブラリscalacache

• 質問とかにも、作者の Chris さん (日本語堪能)が親切に対応してくれる。

Page 37: Play meetup-2-dev-best-practices

その他にも 色々話したいのですが、

Page 38: Play meetup-2-dev-best-practices

続きは懇親会で。

Page 39: Play meetup-2-dev-best-practices

ありがとうございました。