[Japanese] Skinny Framework で始める Scala #jjug_ccc #ccc_r24
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

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

on

  • 6,050 views

English version is here: http://www.slideshare.net/seratch/jjug-ccc-2014springeng

English version is here: http://www.slideshare.net/seratch/jjug-ccc-2014springeng

http://www.java-users.jp/?page_id=1048#R2-4

Statistics

Views

Total Views
6,050
Views on SlideShare
4,932
Embed Views
1,118

Actions

Likes
23
Downloads
36
Comments
0

12 Embeds 1,118

http://seratch.hatenablog.jp 674
https://twitter.com 241
http://osyyare.blogspot.jp 167
http://www.slideee.com 12
http://feedly.com 8
http://osyyare.blogspot.com 5
http://s.deeeki.com 4
https://tweetdeck.twitter.com 2
http://translate.googleusercontent.com 2
http://digg.com 1
http://webcache.googleusercontent.com 1
http://192.168.33.10 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

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

  • 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)
  • 3. 今日は、JJUG の皆さんに Scala を宣伝するために来ました。 Java から Scala へ!!(真顔) !
  • 4. Skinny Framework は Java な現場、SI 業界の案件でも 十分使えるはずと思っています。 ! !
  • 5. 今日は私の話を聴いて 実際に使えそうか見極めてください。 ! !
  • 6. - Scala について -
  • 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) ・メンテされなくなったライブラリは新しいバイナリバー ジョンでビルドされなくなるので選定に注意が必要
  • 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 を採用(理由は後ほど)
  • 15. - Skinny とは -
  • 16. Skinny? ・響きもいいし、自然とこの名前を選びました、 一応 3 つの理由があります ! ・Application should be skinny ・Framework should be skinny ・ 好きに (su-ki-ni)
  • 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 ファイル生成
  • 18. フルスタック? ・フルスタック Web フレームワークはもはや死語? ・定型な機能を提供するフレームワークが珍しくなくなり、 あえてアピールポイントとすることが少なくなった ・ライブラリを組み合わせること前提の開発は柔軟だが、 依存先が増えるリスク、組み合わせの検証コストがある ・チーム開発の場合、ある程度やり方が決められている方 がありがたい場合も多い(もちろんチーム次第) ・よくある要件の実現に必要な時間は極力減らし、差別化 できる要件の開発にこそ時間を使いたい
  • 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 ・入力バリデーション、メール送信はオリジナル ・後ほど、個別の機能を順次紹介します
  • 21. - Skinny をはじめよう -
  • 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 で可)
  • 25. - Skinny MVC -
  • 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”)
  • 47. - Skinny その他の機能 -
  • 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
  • 50. ・バリデーションを含む入力フォームの自動生成 ! ! ! ! ! ! ! ! 最初の scaffold(3)
  • 51. ・flash も動作する状態になっています ! ! ! ! ! ! ! ! 最初の scaffold(4)
  • 52. ・あらかじめ pagination も実装されています ! ! ! ! ! ! ! ! 最初の scaffold(5)
  • 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
  • 58. - まとめと今後 -
  • 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(英語)まで
  • 63. Skinny Framework なかなかよさそうだと思った方? !
  • 64. メディアでの日本語のドキュメントなど 機会があればぜひやりたいです。 公式ドキュメントも協力者がいれば 日本語版をやれるかもしれません。 ! !
  • 65. (時間があれば)質疑応答。 何でも聞いてください。 ! !