1. Javaからの転身!Scala+Play2を知って2ヶ
月でBtoBソーシャルアプリを作るまで
Scala Conference 2013
Junichi Okamura and Takafumi Ikeda
Shanon, Inc.
Social app development
with 2 month study
of Scala+Play!
13年3月2日土曜日
3. About Junichi Okamura (now in SF)
• Twitter: @benzookapi
• Java and PHP developer for 10+ years
• Did not know about Scala until joining current company
• Not familiar with Functional Programming before
• Developing Marketing Web Applications with Scala, Play and Heroku
• Love drinking!
13年3月2日土曜日
4. About Takafumi Ikeda (me!)
• Twitter: @ikeike443
• Play Framework version1 maintainer
• Writing some articles about Play Framework on
“WEB+DB Press vol. 71” and “Jenkins”
• Also Love drinking!
13年3月2日土曜日
6. Our main product (made by perl)
Lead Management Tool
containing several features:
Form and DB, E-mail Marketing,
Web Tracking, Programmable CMS,
Social Marketing, Virtual Event,
Event Attendance Automation, etc.
13年3月2日土曜日
7. } ⇢ T&✏Ä*ÅÇÉÑ⌥
~} ⇥ ÖRÜf&Já*
. / >B
/ à âäff&⇣
Launched at March 2006
5
13年3月2日土曜日
9. Our Technology
• Main product is made by Perl.
• Our main tech stack is consisted by Perl, Apache, FastCGI, PostgreSQL, etc.
• Scala chosen for new product in our company.
13年3月2日土曜日
10. Agenda
• Scalaとの出会い、Javaからなぜ転身したか Why and How using Scala(to me)?
• Javaとの比較、学習、移行コスト Comparison to Java, Learning Cost
• 最低限覚えたことや関数型PGの自己解釈 The things at least I needed to learn
• 業務アプリで使えるのか Can we use Scala in Enterprise Software?
• 運用面で問題は? Are there any problems in operation?
• Herokuとかクラウドとの相性 Relationship with Heroku and other cloud services
• 半年ちょっとつかった感想 Wrapping up
13年3月2日土曜日
12. Scalaとの出会い Why and How using Scala(to me)?
• きっかけ
• 配属になった部署が使おうとしてたから
• 基礎学習期間
• web斜め読みと上司に質問しながらで1週間ぐらい。あとは実務しながら
学習
• Javaを使わなかったわけ
• Javaでもいいけど関数プログラミングへの興味から
Actually not intended, my new company had already chosen it.
But I had been interested in FP, so I learned about the basic of it
by hands-on and also by getting advised from my boss.
13年3月2日土曜日
13. 実務で開発したもの
SHANON SOCIAL SPREADER (SSS)
• キャンペーンのソーシャルネットワーク拡散と貢献ポイント付与、トラッキ
ングなどをするアプリ
• 自社製品のアドオン(JSガジェット)として開発
• フレームワークはPlay2、DBはMongoDBを使用し、テスト運用はHeroku
Actual product I developed is “SHANON SOCIAL SPREADER(SSS)”.
It is kind of social marketing service.
Developed as the add-on javascript gadgets of our main product -
Shanon Marketing Platform(SMP) -.
Powerd by Play Framework2, MongoDB and Heroku.
13年3月2日土曜日
18. 実務で開発したもの(2)
マーケティング用ソーシャルキャンペーンアプリ
• 弊社マーケティングプラットフォームと連携した某社向けFacebook上のキャ
ンペーンアプリ
• 景品抽選をもうけ、顧客企業のイメージをクイズ化し、開催イベントの拡散・
登録増加をねらう
• フレームワーク、DB、ホスティングは同じくPlay2、DBはMongoDB、Heroku
を利用
Another product I developed is Facebook app for lead generation
and collecting some marketing information.
Developed as the Facebook application connected with our SMP.
Also Powerd by Play Framework2, MongoDB and Heroku.
13年3月2日土曜日
22. 使って気持ちよかったところ
• コードが簡潔に書ける
class Person { class Person(
private String name; val name: String,
private int age; val age: Int
)
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
}
Never need boilerplate.
13年3月2日土曜日
23. 使って気持ちよかったところ
• valによる再代入防止でバグ軽減
class Person(val name: String, val age: Int)
val speaker = new Person(name="okamura junichi", age=37)
//I want to be more younger...
speaker.age = 25 //Compile error!
//Speaker changed...
speaker = new Person(name="ikeda takafumi", age=35) //Oops
Never need to mind re-assign problem by val.
13年3月2日土曜日
24. 使って気持ちよかったところ
• varも使えるため、現場の状況に合わせて柔軟に対応できるのも魅力
var speaker = new Person(name="okamura junichi", age=37)
//Speaker changed...
speaker = new Person(name="ikeda takafumi", age=35) //Yep!
Sometimes using “var” meets to real project need.
Flexibility is also beautiful point of Scala.
13年3月2日土曜日
25. 使って気持ちよかったところ
• for、map、caseとかで色々ワンライナーで書ける
for(int i : list) {
list2.add(i + 1);
list map { i => i + 1 }
};
return list2;
One-liner!
13年3月2日土曜日
26. 使って気持ちよかったところ
• 関数型なので処理ごと渡せる(高階関数が簡単にかける)
logging { hoge =>
dosomething(hoge)
doelse
}
Can pass function literal to function.
Higher-order function!
13年3月2日土曜日
27. Javaエンジニアから見たScalaのメリット
• 分岐やループに戻り値がある(式だから)
String attitude;
if(age > 30){ val attitude =
attitude="do not trust..." if(age > 30){
} else { "do not trust..."
• attitude="rock n' roll!" } else {
} "rock n' roll!"
}
//Oops!
attitude="grunge is dead"
• Javaだと分岐やループの結果格納用の変数が必要なのでコードが多くなり、
可読性が下がったり、バグが生まれやすかった。
Condition and loop can return value because they are formula.
Less variable, less bug.
13年3月2日土曜日
28. Javaエンジニアから見たScalaのメリット
• 同様にtry catchにも戻り値があるのは、エラーハンドリングのテストコードが
書きやすく、地味に便利。
( try { doSomething() } catch { case e => None } )
must equalTo(None)
• 期待通りExceptionが発生するかどうかを確認するテストも簡単に書ける。
※ちなみにSpecs2であれば下記のような書き方のほうがベターではある。
doSomething() must throwA[Exception]
Similarly try can return value. It is very helpful to write test code.
You can easily write the test checking if the program can throw
exception expectedly.
13年3月2日土曜日
29. Javaエンジニアから見たScalaのメリット
• Javaのクラス(ライブラリ)が使える
• Javaのコードやライブラリをほぼそのままの形で使える。(JavaMail,
Oauth, Logger系など)
• scala.collection.JavaConversions, scala.collection.mutableを使うことで
配列系のデータもやり取りできる
• まずはJavaの実績あるコードで書いてみて、順次リファクタリングといった
アプローチが可能。
Can use Java library. JavaConversions is very helpful.
You can take the approach such as:
At first, using the proven code by Java.
And then refactoring it gradually to more Scala like code.
13年3月2日土曜日
30. Javaエンジニアから見たScalaのメリット
• WebSocketや非同期I/Oなど新しい技術をサポートしているフレームワークが
多い
• Play, WS, Akkaなど。
There are many modern frameworks which support something cool
technology such as WebSocket, Async I/O and so on.
13年3月2日土曜日
33. ちょっと困ったところ
• break
• continue
• 使いたくなる
I wanna use “break” and “continue”!!
13年3月2日土曜日
34. break
• breakable使えるが、再帰が一般的?
var i = 0
breakable {
def f(i:int) = {
while(true) {
doSomething()
println(i)
if(i<100) f(i+1)
i += 1
}
if (i >= 5) break
f(0)
}
}
※breakableは内部的には例外として実装されているので個人的にはなし
Breakable might be a solution, but personally I don’t want to use.
Because it is implemented as Throwable.
So basically recursive implementation is recommended.
13年3月2日土曜日
35. continue
• 条件式であらかじめフィルタする
Map<int, int> k = new HashMap(); for(i <- 0 to 10;
for (int i = 0; i <= 10; i++) { j <- 4 to 20;
for (int j = 4; j < 20; j++) {
if (i != j) { k = (i, j); if(i==j))
continue; {
} println(k)
k.put(i, j);
System.out.println(k.toString()); }
} //Output are: (4,4)(5,5)...
}
※ループの中はすっきりする
For example, using "if" condition in "for" formula as pre-filter,
instead of using "continue".
Looks clean in loop.
13年3月2日土曜日
37. Javaエンジニアから見た学習、導入コスト
• Scalaレベルを2つにわけるとレベル1のハードルは低い
• レベル1: とにかくScalaで動くものかける
• レベル2: Scalaの強みを理解し、効率的なコードを書ける
• 最終的にレベル2にいかないとScalaを使う意味はないかもしれないが、とり
あえず動くものがかけて、後から徐々にレベルアップできる点がJavaからの
流入者にはいいところ。
Scala learning level may have 2 levels.
Level 1 : can write a working code anyway.
Level 2 : can understand Scala and FP to write an effective code.
To ex-Java guys(me), “can write the working code anyway” is very
important.
13年3月2日土曜日
38. Javaエンジニアから見た学習、導入コスト
• レベル2になるには訓練が必要(高め)
• 特に何が省略されて書かれているか、implicit parameter、implicit
conversion あたりを習得するには少し時間がかかる
To become level 2, you should learn hard. It must be high cost.
Especially, to understand implicit parameter and implicit conversion
might take a little time.
13年3月2日土曜日
39. Javaエンジニアから見た学習、導入コスト
• Scalaが使っているJavaライブラリについてはJavaの知見が生きるので学習コ
ストは下がる
• java.sql.Connection, java.io.Fileなどのお決まりコーディングは生きる、か
つclose処理などは高階関数を使った効率的な実装がしやすい(ex. loan
pattern)
Java knowledge can work such as java.sql.Connection, java.io.File.
Besides due to high-order function, you can implement close()
function effectively.(ex. loan pattern)
13年3月2日土曜日
40. Javaエンジニアから見た学習、導入コスト
• Webの情報やサンプルが少ない分、動くコードをコピペして使えない
• Javaにはそのまま使えるスニペットがたくさん転がっている(コピペの是
非は別として)
Due to less information or less snippets on web, can not copy &
paste working code.
In case of Java, many working snippets exist all over the world.
(Of course, “Get Things Done by Copy & Paste” style itself is not
proper manner...)
13年3月2日土曜日
41. Javaエンジニアから見た学習、導入コスト
• EclipseなどのJavaの強力なIDEの恩恵は減る
• 結論としては、とりあえず書けるレベルにはすぐに到達しそうだが、そこか
ら先のレベルにはエンジニアの個人差が出る。
• Javaのほうが均一な質のエンジニアをそろえやすいが、知見を積極的に共
有、学習すればJavaよりも高パフォーマンスのチームを作れる可能性がある
Less benefits from IDE.
Level 1 “can write the working code anyway” is easy to get, but to
get level 2 might be hard for each engineers.
To build high performed Scala team is very hard because level 2
Scala engineers are hard to employ. But it is worth trying to.
13年3月2日土曜日
43. 既存コードの移行コストは?
• そもそもJavaコードが使えるので、割合そのまま使えることが多い
• 例: JavaMailを使ったScalaのメール送信コード
val msg: Message = new MimeMessage(session)
msg.setFrom(new InternetAddress(mail.from))
• 例: org.apacheのMultiPart Post処理
val entity = new MultipartEntity()
entity.addPart("status",
new StringBody("comment", Charset.forName("UTF-8")))
Basically, can use Java code as it is
13年3月2日土曜日
44. 既存コードの移行コストは?
• インラインコードは機械的にコンバージョンしやすい
• String a → a: String.. など。
• ifやforなどのブロックは最適化が必要
• コンバージョンツールはいくつかある
• IntelliJ IDEAのリファクタ機能の一部
• scalagen: https://github.com/mysema/scalagen
• jatran: https://code.google.com/p/jatran/
Inline code may be easy to convert automatically.
Control block like “if” or “for” need optimization to convert.
Some conversion tools already exist.
13年3月2日土曜日
46. 実務で使うため何を覚えるか
• Scalaで有用な制御構文、オブジェクト定義
• Option、match/case、filter/map、for/foreach/yield、(case )class/object
• フレームワーク基礎知識
• PlayはMVC、Routes、WS、Promiseあたりを一通り。
• sbt基礎知識
• きちんと理解するには、ivy、mavenなど含めた学習が必要だが、とりあえ
ずBuild.scalaの基本的な書き方と定型文のコピーでなんとかなる
What to learn at least are:
Scala’s option, case class, collection, pattern matching.
Framework’s manner, MVC, WS, Promise etc.
How to control SBT. How to tame SBT. How to keep SBT silence.
13年3月2日土曜日
47. 覚えたことで便利だったもの(1)
filter, map, mkString
• この3つだけ覚えておけば、「条件に合う要素だけを抜き出して整形する」
といったよくある処理を宣言的に一行でらくらく書けるようになる
String val ="v1";
String text = "";
for (Map map : list) {
for(String k : map.keySet()){ val value = "v1"
if(k.equals(val)) { println(
text = map.get(k); list.filter(kv => kv._1 == value)
break; .map(kv => kv._2).mkString
} )
};
}
System.out.println(text);
• collectなど他の関数を覚えればもっと短くすることも可能
Collection methods such as filter, map, mkString is useful.
13年3月2日土曜日
48. 覚えたことで便利だったもの(2)
yield, match
String where = "";
for(int i=0; i<params.size; i+) { • SQL生成関数なども一時変数を使わ
if(!params[i].equals(""))
where += "p"+i+"="+params[i];
ずに書けバグの混入が起こりづらい
if(i <params.size-1)
where += " AND ";
}
if(!where.equals(""))
where = "WHERE "+where;
String sql = "select ..." + where;
val sql = "select ..." +
((for(i <- 0 to params.size-1) yield params(i) match {
case "" => ""
case a => "p"+i+"="+a
}) filter (x => x!="") mkString (" AND ") match {
case "" => ""
case a => "WHERE " + a
})
Can write a function like SQL generator without temp variable.
13年3月2日土曜日
49. ビギナーがScalaを使うときのコツ
• 処理を部品化してあとでつなげる
• 部品化は結果に近い方から考える
Tips for beginners:
Consider each process as a component and assemble them later.
Begin to consider from a process near the result in reverse order.
13年3月2日土曜日
50. 例:社員番号リストをゼロサプレスしてCSV出力
• 逆から部品化
• 部品C CSV化 → mkString(“,”)
• 部品B ゼロサプレス → replaceFirst(“0+”, “”)
• 部品A リストを読む → for, foreach, map... ?
Example:
Output CSV file of employee number list with zero suppression.
1. Create components in reverse order.
13年3月2日土曜日
51. 例:社員番号リストをゼロサプレスしてCSV出力
• うまくつながるように部品を見直す
• CでmkString使いたいからコレクションをBで戻すからAはmap
2. reconsider each components to assemble properly.
13年3月2日土曜日
52. 例:社員番号リストをゼロサプレスしてCSV出力
• つなげる
• input->A->B->C->output =
list map(x=>x.replaceFirst("0+","")) mkString(",")
3. Finally assemble all.
13年3月2日土曜日
53. Javaと比較して
• Javaは手続きを連続的に書くことになるので、部品化して考えにくく、ロ
ジックが先に浮かばないと書けない
• Scalaは部分的に書いてつなげるアプローチができる。例えば、ロジックを浮
かばせるために、とりあえず部分部分を書いてみることができる(REPLがあ
ることの優位性!)
• Scalaは初めはとっつきにくいが、なれるとロジックを考えるのがむしろ楽に
なる
Comparison to Java:
Since Java is procedural language, it is hard to think logic as
component. Must think whole of logic to write code.
In case of Scala, it can be.
Scala is hard to get used to, but once you have used to this, it is
much rather easier to think logic than Java.
13年3月2日土曜日
54. 実務で使うのに有効か?
• 今まで見てきた便利な関数型プログラミングと効率化されたOOPのハイブ
リッドは、高い品質や厳密性を求められる業務アプリに向いているはず
• 問題は、コーディング規約、可読性などをどう保つか?
• Javaにくらべて、まだノウハウ的なものが少ない
• コードレベルが個人・会社でバラつく、そもそもエンジニアが少ないから外
注・大規模開発できない
Can Scala be effective to real enterprise project?
Hybrid feature of FP and OOP is effective to enterprise-level quality
and strictness.
Problem may be how to keep readability and how to create
effective code conventions.
Hiring Scala engineers is hard. It also be big problem.
13年3月2日土曜日
56. ライブラリの整備が必要
• Java製ライブラリが使えるせいかScala製のライブラリは少ない印象
• Util系は困らないが通信系の処理で、WSと併用したい場合など、ScalaとJava
のハイブリッドコーディングしないといけない場合は面倒
• Scala製のライブラリを今後増やした方が、Scalaのコードやフレームワーク
の機能をもっと活用できるし、使いやすいライブラリが出来るのではない
か?
The number of Scala origin library is little since Java’s can work.
Sometimes it may be problem.
13年3月2日土曜日
57. Scalaライブラリがなく困った例
• URLの画像を保存->Twitterへコメント付きでアップロードという処理
val url = new java.net.URL("http://hoge.com/aaaa.png")
val urlcon = url.openConnection()
val f= Play.getFile("tmp/aaaa.png")
var fi: java.io.InputStream = urlcon.getInputStream()
var fo: java.io.FileOutputStream = new java.io.FileOutputStream(f)
var end = false
while (end == false) {
fi.read() match {
case n if (n != -1) => fo.write(n)
case _ => end = true
}
}
val entity = new MultipartEntity()
entity.addPart("status", new StringBody("Comment", Charset.forName("UTF-8")))
entity.addPart("media[]", new FileBody(f))
val outputstream = new ByteArrayOutputStream()
entity.writeTo(outputstream)
val header = (entity.getContentType.getName, entity.getContentType.getValue)
WS.url("https://upload.twitter.com/1/statuses/update_with_media.json")
.withHeaders(header)
.sign(OAuthCalculator(key, RequestToken(token, secret)))
.post(outputstream.toByteArray())
13年3月2日土曜日
58. Scalaライブラリがなく困った例
• Twitter APIで画像アップロード
• OAuthシグネチャとHTTP POSTはScala、画像ファイルのmultipart化は
Javaを使用。
• multipart作成ライブラリがScalaになかったのでJavaライブラリを使った
が、Javaコードをコピーしたのでwhileやvarを使いScalaコードとしてはい
けてない
• 使いたいライブラリのパラメータがJava独自クラスのため、芋づる式に
Javaクラスを使うはめに
Example: Image file uploading via Twitter API
OAuth and http post made by Scala, image uploading by multipart
made by Java, because Scala library don’t exist.
13年3月2日土曜日
59. Scalaライブラリがなく困った例
• この案件ではモバイルからのファイルアップロードサポートのために、メール
によるファイル添付から画像アップロード処理を行ったが、メールの解析部
分もJavaコードからの移植だった
• メール解析とか、multipart処理とか、その他業務で必要そうな個々の実装は
結構Java依存になっている
• Scalaによるライブラリ拡充したほうがよさそう
The implementation needed to real project such as parsing mail,
processing multipart, etc. are still depended on Java.
Scala origin library may be needed.
13年3月2日土曜日
60. ビルド、デプロイ
• sbtは高機能だが、依存関係だけを解決したい場合はオーバースペックのよう
に感じることもある
• 設定ファイルがScalaコードのため、柔軟に色んなことができる反面、ライブ
ラリ毎に書き方が異なり使いにくい側面も
• antやmavenだと書き方はばらつきにくいのに
• sbtをwrapした設定の簡易化(制限)版を作ってもいいと思う
SBT have many features but not simple. In case that just want to
resolve dependencies, SBT is too complicated.
Scala-code-config-style is too flexible to maintain.
Ant or Maven or Gradle or something more simple one is better.
13年3月2日土曜日
61. Scalaの後方互換性について
• Javaはバージョンをあげても、それまで動いてたフレームワークはほぼその
まま動作するため、アップグレードしやすく、セキュリティや性能アップの恩
恵を受けれる
• Scalaの場合、言語自体が後方互換性を維持しない上、Play, SBT, Akka, etc.
それぞれのバージョンの組み合わせにも注意を払わないといけない
• エンタープライズで使うにはこの後方互換性の維持が絶対必要!
• ライブラリ作者などを育成し、エコシステムを作るためにも不可欠。
Backward compatibility is serious problem.
To enterprise use, keeping backward compatibility is MUST feature.
To expand Scala-ecosystem, it also be needed.
13年3月2日土曜日
63. クラウドとの相性
• Playが元々ステートレスでスケールアウト指向な設計なので、HerokuやAWS
との相性がよい
• Javaフレームワークのセッションはほとんどサーバーサイドセッションなの
で、単純にサーバーを増やすだけだと正しく動かないことがあるが、Playのそ
れは単なるCookieであるため、自然とステートレスに
Because Play framework is designed as state-less and scale-out
architecture, it work effectively on Heroku and AWS.
Usually, Java framework’s session is server-side session, it is state-
full. But Play is not.
13年3月2日土曜日
64. Herokuとの相性
• git pushで自動デプロイできるのが便利
• ProcFileでPlayにオプションも渡せるのでwebとworkerでサーバーノードを使
い分けることも可能
• ProcFileの例: (webとworkerでconfを変えて、アプリの振る舞いを変える)
web: target/start -Dconfig.file=conf/application_$ENVIRONMENT.conf
$JAVA_OPTS -Dfile.encoding=UTF8
worker: target/start -Dhttp.port=$PORT -Dconfig.file=conf/
application_worker_$ENVIRONMENT.conf $JAVA_OPTS -Dfile.encoding=UTF8
Can deploy via git push.
Can control easily web node and worker node by ProcFile
13年3月2日土曜日
65. Herokuとの相性
• ただし、git pushをする度にデプロイが遅くなるという問題がある
• 当初数十秒だったものが数百回のgit push後には5分以上かかるように
• push毎にリポジトリサイズが増加するためらしく、開発用にbuildpackを
修正する必要あり?
• 今のところ回避策なし(待ち時間に別のことやる、ローカルで済む開発は
ローカルでやるなどしてました)
• 外部APIと連携する開発とか効率落ちる
• Playから提供されているbuildpackも効果がないので今後の優先課題
Every time git push heroku master, deploy is getting slower and
slower. The buildpack introduced by Play can’t work for this.
Anyone knows how to solve, tell me.
13年3月2日土曜日
67. なんだかんだ言っても2ヶ月で出来た
• Javaエンジニアにとっては順次移行できる部分が実務導入しやすい点
• Scalaの機能を全部習得せずとも、ポイントとなる部分をおさえれば大分効率
よいコードが書ける
• コーディングノウハウやコーディング規約がもっと一般化すればエンジニアの
均一化もはかれ、チーム作成がしやすくなる
• 実践的な情報、サンプルが足りないのでふやしましょう(Scalaだけでなくフ
レームワークも)
To Java guys, transition curve to Scala is gentle.
Not need to know everything about Scala and FP. You can write a
working code anyway.
In advance, more snippets, more code conventions, more
information and more real project of Scala are highly needed.
13年3月2日土曜日
68. さらなる普及には
• Scala製のライブラリを増やしScalaのパワーを最大限活かせるようにしたい
• 後方互換を保証し、容易なバージョンアップ
• Herokuの手軽さを活かすために問題点の改善
• 短期習得へのベストプラクティスを示せれば、未知層を取り込んだユーザー拡
大を実現できるはず!
To spread more:
The number of Scala library must increase to unleash the potential
power of Scala.
Backward compatibility is seriously needed. It is MUST.
Fixing the problem when using Heroku and Play together is needed.
If we can introduce the best practice of short cut transition to
Scala, we can expand Scala community more and more.
13年3月2日土曜日
69. 以上
Javaからの転身!Scala+Play2を知って2ヶ
月でBtoBソーシャルアプリを作るまで
でした
This presentation was:
Social app development with 2 month study
of Scala+Play!
13年3月2日土曜日