SlideShare une entreprise Scribd logo
1  sur  65
Télécharger pour lire hors ligne
Skinny Framework
で始める Scala
瀬良 和弘
@seratch(_ja)
エムスリー株式会社
ソフトウェアエンジニア
日本 Skinny Framework ユーザ会
JJUG CCC 2014 Spring
2014/05/18
私について
・本業は主に Web アプリ、バックエンド API 開発、社
内ツール諸々の運用整備の整備などに従事
・Scala は 2009 年に始めて触った(だけ)
・2011 年の正月休みから少しずつ使い始めた
・2011 - 2012 年、Akasaka.scala という勉強会
を隔週で主催していた(現在は休止中)
・社内外の Scala プロジェクトでメイン開発者として開
発している OSS を利用いただくようになってきた
(ScalikeJDBC、Skinny Framework)
今日は、JJUG の皆さんに
Scala を宣伝するために来ました。
Java から Scala へ!!(真顔)
!
Skinny Framework は
Java な現場、SI 業界の案件でも
十分使えるはずと思っています。
!
!
今日は私の話を聴いて
実際に使えそうか見極めてください。
!
!
- Scala について -
Scala のおさらい
・2003 年に生まれた比較的新しい言語
・オブジェクト指向と関数型プログラミングの融合
・スイス連邦工科大学教授 Martin Odersky
・2011 年に出資を受けて Typesafe 社を立ち上げ
・Typesafe 社は Scala の開発だけでなく sbt、
Akka、Play2、Slick、Spray 等のツール・ライブラ
リのメンテナンス・商用サポートも提供
・Rod Johnson 氏が Typesafe 社に参加し話題に
JJUG 的? Scala のメリット
・オブジェクト指向 + 関数型プログラミング
・静的型付け、型推論により記述の簡潔さを両立
・デフォルトが immutable な API
・並行処理、非同期プログラミングとの親和性
・JVM レベルの処理性能が期待できる
・Java で書かれた枯れた実装も流用できる
・大規模なプロダクション利用実績が多い
・GitHub 時代の言語、活気のあるコミュニティ
JJUG 的? Scala のデメリット
・Java と比べてコンパイル時間が長い
・言語のバイナリ互換性などに対応する運用コスト
・Java エンジニアにとって意外にジャンプが大きい
・表現力の裏返しで OOP と関数型プログラミングが混在
するなどスタイルが統一されない懸念がある
・Java と比べて、標準規格よりも動く OSS 実装がリー
ドする世界なので、あまり受け身なスタンスだと難しい
・既に Scala を使いこなしているエンジニアの母数はま
だまだ少なく、人材採用面での不安がある
Scala の互換性の件
・最新バージョンは 2.11.0
・2.10.0 ∼ 2.10.4 はバイナリ互換あり
・2.10.4 と 2.11.0 はバイナリ互換なし
・2.9 までは 2.9.x ごとに互換性がなかった(!)
・2.9(と 2.10 の一部)は Java8 で動作しない
・Maven でいう artifactId にバイナリバージョンが
suffix としてつく(例:scalikejdbc_2.11)
・メンテされなくなったライブラリは新しいバイナリバー
ジョンでビルドされなくなるので選定に注意が必要
- フレームワークの現状 -
Web フレームワーク事情
・長らく Lift ほぼ一択の時代(事例:4sq)
・2012 年春 Play Framework 2.0 が登場
・約 2 年経ち、現在は圧倒的に Play2 の人気が高い
・より軽量なフレームワークはいくつか現実的な選択肢が
ある(Scalatra、Unfiltered、Spray など)
・Play2、Spray は現在 Typesafe 社のプロダクト
!
・2014 年春 Skinny Framework 1.0
DB ライブラリ事情
・あくまで目安として GitHub スター数で比較
・Slick (879)、Squeryl (358)、ScalikeJDBC
(254) がベスト 3、Slick は旧 ScalaQuery
・他には scala-activerecord (164)、Activate
(155)、SORM (124) など
!
・ScalikeJDBC は機能不足によって実務上困ることは
ないが ORM よりもコード量は多くなりがち
・そこを埋めるのが Skinny ORM
テンプレートエンジン事情
・Scalate は長年メンテされており、SSP、Scaml、
Jade、Mustache と複数の文法が使える
・Play2 の Scala Template が最近独立(Twirl)
・Lift はタグを埋める独自のやり方
・Circumflex という Web フレームワークは
FreeMarker の Scala 対応を実装(Skinny はこれ
を fork して Scala 2.10 に対応させた)
!
・Skinny では Scalate を採用(理由は後ほど)
- Skinny とは -
Skinny?
・響きもいいし、自然とこの名前を選びました、
一応 3 つの理由があります
!
・Application should be skinny
・Framework should be skinny
・ 好きに (su-ki-ni)
Skinny Framework
・2014/03/28 に 1.0.0 リリース(現在 1.0.14)
・Scala on Rails がキャッチコピー
・機能豊富なフルスタック Web フレームワーク
・MVC、ORM、DB マイグレーション、メール送信
・scaffold などの自動生成機能
・Play2 と違い Servlet コンテナで動作
・Java 1.6 以上、Servlet 3.0 以上
・war、Jetty 埋め込み jar ファイル生成
フルスタック?
・フルスタック Web フレームワークはもはや死語?
・定型な機能を提供するフレームワークが珍しくなくなり、
あえてアピールポイントとすることが少なくなった
・ライブラリを組み合わせること前提の開発は柔軟だが、
依存先が増えるリスク、組み合わせの検証コストがある
・チーム開発の場合、ある程度やり方が決められている方
がありがたい場合も多い(もちろんチーム次第)
・よくある要件の実現に必要な時間は極力減らし、差別化
できる要件の開発にこそ時間を使いたい
Scala on Rails?
・それって Play2 のことではないの?(否)
・Play2 本体は HTTP 周り以外の機能をあまり持って
いない、今後も周辺を拡充するようには見えない
・Rails、Play1 のように HTML を返す Web アプリ
開発の利便性に最適化しているわけではない
・Play2 は Rails 風味な記述で NIO ベースのサーバア
プリを開発するためのフレームワーク
・JSON API サーバ、Akka の特長を活かしたアプリ
ケーションなどに適している
Skinny の構成
・極力自作を避け、実績があり、かつ Skinny の思想に
合うライブラリを土台とし、その上に作り込んでいる
・ルーティング、Servlet ラッパーのために Scalatra
・デフォルトテンプレートエンジンとして Scalate
・ORM の土台として ScalikeJDBC
・DB マイグレーションは Flyway
・JSON の処理に json4s
・入力バリデーション、メール送信はオリジナル
・後ほど、個別の機能を順次紹介します
- Skinny をはじめよう -
起動まで(1)
・必要なのは JDK(1.6 以上)のみ
・skinny-framework.org にある以下のダウンロー
ドボタンから約 80MB の zip ファイルをダウンロードし
てください
!
!
!
!
!
起動まで(2)
・zip ファイルを解凍して skinny run で起動
・ブラウザから localhost:8080 にアクセス
・Windows OS でも同じ手順です
!
!
!
!
!
!
起動まで(3)
・Skinny が推奨する sbt プロジェクトのひな形
・依存する jar がダウンロード済なので、初回起動時に
ダウンロード待ちをする必要がありません
・基本的な用途はデフォルトでカバーしているので最初か
ら sbt の設定方法を学ぶ必要がありません
・skinny スクリプトだけで起動するので Jenkins で
動かす場合もセットアップは一切不要
・2014 年時点で Scala は Eclipse ではなく IntelliJ
IDEA 推奨(Community Edition で可)
- Skinny MVC -
・#set で request scope に設定した値は
controller/view から参照可能となります
・メソッドの戻り値が response body となります
!
!
!
!
!
!
最初の Controller(1)
// src/main/scala/controller/RootController.scala!
!
package controller!
import skinny._!
class RootController extends ApplicationController {!
def index = {!
set(“name”, “JJUG”)!
render(“/root/index”)!
}!
}
・「Hello ${name}!」に「JJUG」が設定されました
!
!
!
!
!
!
!
!
最初の Controller(2)
! -# src/main/webapp/WEB-INF/views/root/index.html.ssp!
<%@val name: String %>!
<h1>Hello, ${name}!</h1>
・#set には様々な型の値を渡すことができます
・ここでは Scala のコレクションオブジェクトです
!
!
!
!
!
!
!
最初の Controller(3)
// src/main/scala/controller/RootController.scala!
!
package controller!
import skinny._!
class RootController extends ApplicationController {!
def index = {!
set(“numbers”, Seq(1,2,3,4,5))!
render(“/root/index”)!
}!
}!
・${numbers}」を使ったループと if 分岐の例です。
!
!
!
!
!
!
!
!
!
最初の Controller(4)
! -# src/main/webapp/WEB-INF/views/root/index.html.ssp!
!
<%@val numbers: Seq[Int] %>!
#for (n <- numbers)!
#if (n % 2 == 0)!
${n}!
#end!
#end!
・Scalatra が Servlet API の薄いラッパーとして簡
潔に記述できる DSL を提供しています
・例:status = 201, redirect(url), halt(400)
・どうしても必要になれば Servlet API を直接使うこと
も可能です(まずないとは思いますが)
・Servlet をある程度知っている人なら controller を
書く上でつまづくポイントは特にないはずです
!
最初の Controller(5)
・Skinny の Routing は Scalatra の DSL を使いま
す(Routes という trait で少しだけ拡張)
・controller の実体は Filter/Servlet なので
ServletContext にひもづけるだけです
!
!
!
!
!
最初の Routing(1)
! // src/main/scala/controller/Controllers.scala!
! object Controllers {!
! object root extends RootController with Routes {!
! val indexUrl = get(“/“)(index).as(‘index)

! }!
! override def mount(ctx: ServletContext): Unit = {!
! root.mount(ctx)!
! }!
! }!
・以下の場合 s.url(Controllers.root.indexUrl) で
実際の URL を取得できるので view template に
URL を直接書かずにすみます
!
!
!
!
!
!
最初の Routing(2)
! // src/main/scala/controller/Controllers.scala!
! object Controllers {!
! object root extends RootController with Routes {!
! val indexUrl = get(“/“)(index).as(‘index)

! }!
! // 省略!
! }!
・入力がある場合はバリデーション DSL を使います
・エラーの場合、エラーメッセージが request scope
に設定されるので入力フォームで表示するだけで OK
!
!
!
!
!
!
!
SkinnyValidator
! class MembersController extends ApplicationController {!
! protectFromForgery()!
! def createForm = validation(params,!
! paramKey(“name”) is required & maxLength(64),!
! paramKey(“email”) is email!
! )!
! def create = {!
! if (createForm.validate()) {!
! doCreate(params.permit(!
! “name” -> ParamType.String, “email” -> ParamType.String))

! } else {!
! render(“/members/input”)!
! }!
! }!
! }
・Scalate SSP(Scala Server Pages)の例は先ほ
どの Controller のところで少し触れました
・Scalate は SSP 以外に Scaml(≒Haml)、
Jade、Mustache もサポートしています
・SSP 以外を使う場合、拡張子を変えるだけで OK
・FreeMarker、Thymeleaf のサポートも拡張ライ
ブラリとして提供していますが Scala の API に十分対
応できないケースがあります
最初の View(1)
・Scalate も Play2 の Twirl もテンプレートファイル
から Scala のソースコードを出力してコンパイルします
・メリットはコンパイラによるチェックがあること
・デメリットはコンパイル待ちが発生すること
・Skinny での Scalate は、ローカルデバッグでは
precompile せずにこのデメリットを緩和し war 生成
時には precomile して、コンパイラチェックの恩恵を
受けるようにしています
最初の View(2)
・Skinny ORM を使って Rails ActiveRecord 的な
DB アクセスを行うモジュールの例を示します
・case class がエンティティで object が DAO です
!
!
!
!
!
!
最初の Model(1)
! sql”create table member (id serial, name varchar(64))”!
! ! .execute.apply()! !
!
! // src/main/scala/model/Member.scala!
! case class Member(id: Long, name: Option[String])!
!
! object Member extends SkinnyCRUDMapper[Member] {!
! lazy val defaultAlias = createAlias(“m”)!
! def extract(rs: WrappedResultSet, m: ResultName[Member]) =!
! new Member(rs.get(m.id), rs.get(m.name))!
! }
・Flyway を使った DB マイグレーションを使えばロー
カル開発用 DB を手軽に準備できます
!
!
!
!
!
!
!
最初の Model(2)
! ./skinny g migration createMember!
! // src/main/resources/db/migration/V20140514141738__createMember.sql!
! // V20140514141738__createMember.sql に DDL を書く!
!
! // “development” ENV の DB!
! ./skinny db:migrate!
!
! // “test” ENV の DB!
! ./skinny db:migrate test
・これだけで各種 API をすぐに使えます
!
!
!
!
!
!
!
!
最初の Model(3)
! // Insert!
! val id: Long = Member.createWithAttributes('name -> “JJUG")!
! // insert into member (name) values ('JJUG')!
!
! // Finder API!
! val ms: Seq[Member] = Member.findAll()!
! // select m.id as i_on_m, m.name as n_on_m from member m order by m.id;!
!
! // Querying API!
! val ms: Seq[Member] = Member.where(‘name -> “JJUG").apply()!
! // from member m where m.name = ‘JJUG'!
!
! // ScalikeJDBC QueryDSL!
! val m = Member.defaultAlias!
! val mopt: Option[Member] = Member.findBy(sqls.eq(m.name, "JJUG"))!
! // from member m where m.name = ‘JJUG'
・さらに country テーブルを追加して model を二つ
に増やして・・
!
!
!
!
!
!
!
最初の Model(4)
! case class Member(id: Long, name: Option[String])!
! object Member extends SkinnyCRUDMapper[Member] {!
! lazy val defaultAlias = createAlias(“m”)!
! def extract(rs: WrappedResultSet, m: ResultName[Member] =!
! new Member(rs.get(m.id), rs.get(m.name))!
! }!
!
! // create table country(id serial, name varchar(128) not null);!
! object class Country(id: Long, name: String)!
! object Country extends SkinnyCRUDMapper[Country] {!
! lazy val defaultAlias = createAlias(“m”)!
! def extract(rs: WrappedResultSet, c: ResultName[Country] =!
! new Country(rs.get(c.id), rs.get(c.name))!
! }
・関連を持たせます
!
!
!
!
!
!
!
!
最初の Model(5)
! case class Member(!
! id: Long, !
! name: Option[String]!
! countryId: Option[Long],!
! country: Option[Country] = None)!
!
! object Member extends SkinnyCRUDMapper[Member] {!
! val defaultAlias = createAlias(“m”)!
! def extract(rs: WrappedResultSet, m: ResultName[Member] =!
! new Member(rs.get(m.id), rs.get(m.name), rs.get(m.countryId))!
!
! val country = belongsTo[Country](Country, !
! (member, country) => member.copy(country = country)!
! )!
! }
・#joins で設定した association を解決した query
を実行します
!
!
!
!
!
!
!
!
最初の Model(6)
! // Insert!
! val countryId: Long = Country.createWithAttributes('name -> “Japan”)!
! val id = Member.createWithAttributes(!
! ‘name -> “JJUG”, ‘countryId -> countryId)!
!
! // member だけ!
! val m = Member.findById(id)!
! // from member m where m.id = ?!
!
! // country も!
! Member.joins(Member.country).findById(id)!
! // from member m left join country c on m.country_id = c.id where m.id = ?!
・#byDefault を指定すると #joins を呼ばなくても常
に join して取得します
!
!
!
!
!
!
!
!
最初の Model(7)
! case class Member(!
! id: Long, !
! name: Option[String]!
! countryId: Option[Long],!
! country: Option[Country] = None)!
!
! object Member extends SkinnyCRUDMapper[Member] {!
! val defaultAlias = createAlias(“m”)!
! def extract(rs: WrappedResultSet, m: ResultName[Member] =!
! new Member(rs.get(m.id), rs.get(m.name), rs.get(m.countryId))!
!
! val country = belongsTo[Country](Country, !
! (member, country) => member.copy(country = country)!
! ).byDefault!
! }
・auto commit でよければ AutoSession ベースで
・トランザクションは ScalikeJDBC の機能を使うか 1
リクエスト 1 トランザクションでよければ、スレッドロー
カルに扱う TxPerRequestFilter を使います
!
!
!
!
!
!
最初の Model(8)
! DB.localTx { implicit session =>!
! // このブロックから例外で抜けるときは全て自動 rollback される!
! Member.findById(id).map { member =>!
! member.copy(name = newName).save() // SkinnyRecord!
! MemberStatus.setAsActive(member)

! }.getOrElse {!
! val id = Member.createWithAttributes(‘name -> newName)!
! MemberStatus.addNewMemberAsActive(id)

! }!
! }
・controller などからそのまま呼び出すだけ
・fat controller にならないように注意(controller
に一通り実装した後で service object としてまとめる、
model のインタフェースを先に決める)
!
!
!
!
!
!
最初の Model(9)
! // src/main/scala/controller/MembersController.scala!
!
! import model.Member!
! class MembersController extends ApplicationController {!
! def showAll = {!
! set(“members”, Member.findAll())!
! render(“/members/showAll”)!
! }!
! }!
!
・ここで示した例は最も規約に沿っているケースです
・ニッチなケースでは少し煩雑になる場合もあります
・最悪、泥臭く対応する場合 ScalikeJDBC を直接扱え
ば何でもできるので「詰む」ことはありません
・SkinnyModel の API を実装していれば Slick など
別の DB ライブラリによる実装でも scaffold の
CRUD テンプレートに対応できます
・複数 DB 接続などよくあるケースは基本的に対応済です
が、未対応のニーズがあれば気軽にリクエストをください
最初の Model(10)
FactoryGirl
・Ruby で人気の thoughtbot/factory_girl にイン
スパイアされたテスト用の DB データ生成ツール
・YAML ではなく typesafe-config の HOCON で
記述、Scala コードも書ける
!
!
!
!
!
! member {!
! name=“JJUG”!
! luckyNumber="${scala.util.Random.nextInt(64)}"!
! }
! val member: Member = FactoryGirl(Member).create()!
! val member = FactoryGirl(Member).create(‘name -> “ScalaJP”)
- Skinny その他の機能 -
最初の scaffold(1)
・CRUD 画面を生成するなら scaffold が便利です
・テストコードも生成されます
!
!
!
!
!
!
!
! ./skinny g scaffold members member name:String birthday:Option[LocalDate] active:Boolean!
!
! *** Skinny Generator Task ***!
!
! "src/main/scala/controller/ApplicationController.scala" skipped.!
! "src/main/scala/controller/MembersController.scala" created.!
! "src/main/scala/controller/Controllers.scala" modified.!
! "src/test/scala/controller/MembersControllerSpec.scala" created.!
! "src/test/scala/integrationtest/MembersController_IntegrationTestSpec.scala" created.!
! "src/test/resources/factories.conf" modified.!
! "src/main/scala/model/Member.scala" created.!
! "src/test/scala/model/MemberSpec.scala" created.!
! "src/main/webapp/WEB-INF/views/members/_form.html.ssp" created.!
! "src/main/webapp/WEB-INF/views/members/new.html.ssp" created.!
! "src/main/webapp/WEB-INF/views/members/edit.html.ssp" created.!
! "src/main/webapp/WEB-INF/views/members/index.html.ssp" created.!
! "src/main/webapp/WEB-INF/views/members/show.html.ssp" created.!
! "src/main/resources/messages.conf" modified.!
! "src/main/resources/db/migration/V20140514173530__Create_members_table.sql" created.
最初の scaffold(2)
! ./skinny db:migrate !
! ./skinnny run!
!
! ./skinny db:migrate test!
! ./skinny test
・バリデーションを含む入力フォームの自動生成
!
!
!
!
!
!
!
!
最初の scaffold(3)
・flash も動作する状態になっています
!
!
!
!
!
!
!
!
最初の scaffold(4)
・あらかじめ pagination も実装されています
!
!
!
!
!
!
!
!
最初の scaffold(5)
既存 DB から scaffold
・既存 DB から scaffold を生成します
・ID となる PK があることが前提です
!
!
!
!
!
!
!
! ./skinny g reverse-scaffold members members member!
!
! *** Skinny Reverse Engineering Task ***!
!
! Table : members!
! ID : id:Long!
! Resources : members!
! Resource : member!
!
! Columns:!
! - name:String:varchar(512)!
! - birthday:Option[LocalDate]!
! - createdAt:DateTime!
! - updatedAt:DateTime!
!
! *** Skinny Generator Task ***!
!
! "src/main/scala/controller/ApplicationController.scala" skipped.!
! "src/main/scala/controller/MembersController.scala" created.!
! "src/main/scala/controller/Controllers.scala" modified.
・JavaMail をメソッドチェーンで簡潔に書けます
・Skinny 以外でも利用できます
!
!
!
!
!
!
!
!
SkinnyMailer
! val config = SkinnyMailerConfig.default.copy(!
! // JavaMail, SMTP configuration !
! )!
! val mailer = SkinnyMailer(config)!
! mailer!
! .to(“seratch@example.com”)!
! .cc(“users-ml@example.com”)!
! .subject(“JJUG CCC で登壇します!”)!
! .body {“””瀬良です。!
! |今度の日曜日に JJUG CCC 2014 Spring で Skinny について!
! |お話しさせていただくことになりました。!
! |”””.stripMargin}!
! .deliver()
Assets(1)
・ローカル起動時に CoffeeScript、React JSX、
Scala.js、Sass、LESS を JS/CSS に変換
・Sass 以外は JVM だけでも動作するので Windows
マシンを使う開発プロジェクトにも導入しやすいです
・Source Maps にも対応(要 native compiler)
・src/main/webapp/WEB-INF/assets/coffee
の下の CoffeeScript は src/main/webapp/
assets/js にある JS としてアクセスできます
・本番では出力された JS/CSS ファイルを使います
Assets(2)
・Scala.js、プロダクション利用可能な段階ではないで
すが、興味深いので触ってみてください
!
!
!
!
!
!
!
! ./skinny run!! ! ! // Terminal A!
! ./skinny scalajs:watch! // Terminal B!
! vim src/main/webapp/WEB-INF/assets/scala/Sample.scala! // Terminal C
デプロイ
・skinny package で war ファイルを生成
・package では全ての Scalate テンプレートをコンパ
イルするのでいつもアクセスしていないページのリンク切
れやエラーを検知できる場合もあります
・skinny package:standalone は java -jar で
Web サーバとして起動可能な jar を生成します
・Heroku などの PaaS へのデプロイも可能です
!
!
! ./skinny package!
! ./skinny package:standalone
- まとめと今後 -
Skinny の何が嬉しいか
・Play1/Rails 的なものが欲しいなら最適です
・全体的に Java での一般的なスタイルよりもほぼ本質
的なコードのみで簡潔に同じ機能を実装できます
・Skinny ORM + ScalikeJDBC は Java では実装
できない利便性・柔軟性を提供しています
・Scala での開発のボトルネックはコンパイル時間、周
辺ツールや流儀の学習コストと考え、それらを解決・軽減
して現実解を提案したいと思っています(そして、ある程
度は示せたと思っています)
Reactive だけじゃない
・Scala 界隈では Akka のアクターモデルや非同期処理
が注目されることが多く、またそれが本流です
・一方で Ruby っぽいけど型検査のあるもの、Java と
の互換性があってより簡潔なものへの需要も相当あると思っ
ています(少なくとも私はそれも欲しい)
・Skinny(Scalatra)と Akka を組み合わせたり
非同期処理を実装することも問題なくできますが、フレー
ムワークが提供する機能はいわゆる Better Java 的な
利便性を重視しています
ロードマップ
・Skinny 1.1 - Scala 2.10/2.11 クロスビルドと各
種ライブラリメジャーバージョンアップ対応
・極力、基本的な機能の互換性を崩す予定はなく、開発者
が楽できるように細かい改善を続けていく予定です
・安定して使っていただけるようにプロジェクトをハンド
ルしていきたいと思っています
・Scalatra 側で NIO なチャレンジも続けているような
ので、こちらが実用段階になってきたら Skinny でも何
かできるかもしれません
Skinny コミュニティ
・日本 Skinny Framework ユーザ会
http://skinnyjp.doorkeeper.jp/
・Skinny Framework Meetup Tokyo というイベ
ントを先日初めて行い 25 名の方々にご参加いただきまし
た、定期的に開催したいと思っています
・Tokyo 以外でも Meetup やりたいです
・Google Group に ML があります(英語)
・何かあればお気軽に Twitter で @seratch_ja や
@skinny-framework(英語)まで
Skinny Framework
なかなかよさそうだと思った方?
!
メディアでの日本語のドキュメントなど
機会があればぜひやりたいです。
公式ドキュメントも協力者がいれば
日本語版をやれるかもしれません。
!
!
(時間があれば)質疑応答。
何でも聞いてください。
!
!

Contenu connexe

Tendances

PHP in Java -Quercus- によるレガシーマイグレーション実例 #jjug_ccc #ccc_r12
PHP in Java -Quercus- によるレガシーマイグレーション実例 #jjug_ccc #ccc_r12PHP in Java -Quercus- によるレガシーマイグレーション実例 #jjug_ccc #ccc_r12
PHP in Java -Quercus- によるレガシーマイグレーション実例 #jjug_ccc #ccc_r12Ryuji Yamashita
 
ビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscala
ビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscalaビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscala
ビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscalatakezoe
 
Sbtのマルチプロジェクトはいいぞ
SbtのマルチプロジェクトはいいぞSbtのマルチプロジェクトはいいぞ
SbtのマルチプロジェクトはいいぞYoshitaka Fujii
 
Scala Warrior and type-safe front-end development with Scala.js
Scala Warrior and type-safe front-end development with Scala.jsScala Warrior and type-safe front-end development with Scala.js
Scala Warrior and type-safe front-end development with Scala.jstakezoe
 
Scalaはじめました!
Scalaはじめました!Scalaはじめました!
Scalaはじめました!Asami Abe
 
Contributing to Scala OSS from East Asia #ScalaMatsuri
 Contributing to Scala OSS from East Asia #ScalaMatsuri Contributing to Scala OSS from East Asia #ScalaMatsuri
Contributing to Scala OSS from East Asia #ScalaMatsuriKazuhiro Sera
 
Scala勉強会 初心者向けハンズオン前編
Scala勉強会 初心者向けハンズオン前編Scala勉強会 初心者向けハンズオン前編
Scala勉強会 初心者向けハンズオン前編takeuchi-tk
 
TDD BootCamp in JJUG CCC - レガシーコード対策編 -
TDD BootCamp in JJUG CCC - レガシーコード対策編 -TDD BootCamp in JJUG CCC - レガシーコード対策編 -
TDD BootCamp in JJUG CCC - レガシーコード対策編 -Shuji Watanabe
 
Scala再入門 @2014/02/08 Scala関西ビギナーズ第3回
Scala再入門 @2014/02/08 Scala関西ビギナーズ第3回Scala再入門 @2014/02/08 Scala関西ビギナーズ第3回
Scala再入門 @2014/02/08 Scala関西ビギナーズ第3回Asami Abe
 
Scala.js触ってみた
Scala.js触ってみたScala.js触ってみた
Scala.js触ってみたAsami Abe
 
JavaScriptユーティリティライブラリの紹介
JavaScriptユーティリティライブラリの紹介JavaScriptユーティリティライブラリの紹介
JavaScriptユーティリティライブラリの紹介Yusuke Hirao
 
Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略takezoe
 
1周遅れのScala入学 #nds41
1周遅れのScala入学 #nds411周遅れのScala入学 #nds41
1周遅れのScala入学 #nds41Kazumune Katagiri
 
Scala.jsはじめました!
Scala.jsはじめました!Scala.jsはじめました!
Scala.jsはじめました!K Kinzal
 
おっさんES6/ES2015,React.jsを学ぶ
おっさんES6/ES2015,React.jsを学ぶおっさんES6/ES2015,React.jsを学ぶ
おっさんES6/ES2015,React.jsを学ぶdcubeio
 
20140518 JJUG MySQL Clsuter as NoSQL
20140518 JJUG MySQL Clsuter as NoSQL20140518 JJUG MySQL Clsuter as NoSQL
20140518 JJUG MySQL Clsuter as NoSQLRyusuke Kajiyama
 
Ruby on Rails 入門
Ruby on Rails 入門Ruby on Rails 入門
Ruby on Rails 入門Yasuko Ohba
 
Scala.jsはじめました?
Scala.jsはじめました?Scala.jsはじめました?
Scala.jsはじめました?K Kinzal
 
ビッグじゃなくても使えるSpark Streaming
ビッグじゃなくても使えるSpark Streamingビッグじゃなくても使えるSpark Streaming
ビッグじゃなくても使えるSpark Streamingchibochibo
 
Scala界隈の近況
Scala界隈の近況Scala界隈の近況
Scala界隈の近況takezoe
 

Tendances (20)

PHP in Java -Quercus- によるレガシーマイグレーション実例 #jjug_ccc #ccc_r12
PHP in Java -Quercus- によるレガシーマイグレーション実例 #jjug_ccc #ccc_r12PHP in Java -Quercus- によるレガシーマイグレーション実例 #jjug_ccc #ccc_r12
PHP in Java -Quercus- によるレガシーマイグレーション実例 #jjug_ccc #ccc_r12
 
ビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscala
ビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscalaビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscala
ビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscala
 
Sbtのマルチプロジェクトはいいぞ
SbtのマルチプロジェクトはいいぞSbtのマルチプロジェクトはいいぞ
Sbtのマルチプロジェクトはいいぞ
 
Scala Warrior and type-safe front-end development with Scala.js
Scala Warrior and type-safe front-end development with Scala.jsScala Warrior and type-safe front-end development with Scala.js
Scala Warrior and type-safe front-end development with Scala.js
 
Scalaはじめました!
Scalaはじめました!Scalaはじめました!
Scalaはじめました!
 
Contributing to Scala OSS from East Asia #ScalaMatsuri
 Contributing to Scala OSS from East Asia #ScalaMatsuri Contributing to Scala OSS from East Asia #ScalaMatsuri
Contributing to Scala OSS from East Asia #ScalaMatsuri
 
Scala勉強会 初心者向けハンズオン前編
Scala勉強会 初心者向けハンズオン前編Scala勉強会 初心者向けハンズオン前編
Scala勉強会 初心者向けハンズオン前編
 
TDD BootCamp in JJUG CCC - レガシーコード対策編 -
TDD BootCamp in JJUG CCC - レガシーコード対策編 -TDD BootCamp in JJUG CCC - レガシーコード対策編 -
TDD BootCamp in JJUG CCC - レガシーコード対策編 -
 
Scala再入門 @2014/02/08 Scala関西ビギナーズ第3回
Scala再入門 @2014/02/08 Scala関西ビギナーズ第3回Scala再入門 @2014/02/08 Scala関西ビギナーズ第3回
Scala再入門 @2014/02/08 Scala関西ビギナーズ第3回
 
Scala.js触ってみた
Scala.js触ってみたScala.js触ってみた
Scala.js触ってみた
 
JavaScriptユーティリティライブラリの紹介
JavaScriptユーティリティライブラリの紹介JavaScriptユーティリティライブラリの紹介
JavaScriptユーティリティライブラリの紹介
 
Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略
 
1周遅れのScala入学 #nds41
1周遅れのScala入学 #nds411周遅れのScala入学 #nds41
1周遅れのScala入学 #nds41
 
Scala.jsはじめました!
Scala.jsはじめました!Scala.jsはじめました!
Scala.jsはじめました!
 
おっさんES6/ES2015,React.jsを学ぶ
おっさんES6/ES2015,React.jsを学ぶおっさんES6/ES2015,React.jsを学ぶ
おっさんES6/ES2015,React.jsを学ぶ
 
20140518 JJUG MySQL Clsuter as NoSQL
20140518 JJUG MySQL Clsuter as NoSQL20140518 JJUG MySQL Clsuter as NoSQL
20140518 JJUG MySQL Clsuter as NoSQL
 
Ruby on Rails 入門
Ruby on Rails 入門Ruby on Rails 入門
Ruby on Rails 入門
 
Scala.jsはじめました?
Scala.jsはじめました?Scala.jsはじめました?
Scala.jsはじめました?
 
ビッグじゃなくても使えるSpark Streaming
ビッグじゃなくても使えるSpark Streamingビッグじゃなくても使えるSpark Streaming
ビッグじゃなくても使えるSpark Streaming
 
Scala界隈の近況
Scala界隈の近況Scala界隈の近況
Scala界隈の近況
 

Similaire à [Japanese] Skinny Framework で始める Scala #jjug_ccc #ccc_r24

【LT】 怖くない恐怖のScala.js
【LT】 怖くない恐怖のScala.js【LT】 怖くない恐怖のScala.js
【LT】 怖くない恐怖のScala.jsYuto Suzuki
 
イマドキの現場で使えるJavaライブラリ事情
イマドキの現場で使えるJavaライブラリ事情イマドキの現場で使えるJavaライブラリ事情
イマドキの現場で使えるJavaライブラリ事情takezoe
 
Scalaでのプログラム開発
Scalaでのプログラム開発Scalaでのプログラム開発
Scalaでのプログラム開発Kota Mizushima
 
Scalaでプログラムを作りました
Scalaでプログラムを作りましたScalaでプログラムを作りました
Scalaでプログラムを作りましたTomoharu ASAMI
 
Skinny Framework 進捗どうですか? #fud_scala
Skinny Framework 進捗どうですか? #fud_scalaSkinny Framework 進捗どうですか? #fud_scala
Skinny Framework 進捗どうですか? #fud_scalaKazuhiro Sera
 
Play framework 2.0のちょっとした紹介
Play framework 2.0のちょっとした紹介Play framework 2.0のちょっとした紹介
Play framework 2.0のちょっとした紹介Ryo RKTM
 
Reladomo in Scala #scala_ks
Reladomo in Scala #scala_ks Reladomo in Scala #scala_ks
Reladomo in Scala #scala_ks Hiroshi Ito
 
「html5 boilerplate」から考える、これからのマークアップ
「html5 boilerplate」から考える、これからのマークアップ「html5 boilerplate」から考える、これからのマークアップ
「html5 boilerplate」から考える、これからのマークアップYasuhito Yabe
 
JavaScript.Next
JavaScript.NextJavaScript.Next
JavaScript.Nextdynamis
 
SDLoader SeasarCon 2009 Whire
SDLoader SeasarCon 2009 WhireSDLoader SeasarCon 2009 Whire
SDLoader SeasarCon 2009 WhireAkio Katayama
 
traceur-compilerで未来のJavaScriptを体験
traceur-compilerで未来のJavaScriptを体験traceur-compilerで未来のJavaScriptを体験
traceur-compilerで未来のJavaScriptを体験Toshio Ehara
 
Scala Daysに行ってみて
Scala Daysに行ってみてScala Daysに行ってみて
Scala Daysに行ってみてKota Mizushima
 
ASP.NET Core WebAPIでODataを使おう
ASP.NET Core WebAPIでODataを使おうASP.NET Core WebAPIでODataを使おう
ASP.NET Core WebAPIでODataを使おうDevTakas
 
JavaScript.Next Returns
JavaScript.Next ReturnsJavaScript.Next Returns
JavaScript.Next Returnsdynamis
 
はじめよう JavaFX 2.x(第3回 岡山Javaユーザー会)
はじめよう JavaFX 2.x(第3回 岡山Javaユーザー会)はじめよう JavaFX 2.x(第3回 岡山Javaユーザー会)
はじめよう JavaFX 2.x(第3回 岡山Javaユーザー会)a know
 

Similaire à [Japanese] Skinny Framework で始める Scala #jjug_ccc #ccc_r24 (20)

【LT】 怖くない恐怖のScala.js
【LT】 怖くない恐怖のScala.js【LT】 怖くない恐怖のScala.js
【LT】 怖くない恐怖のScala.js
 
イマドキの現場で使えるJavaライブラリ事情
イマドキの現場で使えるJavaライブラリ事情イマドキの現場で使えるJavaライブラリ事情
イマドキの現場で使えるJavaライブラリ事情
 
scala-kaigi1-sbt
scala-kaigi1-sbtscala-kaigi1-sbt
scala-kaigi1-sbt
 
Scalaでのプログラム開発
Scalaでのプログラム開発Scalaでのプログラム開発
Scalaでのプログラム開発
 
Scalaでプログラムを作りました
Scalaでプログラムを作りましたScalaでプログラムを作りました
Scalaでプログラムを作りました
 
Skinny Framework 進捗どうですか? #fud_scala
Skinny Framework 進捗どうですか? #fud_scalaSkinny Framework 進捗どうですか? #fud_scala
Skinny Framework 進捗どうですか? #fud_scala
 
Play framework 2.0のちょっとした紹介
Play framework 2.0のちょっとした紹介Play framework 2.0のちょっとした紹介
Play framework 2.0のちょっとした紹介
 
Reladomo in Scala #scala_ks
Reladomo in Scala #scala_ks Reladomo in Scala #scala_ks
Reladomo in Scala #scala_ks
 
「html5 boilerplate」から考える、これからのマークアップ
「html5 boilerplate」から考える、これからのマークアップ「html5 boilerplate」から考える、これからのマークアップ
「html5 boilerplate」から考える、これからのマークアップ
 
Antのススメ
AntのススメAntのススメ
Antのススメ
 
JavaScript.Next
JavaScript.NextJavaScript.Next
JavaScript.Next
 
SDLoader SeasarCon 2009 Whire
SDLoader SeasarCon 2009 WhireSDLoader SeasarCon 2009 Whire
SDLoader SeasarCon 2009 Whire
 
traceur-compilerで未来のJavaScriptを体験
traceur-compilerで未来のJavaScriptを体験traceur-compilerで未来のJavaScriptを体験
traceur-compilerで未来のJavaScriptを体験
 
Scala Daysに行ってみて
Scala Daysに行ってみてScala Daysに行ってみて
Scala Daysに行ってみて
 
Play勉強会 第3回
Play勉強会 第3回Play勉強会 第3回
Play勉強会 第3回
 
ASP.NET Core WebAPIでODataを使おう
ASP.NET Core WebAPIでODataを使おうASP.NET Core WebAPIでODataを使おう
ASP.NET Core WebAPIでODataを使おう
 
Startup JavaScript
Startup JavaScriptStartup JavaScript
Startup JavaScript
 
JavaScript.Next Returns
JavaScript.Next ReturnsJavaScript.Next Returns
JavaScript.Next Returns
 
はじめよう JavaFX 2.x(第3回 岡山Javaユーザー会)
はじめよう JavaFX 2.x(第3回 岡山Javaユーザー会)はじめよう JavaFX 2.x(第3回 岡山Javaユーザー会)
はじめよう JavaFX 2.x(第3回 岡山Javaユーザー会)
 
実戦Scala
実戦Scala実戦Scala
実戦Scala
 

Plus de Kazuhiro Sera

All I learned while working on a Scala OSS project for over six years #ScalaM...
All I learned while working on a Scala OSS project for over six years #ScalaM...All I learned while working on a Scala OSS project for over six years #ScalaM...
All I learned while working on a Scala OSS project for over six years #ScalaM...Kazuhiro Sera
 
Skinny Meetup Tokyo 2 日本語スライド
Skinny Meetup Tokyo 2 日本語スライドSkinny Meetup Tokyo 2 日本語スライド
Skinny Meetup Tokyo 2 日本語スライドKazuhiro Sera
 
Future on Servlet #scala_ks
Future on Servlet #scala_ksFuture on Servlet #scala_ks
Future on Servlet #scala_ksKazuhiro Sera
 
Servlet と Future の関わり方 #scala_ks
Servlet と Future の関わり方 #scala_ksServlet と Future の関わり方 #scala_ks
Servlet と Future の関わり方 #scala_ksKazuhiro Sera
 
マイクロサービス運用の所感 #m3dev
マイクロサービス運用の所感 #m3devマイクロサービス運用の所感 #m3dev
マイクロサービス運用の所感 #m3devKazuhiro Sera
 
Scala が支える医療系ウェブサービス #jissenscala
Scala が支える医療系ウェブサービス #jissenscalaScala が支える医療系ウェブサービス #jissenscala
Scala が支える医療系ウェブサービス #jissenscalaKazuhiro Sera
 
Scala on Rails #rakutentech
Scala on Rails #rakutentechScala on Rails #rakutentech
Scala on Rails #rakutentechKazuhiro Sera
 
Solid And Sustainable Development in Scala
Solid And Sustainable Development in ScalaSolid And Sustainable Development in Scala
Solid And Sustainable Development in ScalaKazuhiro Sera
 
Beginning Scala with Skinny Framework #jjug_ccc
Beginning Scala with Skinny Framework #jjug_cccBeginning Scala with Skinny Framework #jjug_ccc
Beginning Scala with Skinny Framework #jjug_cccKazuhiro Sera
 
Skinny Framework 1.0.0
Skinny Framework 1.0.0Skinny Framework 1.0.0
Skinny Framework 1.0.0Kazuhiro Sera
 
Skinny Framework Progress Situation
Skinny Framework Progress SituationSkinny Framework Progress Situation
Skinny Framework Progress SituationKazuhiro Sera
 
テストの運用について #m3dev
テストの運用について #m3devテストの運用について #m3dev
テストの運用について #m3devKazuhiro Sera
 
歌舞伎座.tech 1 LT - ScalikeJDBC Async & Skinny Framework #kbkz_tech
歌舞伎座.tech 1 LT - ScalikeJDBC Async & Skinny Framework #kbkz_tech歌舞伎座.tech 1 LT - ScalikeJDBC Async & Skinny Framework #kbkz_tech
歌舞伎座.tech 1 LT - ScalikeJDBC Async & Skinny Framework #kbkz_techKazuhiro Sera
 
Kabukiza.tech 1 LT - ScalikeJDBC-Async & Skinny Framework #kbkz_tech
Kabukiza.tech 1 LT - ScalikeJDBC-Async & Skinny Framework #kbkz_techKabukiza.tech 1 LT - ScalikeJDBC-Async & Skinny Framework #kbkz_tech
Kabukiza.tech 1 LT - ScalikeJDBC-Async & Skinny Framework #kbkz_techKazuhiro Sera
 
テストを書くのが嫌いな君へ #m3dev
テストを書くのが嫌いな君へ #m3devテストを書くのが嫌いな君へ #m3dev
テストを書くのが嫌いな君へ #m3devKazuhiro Sera
 
Skinny Controllers, Skinny Models
Skinny Controllers, Skinny ModelsSkinny Controllers, Skinny Models
Skinny Controllers, Skinny ModelsKazuhiro Sera
 
ScalikeJDBC Tutorial for Beginners
ScalikeJDBC Tutorial for BeginnersScalikeJDBC Tutorial for Beginners
ScalikeJDBC Tutorial for BeginnersKazuhiro Sera
 
A Test Code Generator for RSpec Users
A Test Code Generator for RSpec UsersA Test Code Generator for RSpec Users
A Test Code Generator for RSpec UsersKazuhiro Sera
 

Plus de Kazuhiro Sera (20)

All I learned while working on a Scala OSS project for over six years #ScalaM...
All I learned while working on a Scala OSS project for over six years #ScalaM...All I learned while working on a Scala OSS project for over six years #ScalaM...
All I learned while working on a Scala OSS project for over six years #ScalaM...
 
Skinny Meetup Tokyo 2 日本語スライド
Skinny Meetup Tokyo 2 日本語スライドSkinny Meetup Tokyo 2 日本語スライド
Skinny Meetup Tokyo 2 日本語スライド
 
Skinny 2 Update
Skinny 2 UpdateSkinny 2 Update
Skinny 2 Update
 
Future on Servlet #scala_ks
Future on Servlet #scala_ksFuture on Servlet #scala_ks
Future on Servlet #scala_ks
 
Servlet と Future の関わり方 #scala_ks
Servlet と Future の関わり方 #scala_ksServlet と Future の関わり方 #scala_ks
Servlet と Future の関わり方 #scala_ks
 
マイクロサービス運用の所感 #m3dev
マイクロサービス運用の所感 #m3devマイクロサービス運用の所感 #m3dev
マイクロサービス運用の所感 #m3dev
 
Scala が支える医療系ウェブサービス #jissenscala
Scala が支える医療系ウェブサービス #jissenscalaScala が支える医療系ウェブサービス #jissenscala
Scala が支える医療系ウェブサービス #jissenscala
 
Scala on Rails #rakutentech
Scala on Rails #rakutentechScala on Rails #rakutentech
Scala on Rails #rakutentech
 
Solid And Sustainable Development in Scala
Solid And Sustainable Development in ScalaSolid And Sustainable Development in Scala
Solid And Sustainable Development in Scala
 
Beginning Scala with Skinny Framework #jjug_ccc
Beginning Scala with Skinny Framework #jjug_cccBeginning Scala with Skinny Framework #jjug_ccc
Beginning Scala with Skinny Framework #jjug_ccc
 
Skinny Framework 1.0.0
Skinny Framework 1.0.0Skinny Framework 1.0.0
Skinny Framework 1.0.0
 
Skinny Framework Progress Situation
Skinny Framework Progress SituationSkinny Framework Progress Situation
Skinny Framework Progress Situation
 
テストの運用について #m3dev
テストの運用について #m3devテストの運用について #m3dev
テストの運用について #m3dev
 
歌舞伎座.tech 1 LT - ScalikeJDBC Async & Skinny Framework #kbkz_tech
歌舞伎座.tech 1 LT - ScalikeJDBC Async & Skinny Framework #kbkz_tech歌舞伎座.tech 1 LT - ScalikeJDBC Async & Skinny Framework #kbkz_tech
歌舞伎座.tech 1 LT - ScalikeJDBC Async & Skinny Framework #kbkz_tech
 
Kabukiza.tech 1 LT - ScalikeJDBC-Async & Skinny Framework #kbkz_tech
Kabukiza.tech 1 LT - ScalikeJDBC-Async & Skinny Framework #kbkz_techKabukiza.tech 1 LT - ScalikeJDBC-Async & Skinny Framework #kbkz_tech
Kabukiza.tech 1 LT - ScalikeJDBC-Async & Skinny Framework #kbkz_tech
 
テストを書くのが嫌いな君へ #m3dev
テストを書くのが嫌いな君へ #m3devテストを書くのが嫌いな君へ #m3dev
テストを書くのが嫌いな君へ #m3dev
 
Skinny Controllers, Skinny Models
Skinny Controllers, Skinny ModelsSkinny Controllers, Skinny Models
Skinny Controllers, Skinny Models
 
ScalikeJDBC Tutorial for Beginners
ScalikeJDBC Tutorial for BeginnersScalikeJDBC Tutorial for Beginners
ScalikeJDBC Tutorial for Beginners
 
A Test Code Generator for RSpec Users
A Test Code Generator for RSpec UsersA Test Code Generator for RSpec Users
A Test Code Generator for RSpec Users
 
Crucible @ M3, Inc.
Crucible @ M3, Inc.Crucible @ M3, Inc.
Crucible @ M3, Inc.
 

Dernier

Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxAtomu Hidaka
 
20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directoryosamut
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000Shota Ito
 
プレイマットのパターン生成支援ツール
プレイマットのパターン生成支援ツールプレイマットのパターン生成支援ツール
プレイマットのパターン生成支援ツールsugiuralab
 
プレイマットのパターン生成支援ツールの評価
プレイマットのパターン生成支援ツールの評価プレイマットのパターン生成支援ツールの評価
プレイマットのパターン生成支援ツールの評価sugiuralab
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Danieldanielhu54
 

Dernier (8)

Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
 
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
 
20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000
 
プレイマットのパターン生成支援ツール
プレイマットのパターン生成支援ツールプレイマットのパターン生成支援ツール
プレイマットのパターン生成支援ツール
 
プレイマットのパターン生成支援ツールの評価
プレイマットのパターン生成支援ツールの評価プレイマットのパターン生成支援ツールの評価
プレイマットのパターン生成支援ツールの評価
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
 

[Japanese] Skinny Framework で始める Scala #jjug_ccc #ccc_r24

  • 1. Skinny Framework で始める Scala 瀬良 和弘 @seratch(_ja) エムスリー株式会社 ソフトウェアエンジニア 日本 Skinny Framework ユーザ会 JJUG CCC 2014 Spring 2014/05/18
  • 2. 私について ・本業は主に Web アプリ、バックエンド API 開発、社 内ツール諸々の運用整備の整備などに従事 ・Scala は 2009 年に始めて触った(だけ) ・2011 年の正月休みから少しずつ使い始めた ・2011 - 2012 年、Akasaka.scala という勉強会 を隔週で主催していた(現在は休止中) ・社内外の Scala プロジェクトでメイン開発者として開 発している OSS を利用いただくようになってきた (ScalikeJDBC、Skinny Framework)
  • 4. Skinny Framework は Java な現場、SI 業界の案件でも 十分使えるはずと思っています。 ! !
  • 7. Scala のおさらい ・2003 年に生まれた比較的新しい言語 ・オブジェクト指向と関数型プログラミングの融合 ・スイス連邦工科大学教授 Martin Odersky ・2011 年に出資を受けて Typesafe 社を立ち上げ ・Typesafe 社は Scala の開発だけでなく sbt、 Akka、Play2、Slick、Spray 等のツール・ライブラ リのメンテナンス・商用サポートも提供 ・Rod Johnson 氏が Typesafe 社に参加し話題に
  • 8. JJUG 的? Scala のメリット ・オブジェクト指向 + 関数型プログラミング ・静的型付け、型推論により記述の簡潔さを両立 ・デフォルトが immutable な API ・並行処理、非同期プログラミングとの親和性 ・JVM レベルの処理性能が期待できる ・Java で書かれた枯れた実装も流用できる ・大規模なプロダクション利用実績が多い ・GitHub 時代の言語、活気のあるコミュニティ
  • 9. JJUG 的? Scala のデメリット ・Java と比べてコンパイル時間が長い ・言語のバイナリ互換性などに対応する運用コスト ・Java エンジニアにとって意外にジャンプが大きい ・表現力の裏返しで OOP と関数型プログラミングが混在 するなどスタイルが統一されない懸念がある ・Java と比べて、標準規格よりも動く OSS 実装がリー ドする世界なので、あまり受け身なスタンスだと難しい ・既に Scala を使いこなしているエンジニアの母数はま だまだ少なく、人材採用面での不安がある
  • 10. Scala の互換性の件 ・最新バージョンは 2.11.0 ・2.10.0 ∼ 2.10.4 はバイナリ互換あり ・2.10.4 と 2.11.0 はバイナリ互換なし ・2.9 までは 2.9.x ごとに互換性がなかった(!) ・2.9(と 2.10 の一部)は Java8 で動作しない ・Maven でいう artifactId にバイナリバージョンが suffix としてつく(例:scalikejdbc_2.11) ・メンテされなくなったライブラリは新しいバイナリバー ジョンでビルドされなくなるので選定に注意が必要
  • 12. Web フレームワーク事情 ・長らく Lift ほぼ一択の時代(事例:4sq) ・2012 年春 Play Framework 2.0 が登場 ・約 2 年経ち、現在は圧倒的に Play2 の人気が高い ・より軽量なフレームワークはいくつか現実的な選択肢が ある(Scalatra、Unfiltered、Spray など) ・Play2、Spray は現在 Typesafe 社のプロダクト ! ・2014 年春 Skinny Framework 1.0
  • 13. DB ライブラリ事情 ・あくまで目安として GitHub スター数で比較 ・Slick (879)、Squeryl (358)、ScalikeJDBC (254) がベスト 3、Slick は旧 ScalaQuery ・他には scala-activerecord (164)、Activate (155)、SORM (124) など ! ・ScalikeJDBC は機能不足によって実務上困ることは ないが ORM よりもコード量は多くなりがち ・そこを埋めるのが Skinny ORM
  • 14. テンプレートエンジン事情 ・Scalate は長年メンテされており、SSP、Scaml、 Jade、Mustache と複数の文法が使える ・Play2 の Scala Template が最近独立(Twirl) ・Lift はタグを埋める独自のやり方 ・Circumflex という Web フレームワークは FreeMarker の Scala 対応を実装(Skinny はこれ を fork して Scala 2.10 に対応させた) ! ・Skinny では Scalate を採用(理由は後ほど)
  • 17. Skinny Framework ・2014/03/28 に 1.0.0 リリース(現在 1.0.14) ・Scala on Rails がキャッチコピー ・機能豊富なフルスタック Web フレームワーク ・MVC、ORM、DB マイグレーション、メール送信 ・scaffold などの自動生成機能 ・Play2 と違い Servlet コンテナで動作 ・Java 1.6 以上、Servlet 3.0 以上 ・war、Jetty 埋め込み jar ファイル生成
  • 19. Scala on Rails? ・それって Play2 のことではないの?(否) ・Play2 本体は HTTP 周り以外の機能をあまり持って いない、今後も周辺を拡充するようには見えない ・Rails、Play1 のように HTML を返す Web アプリ 開発の利便性に最適化しているわけではない ・Play2 は Rails 風味な記述で NIO ベースのサーバア プリを開発するためのフレームワーク ・JSON API サーバ、Akka の特長を活かしたアプリ ケーションなどに適している
  • 20. Skinny の構成 ・極力自作を避け、実績があり、かつ Skinny の思想に 合うライブラリを土台とし、その上に作り込んでいる ・ルーティング、Servlet ラッパーのために Scalatra ・デフォルトテンプレートエンジンとして Scalate ・ORM の土台として ScalikeJDBC ・DB マイグレーションは Flyway ・JSON の処理に json4s ・入力バリデーション、メール送信はオリジナル ・後ほど、個別の機能を順次紹介します
  • 22. 起動まで(1) ・必要なのは JDK(1.6 以上)のみ ・skinny-framework.org にある以下のダウンロー ドボタンから約 80MB の zip ファイルをダウンロードし てください ! ! ! ! !
  • 23. 起動まで(2) ・zip ファイルを解凍して skinny run で起動 ・ブラウザから localhost:8080 にアクセス ・Windows OS でも同じ手順です ! ! ! ! ! !
  • 24. 起動まで(3) ・Skinny が推奨する sbt プロジェクトのひな形 ・依存する jar がダウンロード済なので、初回起動時に ダウンロード待ちをする必要がありません ・基本的な用途はデフォルトでカバーしているので最初か ら sbt の設定方法を学ぶ必要がありません ・skinny スクリプトだけで起動するので Jenkins で 動かす場合もセットアップは一切不要 ・2014 年時点で Scala は Eclipse ではなく IntelliJ IDEA 推奨(Community Edition で可)
  • 26. ・#set で request scope に設定した値は controller/view から参照可能となります ・メソッドの戻り値が response body となります ! ! ! ! ! ! 最初の Controller(1) // src/main/scala/controller/RootController.scala! ! package controller! import skinny._! class RootController extends ApplicationController {! def index = {! set(“name”, “JJUG”)! render(“/root/index”)! }! }
  • 27. ・「Hello ${name}!」に「JJUG」が設定されました ! ! ! ! ! ! ! ! 最初の Controller(2) ! -# src/main/webapp/WEB-INF/views/root/index.html.ssp! <%@val name: String %>! <h1>Hello, ${name}!</h1>
  • 28. ・#set には様々な型の値を渡すことができます ・ここでは Scala のコレクションオブジェクトです ! ! ! ! ! ! ! 最初の Controller(3) // src/main/scala/controller/RootController.scala! ! package controller! import skinny._! class RootController extends ApplicationController {! def index = {! set(“numbers”, Seq(1,2,3,4,5))! render(“/root/index”)! }! }!
  • 29. ・${numbers}」を使ったループと if 分岐の例です。 ! ! ! ! ! ! ! ! ! 最初の Controller(4) ! -# src/main/webapp/WEB-INF/views/root/index.html.ssp! ! <%@val numbers: Seq[Int] %>! #for (n <- numbers)! #if (n % 2 == 0)! ${n}! #end! #end!
  • 30. ・Scalatra が Servlet API の薄いラッパーとして簡 潔に記述できる DSL を提供しています ・例:status = 201, redirect(url), halt(400) ・どうしても必要になれば Servlet API を直接使うこと も可能です(まずないとは思いますが) ・Servlet をある程度知っている人なら controller を 書く上でつまづくポイントは特にないはずです ! 最初の Controller(5)
  • 31. ・Skinny の Routing は Scalatra の DSL を使いま す(Routes という trait で少しだけ拡張) ・controller の実体は Filter/Servlet なので ServletContext にひもづけるだけです ! ! ! ! ! 最初の Routing(1) ! // src/main/scala/controller/Controllers.scala! ! object Controllers {! ! object root extends RootController with Routes {! ! val indexUrl = get(“/“)(index).as(‘index)
 ! }! ! override def mount(ctx: ServletContext): Unit = {! ! root.mount(ctx)! ! }! ! }!
  • 32. ・以下の場合 s.url(Controllers.root.indexUrl) で 実際の URL を取得できるので view template に URL を直接書かずにすみます ! ! ! ! ! ! 最初の Routing(2) ! // src/main/scala/controller/Controllers.scala! ! object Controllers {! ! object root extends RootController with Routes {! ! val indexUrl = get(“/“)(index).as(‘index)
 ! }! ! // 省略! ! }!
  • 33. ・入力がある場合はバリデーション DSL を使います ・エラーの場合、エラーメッセージが request scope に設定されるので入力フォームで表示するだけで OK ! ! ! ! ! ! ! SkinnyValidator ! class MembersController extends ApplicationController {! ! protectFromForgery()! ! def createForm = validation(params,! ! paramKey(“name”) is required & maxLength(64),! ! paramKey(“email”) is email! ! )! ! def create = {! ! if (createForm.validate()) {! ! doCreate(params.permit(! ! “name” -> ParamType.String, “email” -> ParamType.String))
 ! } else {! ! render(“/members/input”)! ! }! ! }! ! }
  • 34. ・Scalate SSP(Scala Server Pages)の例は先ほ どの Controller のところで少し触れました ・Scalate は SSP 以外に Scaml(≒Haml)、 Jade、Mustache もサポートしています ・SSP 以外を使う場合、拡張子を変えるだけで OK ・FreeMarker、Thymeleaf のサポートも拡張ライ ブラリとして提供していますが Scala の API に十分対 応できないケースがあります 最初の View(1)
  • 35. ・Scalate も Play2 の Twirl もテンプレートファイル から Scala のソースコードを出力してコンパイルします ・メリットはコンパイラによるチェックがあること ・デメリットはコンパイル待ちが発生すること ・Skinny での Scalate は、ローカルデバッグでは precompile せずにこのデメリットを緩和し war 生成 時には precomile して、コンパイラチェックの恩恵を 受けるようにしています 最初の View(2)
  • 36. ・Skinny ORM を使って Rails ActiveRecord 的な DB アクセスを行うモジュールの例を示します ・case class がエンティティで object が DAO です ! ! ! ! ! ! 最初の Model(1) ! sql”create table member (id serial, name varchar(64))”! ! ! .execute.apply()! ! ! ! // src/main/scala/model/Member.scala! ! case class Member(id: Long, name: Option[String])! ! ! object Member extends SkinnyCRUDMapper[Member] {! ! lazy val defaultAlias = createAlias(“m”)! ! def extract(rs: WrappedResultSet, m: ResultName[Member]) =! ! new Member(rs.get(m.id), rs.get(m.name))! ! }
  • 37. ・Flyway を使った DB マイグレーションを使えばロー カル開発用 DB を手軽に準備できます ! ! ! ! ! ! ! 最初の Model(2) ! ./skinny g migration createMember! ! // src/main/resources/db/migration/V20140514141738__createMember.sql! ! // V20140514141738__createMember.sql に DDL を書く! ! ! // “development” ENV の DB! ! ./skinny db:migrate! ! ! // “test” ENV の DB! ! ./skinny db:migrate test
  • 38. ・これだけで各種 API をすぐに使えます ! ! ! ! ! ! ! ! 最初の Model(3) ! // Insert! ! val id: Long = Member.createWithAttributes('name -> “JJUG")! ! // insert into member (name) values ('JJUG')! ! ! // Finder API! ! val ms: Seq[Member] = Member.findAll()! ! // select m.id as i_on_m, m.name as n_on_m from member m order by m.id;! ! ! // Querying API! ! val ms: Seq[Member] = Member.where(‘name -> “JJUG").apply()! ! // from member m where m.name = ‘JJUG'! ! ! // ScalikeJDBC QueryDSL! ! val m = Member.defaultAlias! ! val mopt: Option[Member] = Member.findBy(sqls.eq(m.name, "JJUG"))! ! // from member m where m.name = ‘JJUG'
  • 39. ・さらに country テーブルを追加して model を二つ に増やして・・ ! ! ! ! ! ! ! 最初の Model(4) ! case class Member(id: Long, name: Option[String])! ! object Member extends SkinnyCRUDMapper[Member] {! ! lazy val defaultAlias = createAlias(“m”)! ! def extract(rs: WrappedResultSet, m: ResultName[Member] =! ! new Member(rs.get(m.id), rs.get(m.name))! ! }! ! ! // create table country(id serial, name varchar(128) not null);! ! object class Country(id: Long, name: String)! ! object Country extends SkinnyCRUDMapper[Country] {! ! lazy val defaultAlias = createAlias(“m”)! ! def extract(rs: WrappedResultSet, c: ResultName[Country] =! ! new Country(rs.get(c.id), rs.get(c.name))! ! }
  • 40. ・関連を持たせます ! ! ! ! ! ! ! ! 最初の Model(5) ! case class Member(! ! id: Long, ! ! name: Option[String]! ! countryId: Option[Long],! ! country: Option[Country] = None)! ! ! object Member extends SkinnyCRUDMapper[Member] {! ! val defaultAlias = createAlias(“m”)! ! def extract(rs: WrappedResultSet, m: ResultName[Member] =! ! new Member(rs.get(m.id), rs.get(m.name), rs.get(m.countryId))! ! ! val country = belongsTo[Country](Country, ! ! (member, country) => member.copy(country = country)! ! )! ! }
  • 41. ・#joins で設定した association を解決した query を実行します ! ! ! ! ! ! ! ! 最初の Model(6) ! // Insert! ! val countryId: Long = Country.createWithAttributes('name -> “Japan”)! ! val id = Member.createWithAttributes(! ! ‘name -> “JJUG”, ‘countryId -> countryId)! ! ! // member だけ! ! val m = Member.findById(id)! ! // from member m where m.id = ?! ! ! // country も! ! Member.joins(Member.country).findById(id)! ! // from member m left join country c on m.country_id = c.id where m.id = ?!
  • 42. ・#byDefault を指定すると #joins を呼ばなくても常 に join して取得します ! ! ! ! ! ! ! ! 最初の Model(7) ! case class Member(! ! id: Long, ! ! name: Option[String]! ! countryId: Option[Long],! ! country: Option[Country] = None)! ! ! object Member extends SkinnyCRUDMapper[Member] {! ! val defaultAlias = createAlias(“m”)! ! def extract(rs: WrappedResultSet, m: ResultName[Member] =! ! new Member(rs.get(m.id), rs.get(m.name), rs.get(m.countryId))! ! ! val country = belongsTo[Country](Country, ! ! (member, country) => member.copy(country = country)! ! ).byDefault! ! }
  • 43. ・auto commit でよければ AutoSession ベースで ・トランザクションは ScalikeJDBC の機能を使うか 1 リクエスト 1 トランザクションでよければ、スレッドロー カルに扱う TxPerRequestFilter を使います ! ! ! ! ! ! 最初の Model(8) ! DB.localTx { implicit session =>! ! // このブロックから例外で抜けるときは全て自動 rollback される! ! Member.findById(id).map { member =>! ! member.copy(name = newName).save() // SkinnyRecord! ! MemberStatus.setAsActive(member)
 ! }.getOrElse {! ! val id = Member.createWithAttributes(‘name -> newName)! ! MemberStatus.addNewMemberAsActive(id)
 ! }! ! }
  • 44. ・controller などからそのまま呼び出すだけ ・fat controller にならないように注意(controller に一通り実装した後で service object としてまとめる、 model のインタフェースを先に決める) ! ! ! ! ! ! 最初の Model(9) ! // src/main/scala/controller/MembersController.scala! ! ! import model.Member! ! class MembersController extends ApplicationController {! ! def showAll = {! ! set(“members”, Member.findAll())! ! render(“/members/showAll”)! ! }! ! }! !
  • 45. ・ここで示した例は最も規約に沿っているケースです ・ニッチなケースでは少し煩雑になる場合もあります ・最悪、泥臭く対応する場合 ScalikeJDBC を直接扱え ば何でもできるので「詰む」ことはありません ・SkinnyModel の API を実装していれば Slick など 別の DB ライブラリによる実装でも scaffold の CRUD テンプレートに対応できます ・複数 DB 接続などよくあるケースは基本的に対応済です が、未対応のニーズがあれば気軽にリクエストをください 最初の Model(10)
  • 46. FactoryGirl ・Ruby で人気の thoughtbot/factory_girl にイン スパイアされたテスト用の DB データ生成ツール ・YAML ではなく typesafe-config の HOCON で 記述、Scala コードも書ける ! ! ! ! ! ! member {! ! name=“JJUG”! ! luckyNumber="${scala.util.Random.nextInt(64)}"! ! } ! val member: Member = FactoryGirl(Member).create()! ! val member = FactoryGirl(Member).create(‘name -> “ScalaJP”)
  • 48. 最初の scaffold(1) ・CRUD 画面を生成するなら scaffold が便利です ・テストコードも生成されます ! ! ! ! ! ! ! ! ./skinny g scaffold members member name:String birthday:Option[LocalDate] active:Boolean! ! ! *** Skinny Generator Task ***! ! ! "src/main/scala/controller/ApplicationController.scala" skipped.! ! "src/main/scala/controller/MembersController.scala" created.! ! "src/main/scala/controller/Controllers.scala" modified.! ! "src/test/scala/controller/MembersControllerSpec.scala" created.! ! "src/test/scala/integrationtest/MembersController_IntegrationTestSpec.scala" created.! ! "src/test/resources/factories.conf" modified.! ! "src/main/scala/model/Member.scala" created.! ! "src/test/scala/model/MemberSpec.scala" created.! ! "src/main/webapp/WEB-INF/views/members/_form.html.ssp" created.! ! "src/main/webapp/WEB-INF/views/members/new.html.ssp" created.! ! "src/main/webapp/WEB-INF/views/members/edit.html.ssp" created.! ! "src/main/webapp/WEB-INF/views/members/index.html.ssp" created.! ! "src/main/webapp/WEB-INF/views/members/show.html.ssp" created.! ! "src/main/resources/messages.conf" modified.! ! "src/main/resources/db/migration/V20140514173530__Create_members_table.sql" created.
  • 49. 最初の scaffold(2) ! ./skinny db:migrate ! ! ./skinnny run! ! ! ./skinny db:migrate test! ! ./skinny test
  • 53. 既存 DB から scaffold ・既存 DB から scaffold を生成します ・ID となる PK があることが前提です ! ! ! ! ! ! ! ! ./skinny g reverse-scaffold members members member! ! ! *** Skinny Reverse Engineering Task ***! ! ! Table : members! ! ID : id:Long! ! Resources : members! ! Resource : member! ! ! Columns:! ! - name:String:varchar(512)! ! - birthday:Option[LocalDate]! ! - createdAt:DateTime! ! - updatedAt:DateTime! ! ! *** Skinny Generator Task ***! ! ! "src/main/scala/controller/ApplicationController.scala" skipped.! ! "src/main/scala/controller/MembersController.scala" created.! ! "src/main/scala/controller/Controllers.scala" modified.
  • 54. ・JavaMail をメソッドチェーンで簡潔に書けます ・Skinny 以外でも利用できます ! ! ! ! ! ! ! ! SkinnyMailer ! val config = SkinnyMailerConfig.default.copy(! ! // JavaMail, SMTP configuration ! ! )! ! val mailer = SkinnyMailer(config)! ! mailer! ! .to(“seratch@example.com”)! ! .cc(“users-ml@example.com”)! ! .subject(“JJUG CCC で登壇します!”)! ! .body {“””瀬良です。! ! |今度の日曜日に JJUG CCC 2014 Spring で Skinny について! ! |お話しさせていただくことになりました。! ! |”””.stripMargin}! ! .deliver()
  • 55. Assets(1) ・ローカル起動時に CoffeeScript、React JSX、 Scala.js、Sass、LESS を JS/CSS に変換 ・Sass 以外は JVM だけでも動作するので Windows マシンを使う開発プロジェクトにも導入しやすいです ・Source Maps にも対応(要 native compiler) ・src/main/webapp/WEB-INF/assets/coffee の下の CoffeeScript は src/main/webapp/ assets/js にある JS としてアクセスできます ・本番では出力された JS/CSS ファイルを使います
  • 56. Assets(2) ・Scala.js、プロダクション利用可能な段階ではないで すが、興味深いので触ってみてください ! ! ! ! ! ! ! ! ./skinny run!! ! ! // Terminal A! ! ./skinny scalajs:watch! // Terminal B! ! vim src/main/webapp/WEB-INF/assets/scala/Sample.scala! // Terminal C
  • 57. デプロイ ・skinny package で war ファイルを生成 ・package では全ての Scalate テンプレートをコンパ イルするのでいつもアクセスしていないページのリンク切 れやエラーを検知できる場合もあります ・skinny package:standalone は java -jar で Web サーバとして起動可能な jar を生成します ・Heroku などの PaaS へのデプロイも可能です ! ! ! ./skinny package! ! ./skinny package:standalone
  • 59. Skinny の何が嬉しいか ・Play1/Rails 的なものが欲しいなら最適です ・全体的に Java での一般的なスタイルよりもほぼ本質 的なコードのみで簡潔に同じ機能を実装できます ・Skinny ORM + ScalikeJDBC は Java では実装 できない利便性・柔軟性を提供しています ・Scala での開発のボトルネックはコンパイル時間、周 辺ツールや流儀の学習コストと考え、それらを解決・軽減 して現実解を提案したいと思っています(そして、ある程 度は示せたと思っています)
  • 60. Reactive だけじゃない ・Scala 界隈では Akka のアクターモデルや非同期処理 が注目されることが多く、またそれが本流です ・一方で Ruby っぽいけど型検査のあるもの、Java と の互換性があってより簡潔なものへの需要も相当あると思っ ています(少なくとも私はそれも欲しい) ・Skinny(Scalatra)と Akka を組み合わせたり 非同期処理を実装することも問題なくできますが、フレー ムワークが提供する機能はいわゆる Better Java 的な 利便性を重視しています
  • 61. ロードマップ ・Skinny 1.1 - Scala 2.10/2.11 クロスビルドと各 種ライブラリメジャーバージョンアップ対応 ・極力、基本的な機能の互換性を崩す予定はなく、開発者 が楽できるように細かい改善を続けていく予定です ・安定して使っていただけるようにプロジェクトをハンド ルしていきたいと思っています ・Scalatra 側で NIO なチャレンジも続けているような ので、こちらが実用段階になってきたら Skinny でも何 かできるかもしれません
  • 62. Skinny コミュニティ ・日本 Skinny Framework ユーザ会 http://skinnyjp.doorkeeper.jp/ ・Skinny Framework Meetup Tokyo というイベ ントを先日初めて行い 25 名の方々にご参加いただきまし た、定期的に開催したいと思っています ・Tokyo 以外でも Meetup やりたいです ・Google Group に ML があります(英語) ・何かあればお気軽に Twitter で @seratch_ja や @skinny-framework(英語)まで