ニコニコAndroid(サーバ編) - Scalaを業務で使って
Upcoming SlideShare
Loading in...5
×
 

ニコニコAndroid(サーバ編) - Scalaを業務で使って

on

  • 14,599 views

2013 JJUG(http://www.java-users.jp/?page_id=330) #jjug_ccc

2013 JJUG(http://www.java-users.jp/?page_id=330) #jjug_ccc
※一部発表時と異なる点があります

Statistics

Views

Total Views
14,599
Views on SlideShare
14,321
Embed Views
278

Actions

Likes
53
Downloads
36
Comments
0

8 Embeds 278

https://twitter.com 230
http://taityo-diary.hatenablog.jp 30
http://s.deeeki.com 11
https://www.chatwork.com 2
http://192.168.33.10 2
http://pinterest.com 1
http://b.hatena.ne.jp 1
https://kcw.kddi.ne.jp 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

ニコニコAndroid(サーバ編) - Scalaを業務で使って ニコニコAndroid(サーバ編) - Scalaを業務で使って Presentation Transcript

  • ニコニコAndroid- サーバ編 -間島 大智
  • 目次•ニコニコAndroidサーバって何?•Scalaいいところ・わるいところ•サーバチームの仕事の流れ
  • 間島 大智•株式会社ドワンゴ•ニコニコAndroidサーバチーム•2012年新卒入社
  • 間島 大智•株式会社ドワンゴ•ニコニコAndroidサーバチーム•2012年新卒入社
  • 間島 大智•株式会社ドワンゴ•ニコニコAndroidサーバチーム•2012年新卒入社•化学の知識を活用できるWebサービスのプロジェクトまだですかね
  • ニコニコAndroidサーバって?社内向けAPI・DBニコニコAndroidサーバAndroidアプリau STBアプリ様々なアプリでニコニコを使うために必要なAPIを提供
  • プロジェクトの歴史•2012/02 プロジェクト発足•2012/08 au STBアプリリリース•2012/11 Androidアプリリリース•74 API•330万リクエスト/日
  • サーバ側メンバー• mashijp (github)• @kozo1215• @mtgto• @mitikage• @kimwoonsung• インフラ2人
  • 環境•言語: Scala•フレームワーク: Play Framework 2.0•IDE: IntelliJ IDEA 11, 12•CI: Jenkins社内初
  • ニコニコAndroidサーバって?
  • ニコニコAndroidサーバの役目社内向けAPI・DBニコニコAndroidサーバAndroidアプリau STBアプリこの位置に求められることって…?
  • ニコニコAndroidサーバに求められること社内向けAPI・DBニコニコAndroidサーバAndroidアプリau STBアプリアプリにとって使いやすいAPIを提供すること
  • 使いやすいAPIとは?•用語が統一されている•用語が直感的に理解できる•内部的な細かい仕様を知らなくていい•ドキュメント化されている
  • •用語が統一されている•用語が直感的に理解できる•内部的な細かい仕様を知らなくていい逆にこの3つを満たしていないAPIって?
  • 社内APIを変えればいい?長い歴史があるもの(社内API)にはどうしてもわかりにくい用語・仕様がまじってしまう社内APIを修正すればいい…?
  • そう簡単には変えられない•社内APIは多数の社内サービスが既に使っている•仕様を変更するのは容易ではない
  • サーバで内部仕様を吸収mylist.list deflist.listmylist.remove deflist....GET /xxx/mylists/:id社内向けAPI・DBニコニコAndroidサーバAndroidアプリau STBアプリわかりやすい!モデルもScalaで再定義
  • ドメイン層Androidアプリau STBアプリインフラストラクチャ層社内向けAPI・DBAPI層ドメイン駆動設計による浄化社内APIを叩くことだけに専念ビジネスロジックだけに専念リクエストの処理だけに専念明確にレイヤー分離された設計をしています
  • 社内向けAPIドキュメント•Confluence(Wikiみたいなもの)で管理•全てのAPIについて細かく記述している
  • ドキュメントの例
  • ドキュメントの例
  • ドキュメントの例
  • ドキュメントの例共通で使うレスポンスの形は別ページにしている(多重管理を避けるため)
  • APIドキュメントの記述•社内向けAPIドキュメントだからといって決して手を抜いていない•多重管理を避け、ドキュメントが古くなってしまうことを避けている
  • 使いやすいAPIが実現できた•用語が統一され、直感的に理解できる•内部的な細かい仕様を知らなくていい•ドキュメント化されている→Scalaでモデルを再定義しアプリに提供→社内向けだからといって甘えていない 管理しやすく見やすいドキュメント作成
  • Scalaの良い所・悪い所
  • 環境•言語: Scala•フレームワーク: Play Framework 2.0•IDE: IntelliJ IDEA 11, 12•CI: Jenkins
  • •昨年6月、新卒研修が終わりニコニコAndroidチームに配属された•入社前•Javaは趣味で触ってた•が、 Scala は名前すら知らないScala…?!
  • Java利用者にとってのScala実体験をふまえて
  • Scalaって?•静的型付け言語•関数型言語とオブジェクト指向言語のハイブリッド•JVM上で動く•Javaのコードも簡単に混ぜられる
  • Scalaって?•静的型付け言語•関数型言語とオブジェクト指向言語のハイブリッド•JVM上で動く•Javaのコードも簡単に混ぜられるって言われても何が良いのかわからん!
  • 便利やでScala•型推論•コレクション関数•対話環境•Option型
  • 型推論String str = fugahoge ;String piyo = str + piyo ;Java
  • 型推論String str = fugahoge ;String piyo = str + piyo ;Java
  • 型推論String str = fugahoge ;String piyo = str + piyo ;Java↑書かなくても右辺見ればわかる
  • 型推論String str = fugahoge ;String piyo = str + piyo ;JavaScala↑書かなくても右辺見ればわかる
  • 型推論String str = fugahoge ;String piyo = str + piyo ;JavaScala↑書かなくても右辺見ればわかるval str = fugahogeval piyo = str + piyo
  • 型推論String str = fugahoge ;String piyo = str + piyo ;JavaScala↑書かなくても右辺見ればわかるval str = fugahogeval piyo = str + piyo↑コンパイラが勝手にStringと推測
  • 型推論
  • Scala型推論
  • Scala型推論def replaceAbc(str: String) = {str.replaceAll( abc , def )}val fuga = replaceAbc( abcdef )
  • Scala型推論def replaceAbc(str: String) = {str.replaceAll( abc , def )}val fuga = replaceAbc( abcdef )↑メソッドの返り値はStringと推測される
  • Scala型推論def replaceAbc(str: String) = {str.replaceAll( abc , def )}val fuga = replaceAbc( abcdef )↑メソッドの返り値はStringと推測される↑よって、fugaもString
  • Scala型推論def replaceAbc(str: String) = {str.replaceAll( abc , def )}val fuga = replaceAbc( abcdef )↑メソッドの返り値はStringと推測される↑よって、fugaもString冗長な記述をしなくていい
  • コレクション関数JavaString[] strs = { a , fuga , bb , hogee };List<String> result = new ArrayList<String>();for(String str : strs) {if (str.length >= 3) { result.add(str); }}return result;
  • コレクション関数Scalaval strs = List( a , fuga , bb , hogee );return strs.filter(_.length >= 3)強力なコレクション関数+型推論によりコード記述量を大幅に減らせる
  • ちなみに•ニコニコAndroidサーバのコードにはfor文は7つしかない
  • Scalaのfor使うときval list1 = List( a , b , c )val list2 = List(1, 2, 3)for(a <- list1; b <- list2) {println(a+b)}
  • Scalaのfor使うときval list1 = List( a , b , c )val list2 = List(1, 2, 3)for(a <- list1; b <- list2) {println(a+b)}出力結果: a1 a2 a3 b1 b2 b3 c1 c2 c3
  • Scalaのfor使うときval list1 = List( a , b , c )val list2 = List(1, 2, 3)for(a <- list1; b <- list2) {println(a+b)}出力結果: a1 a2 a3 b1 b2 b3 c1 c2 c3複数のコレクションの組み合わせを網羅するのに非常に便利
  • 強力なコレクション関数+for•コード記述量が大幅に減った•単純なコレクションの処理をする際にfor文使うことほぼなし•たまに「forどうやって書くんだっけ」という声がでるほど…
  • 対話環境
  • 強力なimport文•ブロックの中にかける•別名をかけるScala
  • importをブロックの中にかけるimport java.util.Date;public void methodA(){Date date = new Date(). .......}public void methodB(){java.sql.Date date = new java.sql.Date(..). .......}Java名前が衝突するのでimportできず、フルネームで書くしかない
  • importをブロックの中にかけるdef methodA() = {import java.util.Dateval date = new Date(). .......}def methodB() = {import java.sql.Dateval date = new Date(..). .......}Scala
  • 別名をつけられるimport java.util.Dateimport java.sql.{Date => SqlDate}def methodA() = {val date = new Date(). .......}def methodB() = {val date = new SqlDate(..). .......}Scala
  • 強力なimport文•ブロックの中にかける&別名をつけることができる•クラス名をつける際に「かぶりそうだな…」と怯えることがなくなった•短いクラス名をどんどんつけちゃう•例) Client (Redis接続用クラス)
  • Option型Java・このメソッドってnull返すことあるっけ? えーとドキュメント...・あ、そうだ nullチェックしないと... if (result != null) { ....
  • Option型Java・このメソッドってnull返すことあるっけ? えーとドキュメント...・あ、そうだ nullチェックしないと... if (result != null) { ....NullPointerException
  • Javaでぬるぽを起こす例JavaMap<String, String> map = getMap();String result = map.get(fieldName);if (result.length() >= 3) {return 長さは +result.length();} else {return 短い!! ;}Mapからとってきたものが3文字以上かどうかチェックするメソッド
  • Javaでぬるぽを起こす例JavaMap<String, String> map = getMap();String result = map.get(fieldName);if (result.length() >= 3) {return 長さは +result.length();} else {return 短い!! ;}Mapからとってきたものが3文字以上かどうかチェックするメソッド
  • Javaでぬるぽを起こす例JavaMap<String, String> map = getMap();String result = map.get(fieldName);if (result.length() >= 3) {return 長さは +result.length();} else {return 短い!! ;}NullPointerException!!!   ( ・∀・)   | | ガッ  と    )    | |    Y /ノ    人     / )    <  >__Λ∩   _/し //. V`Д´)/  (_フ彡        /そんなキーねえよMapからとってきたものが3文字以上かどうかチェックするメソッド
  • nullチェック追加Map<String, String> map = getMap();String result = map.get(fieldName);if (result != null && result.length() >= 3) {return 長さは +result.length();} else {return 短い!! ;}Java
  • nullチェック追加Map<String, String> map = getMap();String result = map.get(fieldName);if (result != null && result.length() >= 3) {return 長さは +result.length();} else {return 短い!! ;}Javaどうしてもnullチェック忘れてしまう…!
  • Option型って?Option[T]Some[T] None値がある 値がない値がある・ないを型で表現しているScala
  • Option型の挙動Scalaval map = Map("key1" -> "value1", "key2" -> "value2")// Map#getの返り値はOption型(ここではOption[String])println(map.get( key1 ))//→ Some(value1)println(map.get( fuga ))//→ Nonemap.get( key1 ).getOrElse( ないとき )//→ value1map.get( fuga ).getOrElse( ないとき )//→ ないときSomeのときは中身を取り出し、Noneのときは引数を返す
  • 型で値がないことに気づけるval map = getMap()val result = map.get(fieldName)↑resultの型は Option[String]この時点で「値がないこともありうる」ということに気づけるScala
  • val map = getMap()val result = map.get(fieldName)result.filter(_.length > 3).map(e => 長さは +e.length).getOrElse( 短い )さっきの例をScalaで実装Scala
  • ぬるぽがない安心感•Scalaの標準ライブラリは原則nullを返さない(Scalaはnullを使わない文化)•つまりnullチェックを書く必要がない
  • 社内向けAPIドキュメント
  • 社内向けAPIドキュメントnullがありうるものをドキュメントに残すのに苦労しなかった
  • Scalaの悪いところ...•コンパイル遅すぎ!•社内にScalaについて聞ける人が少ない
  • コンパイル•遅い!!とにかく遅い!!•メモリ食い過ぎー!•ビルド時のJavaの設定-Xms512m -Xmx1024m -XX:MaxPermSize=512mScala
  • コンパイル•遅い!!とにかく遅い!!•メモリ食い過ぎー!•ビルド時のJavaの設定-Xms512m -Xmx1024m -XX:MaxPermSize=512mScalaJenkinsで並行ビルドするとスワップアウト...→ Jenkinsサーバのメモリ増設(4GB → 8GB)
  • 社内に聞ける人が少ない•弊社内でScalaのプロジェクトはニコニコAndroidサーバが初めて•社内ノウハウが少ない…•Scala書ける人もあんまりいない…
  • 学習コストはそんなにかからない開発メンバー5人中4人がScalaをはじめて1年たっていない
  • 学習コストはそんなにかからない開発メンバー5人中4人がScalaをはじめて1年たっていないでも1ヶ月勉強したら業務で書けるようになった
  • どうやって勉強?•おすすめ本「JavaプログラマのためのScalaプログラミング」•疑問は社内IRCでブツブツ言う•誰か答えてくれる•#scalaというチャンネルもできた
  • 少しずつ広まっている...!最近は社内でもScalaを使う流れができつつあり、今後は改善されそう!ドワンゴでは4プロジェクトがScala使ってます
  • チームの実際の仕事の流れ
  • 仕事のサイクル計画振り返り 実装レビューリリースマージ1周=2週間のアジャイル開発
  • 開発メンバー全員で2週間にやることを計画誰がどの仕事をするか割り振る全員で計画する
  • 計画の前準備会議をする前に各自でやらないといけないことを洗い出し、チケットとして作成チケット管理にはAtlassian製品のJIRAを使っています
  • 全員で見積もるチケットを作った人がチケットの内容を説明工数見積もり(予想)を各自で出す見積もりがあわなかったら最大3回やる全員でやることを共有できているので突然誰かが倒れても大丈夫なチームに
  • 実装する• IntelliJ IDEA 12 Ultimate($200)使ってます• キャンペーンのときに全員買った• 買うまではCommunity Edition(無料)• 会社で買ってくれるという話も出てる• ScalaのIDEはIntelliJ IDEA一択• EclipseでのScala開発はめっちゃ重い…
  • テストに力を入れています1000以上のテストケースによりコードカバレッジ80%以上を達成
  • FishEyeでコードレビュー全員が仕事を理解しているので誰でもレビューできるみんなで気軽にレビューコメントをつける
  • GitHub:eよりFishEyeのほうが便利•誰がレビューOK出しているのか、どれぐらい見ているのかがすぐ分かる!全員のレビューOKが出ればマージする
  • Jenkins•ビルド•テストの実行•developブランチにマージするとJenkinsが動き出す•テストが落ちるとチームメンバーに罵られる
  • 振り返る(KPT)毎週水曜日にKPTKeep(続けたいこと), Problem(困ったこと),Try(次やりたいこと) をみんなで自由に書く
  • KPTで改善された例Jenkins用サーバで並行ビルドできないもっとスペックの高いJenkins用サーバを調達し、並行ビルド可能にProblemTry
  • 思ったことを気軽に書けるので「ちょっとした問題」を改善していく流れを作ることができた
  • 強いチーム作りに成功「全員で」計画し「全員で」振り返ることで常に意識を共有全員が主体的に動く強いチームを作っています
  • ドワンゴで働きませんか• Scalaに興味のある人もない人も• 「ドワンゴ 採用」で検索!• http://info.dwango.co.jp/recruit/• 7月から新オフィス(歌舞伎座)お待ちしています!
  • まとめ• 美しいAPIをアプリチームに提供できた• Scalaで再モデリング・ドキュメント整備• Scalaを業務で楽しく使ってます!• 強力なScalaの機能で効率の良い開発が可能に• 強いチームでやってます• 全員が仕様を理解できている• 誰が風邪引いても困らない