これからScalaを始める人に役立つヒント満載!『Scala大名の平成維新☆殿中でScala!』
- ガジェット通信を≫
- @getnewsfeedさんをフォロー
LT1:「十人十色のScalaの始め方」
トップバッターはナイルの佐藤和輝さん。現在はApplivのマイクロサービス化&検索機能改善に携わっている。Applivは「アプリインストールを、もっと身近なものにする」をミッションに、2012年8月リリースされたユーザー参加型のスマートフォンアプリ発見サービス。国内版のほか、英語版も含め世界10カ国で展開している。
ナイルでは2015年3月にScalaの導入が決まり、5月には一部でScalaによる開発がスタート。8月にはScalaをテーマに開発合宿を実施し、10月からは本格的にプロジェクトにおいてScalaを使っているのだそう。
佐藤さんのLTでは、Scalaを始めたきっかけやScalaを始めるためにまずしたこと、ナイルのエンジニアがどんなことにつまずいたかなどが紹介された。
【CASE1】入社9年目のナチュラルボーンエンジニア
Scalaをはじめたきっかけ:1年前にScalaを使うプロジェクトがスタートしたこと
Scalaを始めるためにまずしたこと:使う予定のライブラリのチュートリアルの実施。そしてfor文が既存のものと違い、先入観でつまずいた
今からやるなら・やり直すなら:数学的基礎概念をたたき込んでからやりたい。今追いかけている。
【CASE2】プログラミングを始めたその場ののりと勢いで生きるS氏
Scalaをはじめたきっかけ:使う予定のライブラリのチュートリアル
Scalaでつまずいたこと:traitとか意味のわからない単語や記号がいっぱいで、しかもこれらの記号は検索できない
Scalaを始めるためにしたこと:まとまっている情報をまず見つけ、それを参考にhow to useをやっていたりしている
【CASE3】新卒入社後、すぐScalaプロジェクトに参加したM氏
Scalaを始めるためにしたこと:「Scala入門」で検索し、わかりやすそうな記事を探した
Scalaでつまずいたこと:関数型プログラミングの意味やノリやAkkaのActorシステムの使い方、for、forldLeft、reduceLeft、map、flatMapの使い方などにつまずいた
今からやるなら・やり直すなら:まずはmap、flatMapの意味を理解すること。そうすればScalaコードが書きやすくなるので、そこを人に聞きまくる。
いずれにしてもScalaの始め方は十人十色で、これがベストというものはない。ただ、まったく異次元の言語というわけではないので、自分と似たタイプの人を探して一緒に頑張れば上達が早いはず、とアドバイスをした。
☆☆佐藤さんの講演資料「十人十色のScalaの始め方」
LT2:「株式会社ドワンゴにおけるScala教育の現状」
2番目に登壇したのはドワンゴのScalaエバンジェリストの水島宏太さん。Scalaエバンジェリスト。Japan Scala Association代表理事を務めている。
ドワンゴでのScalaの立ち位置はメインの開発言語の1つで、ニコニコ生放送2やアカウントシステムなど、いろいろなところで使われている。
2015年度より新入社員研修にScala研修を導入。現在、ドワンゴではその研修で使用しているテキストの前半部分(Scala言語の基本が記載されている)を一般公開している。
ドワンゴオリジナルの、新卒エンジニア向けの研修資料
IntelliJ IDEAのバージョンアップ、Scalaのバージョンアップへの対応、非推奨機能の置き換えなどをしたりするなど、継続的なテキストのメンテナンスももちろんしている。
今は2016年度新入社員研修に向けて修正として、テストの章を加筆したり、練習問題の解答例の整備を行ったりしている。これからScalaを始めたいという人にとっては、ぜひ、参考にしたいテキストである。
☆☆水島さんの講演資料「株式会社ドワンゴにおけるScala教育の現状」
LT3:「いろんなところでScala Compile」
三番目に登壇したのはリクルートマーケティングパートナーズの松川翼さん。松川さんは「スタディサプリ English」「スタディサプリ 英単語」のサーバサイド、インフラ周りを担当している。
松川さんは「Scalaのデメリットはコンパイルが遅いこと」だと言う。CPUでとのくらい違うのか、AWC、GCP(プリエンティブルVMを使用。PVMはGoogle Cloud Platformで提供されている、AWSでいうスポットインスタンスのようなもので、コストが安い)、Macでインスタンスを作ってコンパイルしてみたという。
条件は以下の通り。
プロジェクト
▶ https://github.com/apache/spark
▶ Apacheのプロジェクト。ファイル数2946 コード行数は約95万行
▶ これをclean compileし、2回目を計測
環境
▶ GCP:CentOS7、AWS:Amazon Linux
▶ Scala2.11.7
▶ SBT13.9
▶ JDK8
評価してみたところ、AWSのc4が最も速いことがわかった。その理由について、c4は計算に特化なので個々のCPU処理能力が高いからではと考察。scala compileは負荷が特定のコアによってしまうことが多く、GCPのCPU数の優位を活かせていなのではないかと指摘。
そこで現状、Scala CompileにはAWS c4インスタンスがお勧めだという。ただ、CPU数を多く確保することにメリットのあるケースではPVMは安くて良い選択肢になるのではとアドバイス。コンソールもどんどん使いやすくなっているそうだ。Dottyを心待ちにしているとのこと。
☆☆松川さんの講演資料「いろんなところでScala Compile」
LT4:「Akkaを使ったスケーラブルなLINE Bot」
4番目に登壇したのは、TISの杉本貴史さん。Scala歴は約1年。
4月7日にトライアルAPIが公開されたLINE BOTにAkkaを組み合わせスケーラブルな簡易電卓を作ってみたとのこと。
この電卓機能の特徴は、+2と書けば前の答えを使って計算してくれるところである。これを実現するために活用したのが、Akka ActorとAkka Persistenceである。Akka Actorは状態をオンメモリで保持し、並列処理を得意とするため高速に処理できる。
次にLINE BOTはスケールすることも求められる。しかし、NodeとActorを対応させて管理するのは非常に大変。そこで活用したのがAkka Cluster Shardingだ。
これを活用することでActorを複数のNodeで分散管理し、Shardというグループ単位で管理することになる。また自動ルーティングによりどのNodeから送っても対応するActorへ届くようになる。
Nodeの負荷の平滑化のため、自動的にShardに移動するが、この際に状態が消失してしまう。それを防ぐために活用するのが、Akka Persistenceである。
これにより、Actorの持つ状態を永続化できるようになる。Akka Cluster Sharding+Akka Persistenceを組み合わせすることで、スケールラブルなBOTの作成が可能になる。
☆☆杉本さんの講演資料「Akkaを使ったスケーラブルなLINE BOT」
LT5:「制約をロジックではなく型で表現する」
続いては、Tech to Valueの中村学さんが登壇。「制約をロジックではなく型で表現する」。
中村さんはテストそのものを書くのはそれなりに好きだが、テストデータを作るのがあまり好きではないという。
それはテストデータのメンテナンスが大変だからだ。例えばテストごとに独立したデータ定義をすると、仕様変更や機能追加でフィールドが増えた際にすべてのテストごとのデータを修正する必要がでてきてしまう。
そこでお勧めなのが「Property Based Test」である。Property Based Testとは、テストデータをランダムに半自動生成して、そのすべての値について、満たすべき性質をきちんと満たしているかテストするというもの。
半自動生成とは、型毎にインスタンスをどう生成するのかを表す Generator/Arbitrary を定義すれば、後はテストフレームワークがその定義に従いランダムに値を生成するというものだ。
つまりデータの生成方法だけ定義すればよいので、仕様変更や回収でフィールドが増減してもその方法だけ変更すれば対応できるようになるというわけだ。
だがProperty Based Testをかいていくと制約をロジックで表しているコードGenerator/Arbitraryが定義しづらい。そのような場合は制約自体を思い切って型として表現すると、Generator/Arbitraryが定義しやすくなる。
制約を型で表現することによって、コンパイル時に間違いを検出できたり、テスタビリティが高まったりなど、いろいろはかどるようになる。
☆☆中村さんの講演資料「制約をロジックではなく型で表現する(LT版)」
LT6:「仕様をコードに落とし込む際 気をつけたいこと」
前半最後に登壇したのは、Fringe81の豊島正規さん。「仕様をコードに落とし込む際 気をつけたいこと」。豊島さんはアドテクの会社Fringe81で働くScalaエンジニア。Scala歴は2.5年。
Scalaを新しく始めた人も多い。例えば「DDD(ドメイン駆動設計)」。これをするにはドメインの理解やモデルの抽出、コードで表現することが求められる。しかしこれらのときにミスすることも多い。
【例】
val result: Boolean = executer.run(args)
人によっては将来の拡張性を考えて、次の様に設計するかもしれない。
val result: Result = executer.run(args)
case class Result(isValid: Boolean)
仕様追加で、“isValidがfalseの時はargsのうち原因となったArgも返す”と言われたとする。つまり、
isValidが
trueならArgはなし
falseならArgはある
これを次の様なオプション型で書いてしまうと
case class Result(isValid: Boolean, arg: Option[Arg])
Resultは以下の4通りの組み合わせが登場してしまう。
true x Some
true x None
false x Some
false x None
しかし一番上と一番下は仕様と異なる。このような仕様と異なる組み合わせが作れないようにするために、validationを入れて、組み合わせ違反は実行時例外を出してインスタンス化を防ぐなど頑張るのは間違いである。
この原因は仕様と型がずれていること。つまり、
isValidが
falseならArgはある
trueならArgはなし
sealed trait Result
case class Valid() extends Result
case class Invalid(arg: Arg) extends Result
と書くのが得策となる。
コードを書くときに、自分が作った型が仕様を表現できているのか、実行時検査による例外送出ではなく、コンパイルエラーで防げないか、ユニットテストを書かない方向にもっていけないかを考えながら、プログラミングするとよいのではとアドバイスをした。
☆☆豊島さんの講演資料「仕様をコードに落としこむ際気をつけたいこと」
LT7:「ScalaでWebAPIラッパーを作る」
10分間の休憩の後、後半のLTが開始。Marverickのぽんこつさんが登壇。今回のLTではScala-SlackというSlackのAPIのラップするライブラリをフォークした経験を話してくれた。
必要なHttpClientはラップするのは、テストがしやすい、HTTPライブラリの変更が容易になるからである。続いてエラーの返り方を統一する。Scala-Slackは例外で処理している。次にResponseを型に落とすこと。これは重要だが、非常に面倒くさい。
Scala-Slackは例外で処理している。型の中で情報量の違う同じモノもある。例えばSlackのChannelは返す3つのChannel(channels.info、channels.list、channels.rename)のデータがすべて異なる。
そういう場合は、共通の基底となるtraitを作るのがお勧めだ。メソッドの引数は、idを渡せるようにする、Responseそのものを選べると良いという(Scala-Slackでは未実装)。
API呼び出しはオブジェクトにせず、クラスにすること。引数にHttpClientを取ることで、テストがしやすくなるからだ。そして単体テストをする。
HttpClientを単体テスト用に置き換える。その方法はMockか継承にする。これで単体テストをすることで、クエリとJSONのパースがテスト可能になる。そのコード例が以下だ。
class ChannelsSpec extends FlatSpec with MockitoSugar with Matchers with BeforeAndAfterEach {
private var mockHttpClient: HttpClient = _
private var channels: Channels = _
override def befereEash() {
// set mock
when(mockHttpClient.get(“channels.info”, params)
.thenReturn(json)
channels = new Channels(mockHttpClient, testApiKey)
}
“Channels.info()” should “get channel info” in {
val response = channels.info(“C024BE91L”)
… // check value
}
}
あとはMavenCentralに登録する。これがある意味一番難しい。
このように手を動かすと、品質の良いScalaライブラリが増え、みんなが幸せになる。最後に「みんなガンガンライブラリを作ろう」と呼びかけた。
☆☆ぽんこつさんの講演資料「ScalaでWebAPIラッパーを作る」
LT8:「3ヶ月間Scalaと付き合って感じた事」……という発表を想定していたのですが
続いて登壇したのは、Opt Technologiesのcedretaberさん。Scala歴はもうすぐ4カ月になるとのこと。同社では技術ブログを運営している。記事のテーマはScala中心だが、JavaScriptの記事もある。
cedretaberさんが「PlayFramework 2を使うならAkkaも使っちゃおうぜ」というような記事を書いたら、指摘を受けたという。その辺りの理由の一つとなった、
「なぜ可変な状態を持たないモノにAkkaのActorを使うのはアンチパターンなのか」について解説。
結論はコストに見合うリターンが得がたいからである。ここでいうコストとは設計の複雑さ、安全性の低下、パフォーマンスのこと。アンチパターンになる第一は、Actorの死活問題である。Actorは死ぬこともある(少なくともそれを前提に設計するべき)。死んだActorをどうすればよいのか。
しかし「とりあえずこうしておけばよい」という方法論がない。
例えばSupervisorを使えば、ワーカ(子アクター)の監視や再起動ができたり、例外に対応して処理を記述できたり、再起動に関しては戦略を決めることができたりするが、どの戦略を採ればいいのかは、作るべきシステムによって変わるので、作るべきシステムに対する深い理解が必要になる。
もう一つはメールボックスの容量問題である。Actorのメールボックスが一杯になることもある。Akkaでは組み込みのメールボックス実装があるが、作るべきシステムに対する深い理解が必要になるという。
第三は安全性の低下について。現状のAkkaのActorではどんな型の変数でもメッセージとして送ることができる。送る側の方と受け取る側の型がミスマッチだと、受け取られる宛の内メッセージを送り続けることになってしまう。
ただし、この辺は将来的にAkkaに型が導入されるので、改善されるのではという。
第四はパフォーマンス問題。Akka Actorを使うと普通にFutureを使うより圧倒的に遅いという。
このような問題があるにも関わらず、なぜAkkaを使うのか。第一の理由は変化しうる状態を並行に扱う際、これ以上ないほどキレイに設計できることである。
次にデッドロックの恐怖からも解放される。そのほか処理同士が疎結合にメンテナンス性が高まること、さらに計算機をまたいで処理を書けることなどが挙げられる。
活用する際に特に注意すべきことは、Akkaについて深い理解を持つこと。こう最後にアドバイスした。
☆☆cedretaberさんの講演資料「3ヶ月間Scalaと付き 合って感じた事 ……という発表を想定していたのですが」
LT9:「Introduction of ScalaTest ~ScalaTest移行への手引き~」
次に登壇したのは、セプテーニ・オリジナルの木村彰宏さん。セプテーニ・オリジナルは、ソーシャルメディア等の広告運用管理(アドテク)ツール「PYXIS(ピクシス)」や、オリジナル新作マンガの配信サービス「GANMA!(ガンマ!)」を開発している。
同社ではScalaのテストフレームワークにはSpecs2、モックフレームワークにはMockito、もしくは一部プロジェクトでScalaMockを使っているという。Specs2を選定したのはPlayFrameworkで組み込む際に、activator newしたらbuild.sbtのデフォルトだったからだ。
木村さん個人の選定では、テストフレームワークにScalaTest、モックフレームワークはMockitoを使っている。今年の2月よりPlayFrameWorkの標準になったことが、ScalaTestを試してみる動機になったのだそう。
またScalaTestは導入障壁が低いのもその特徴だ。様々なテストスタイルでテスト記述できるAPIが提供されていている。DSLを使わなくてもassertだけでほとんどのテストが書けてしまう。
ただし、様々な記述方法が備わっているので、チーム内で統一したい場合は、基礎とするtraitをミックスインしてBaseとなるクラスを定義しておくこと。これはScalaTestの公式でも推奨されている。
また2.2.0から導入されたDiagrammedAssertionsをミックスインするとpower assertが利用できるようになる。power-assertについては「5分ぐらいでわかるpower assert」について詳しく記されている。
DiagrammedAssertionsについては実際にいろいろ試してみること。参考になる記事「ScalaTest 2.2.0のDiagrammedAssertionsを試してみる」も紹介。最後にSpecs2からでもすんなり入門できるということを伝えてた。
☆☆木村さんの講演資料「Introduction of ScalaTest」
LT10:「将軍スポンサー殴り込み枠LT」
登壇したのは、チャットワークのKouta Ozakiさん。OzakiさんはJSが大好きなPHPエンジニア。まずはScala.jsについて。Scala.jsはAltJSの一種。基本的にブラウザで動くJS向けで、Node.jsでは一手間掛ける必要がある。
TypeScript、Flowtypeに比べて型の表現力が高いという特徴を持つ。続いてHubotについて。HubotはGitHub社が作っているNode.js性のBotフレームワーク。チャットワークも非公式で対応している。
今回のLTではScala.jsでNodeJSのHubotのコードをScala.jsで書いてみるとどうなるか、実際にコードを見せながら解説が行われた。実際のコードは次の様になる(PDF P11)。
以下の2行がNode.jsのコードをScala.jsで書くときの肝になってくる。
“node-java-maven”:”0.0.12″,
“scalajs-standalone-bin”:”^0.4.3″
“node-java-maven”はmavenレポジトリから依存するJavaファイルを持ってきてくれる。
scalajs-standalone-binはScala.jsのスタンドアロン版が配付されているので、sbtを使わなくて済む実行形が配付されているので、それをnodeプロジェクトに取り込むライブラリとなる。
この2つを使うとsbtの依存解決と、ビルド周りの代替をすることができる。
Package.jsonが用意できれば、$ npm installでNodeJSのJavaの依存系を解決して、n$ npm run buildでScalaのコードをJSに落とし込むことができる。この動作が確認できればherukuの方にプッシュする。
Scala.js+Hubotの悪魔合体は楽しいが、ただし、Scala.jsで書く意味は特にない。あくまでも趣味の世界という話だった。
LT11:「社内のScala戦士を増やせ!」
後半4番目に登壇したのはCyberZの鈴木雄登さん。現在、CyberZではScalaエンジニアを増やすことにいろんなトライをしている。
Scalaエンジニアを増やすための第一の方法は、まずは興味を持ってもらうこと。そのために最初は無理をしてでも、Scalaにつなげていくことが大事だと言う。例えばJavaと比較してあえて大げさな例でScalaの優位性を紹介したりする。
第二に聞ける体制を整えること。Slackやチャットワークやメッセンジャーなどで、「Scala部屋」を作っていつでも聞ける体制を用意する。
第三はScalaビギナーを新規プロジェクトにいきなりアサインしないこと。レビューや参考になるソースがある状態で戦ってもらうようにする。書き方がわからない状態でScalaを書くと、単純なJavaを書くよりも辛くなってしまうからだ。もちろん、わかりづらい・難解なコードを担当させないことも重要だ。
第四はScalaの問題に挑戦してもらうこと。同社では以前、自作していたが、今は「Scalaパズル」を利用しているという。この問題を解いてもらうことで、Scalaの底力を上げている。
第五はScalaの楽しさを伝えること。関数型の魅力を伝えることで、新しいパラダイムを体験してもらうのである。
CyberZではこのような取り組みをすることで、社内にScalaエンジニアを着実に増やしているのだ。
☆☆鈴木さんの講演資料「Scala戦士を増やせ」
LT12:「頑張らないScala」
5番目に登壇したのは、VOYAGE GROUPのkatzchangさん。katzchangさんはVOYEGE GROUPのZucksで広告配信業を行っている。
広告配信サーバをScalaで動かしているのは2013年から。katzchangさんはScalaとはベタージャバだと位置付ける(2016年俺調べ)。
続いて、Scalazとは便利ライブラリだと言うkatzchangさん。さらにAkka Actorは知らなくてもなんとかなる、ついでにSparkは使わなくてもなんとかなると言い切る。Webアプリケーションの実装はServrlet3.0を使っている。
実際に、会場の参加者もPlayFrameworkよりもServletを触った人の方が少し多く、馴染みがあるツールである。テスティングフレームワークはScalaTestのFreeSpecがシンプルで良いという。
モック、フィクスチャーは難しい。品質をどう担保するかはチーム全体でカバーする。最後にsbtとは私たちにとってはコンパイラ。sbt pluguinはmakefileでがんばればよいのだそう。
パフォーマンス対策はGC対策(val→def)だが、究極の対策は課金すること(サーバを追加)。とにかくベタージャバとして動かしてみることをテンポ良く、会場からの笑いも多く、盛り上がった。
☆☆katzchangさんの講演資料「頑張らないScala」
LT13:「分散ビルド」
最後に登壇したのは、Lightbend社のEugene Yokotaさん。米マサチューセッツからのリモート登壇である。Yokotaさんは商用プラットフォームの開発およびsbtのテックリードも務めている。
今回のLTでは分散ビルドについて解説した。Yokotaさんは現在のReactive Platformチームに入る前は、裏でどうやってスケールさせるのかなど、分散ビルドを担当していた。
Scalaはビルドが遅いとよく言われる。特に大規模なマルチプロジェクトのときはビルドに時間がかかる。そこでLightbend社ではcheckpointという分散ビルド用sbt pluginを開発しており、そのデモを行った。
現在、そのpluginは開発中でまだ公開はされていない。しかし改良が進んで納得したものができれば、Reactive Platformに載せるべく取り組んでいるという。
分散ビルドは特に大規模な製品開発におけるScalaのコンパイルが遅いという問題を解決する技術として使えるという。プラグインの完成が待たれる。
Scalaを始めてみたいと考えているのであれば、ぜひ、このLTを参考に取り組んでみれば。関数型言語といっても、VOYAGE GROUPのkatzchangさんの言葉を借りれば、ベタージャバ。この機会に一歩踏み出してみてはいかがだろう。
【参考レポート】
市ヶ谷Geek★Night#7 「Scala大名の平成維新」 イベントレポート
Javaエンジニアが簡単に習得できる?「秘伝のScalaレシピ」を公開!