Non-Functional Programming in Scala

250 views

Published on

Scala Kansai Summit 2017 #scala_ks

Published in: Software
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
250
On SlideShare
0
From Embeds
0
Number of Embeds
17
Actions
Shares
0
Downloads
0
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Non-Functional Programming in Scala

  1. 1. Non-Functional Programming in Scala Naoki Takezoe @takezoen BizReach, Inc
  2. 2. 自己紹介 竹添 直樹: @takezoen ビズリーチという会社でScalaを書いてます OSS開発や技術書の執筆などもしています
  3. 3. 主題 Scalaがもっと普及して欲しい そうしないと自分が失業してしまう(重要!!) そのためにはどうすればいいのか?
  4. 4. いままでやってきたこと Scalaの本を書いたり、翻訳したりした SI企業で業務システム開発の事例を作った Scalaでオープンソースプロダクトを開発 Scala関連イベントのサポート Webサービス企業でそれなりの規模でScalaを採用した
  5. 5. 突き当たった壁
  6. 6. 関数型プログラミング
  7. 7. 関数型プログラミング in Scala 基本的には副作用を使った手続き型プログラミング言語 関数型言語由来の様々な機能を備えている for内包表記、暗黙的なモナド Scalaz、Cats、Slickなどの関数型ライブラリ どこまで関数型に寄せるか?という選択を迫られる プログラミングスタイルだけでなく、ライブラリやフレームワークの 選定から考慮しなくてはならない
  8. 8. 振り返ってみる 業務での開発で起きたこと OSS開発で起きたこと
  9. 9. 業務での開発で起きたこと 時間 Scala力
  10. 10. 業務での開発で起きたこと 最初はみんな 初心者 時間 Scala力
  11. 11. 業務での開発で起きたこと Scala力アップ!! 最初はみんな 初心者 時間 Scala力
  12. 12. 業務での開発で起きたこと Scala力アップ!! 最初はみんな 初心者 後から入ってくる 人つらい!! 時間 Scala力 ハードルの高さ
  13. 13. こうあって欲しい(気持ちは理解できる) 時間 Java力
  14. 14. 業務での開発で起きたこと 最初はみんなScala初心者だった 初期のメンバーが少しずつレベルアップしてくる 関数型プログラミングが取り入れられてくる 時代によってコードの傾向が違う 後から入ってくる人ほどつらくなってしまう
  15. 15. 振り返り Scalaはプログラマの成長にあわせてスタイルを変えられる 長期間、固定のチームで開発するのであればチームの成長にあ わせて変化していくことができる メンバーの増加・入れ替わりが激しい場合は変化が大きいとどん どんハードルが上がっていってしまう
  16. 16. OSS開発で起きたこと Elasticsearch-Hadoop、Apache PredictionIOなど 手続き型バリバリのプログラミングスタイル varやmutableコレクション、whileループ、returnや例外なども多 用されている
  17. 17. OSS開発で起きたこと コミッターのスキルが低いのか?そんなことはない バックグラウンド、モチベーションの違い SparkのためにScalaを使っている
  18. 18. 振り返り 言語としてではなくプロダクトとしてのニーズが存在する ○○を使えば□□ができる、というフックは増やしていくべき
  19. 19. 関数型プログラミングへのモチベーションが 低い状況でどうScalaを使うか?
  20. 20. 方針 そもそもScalaは副作用のある手続き型プログラミング言語であ り、モナドを意識せずに使えるように設計されている Scalaの便利な機能を使いつつ、関数型プログラミングに寄せす ぎないようにする
  21. 21. 使うべきか?使わないべきか? ● var、while ● mutableコレクション ● return ● 例外 ● null ● Option.get ● for内包表記 ● 型クラス
  22. 22. 考えてみよう!!
  23. 23. var、while
  24. 24. var、while ループ処理などでフラグやアキュムレータなどに使いがち takeWhileやfoldLeftなどで代用可能だが取っつきづらい var line = reader.readLine() while(line != null) { ... line = reader.readLine() }
  25. 25. var、while ループ処理などでフラグやアキュムレータなどに使いがち takeWhileやfoldLeftなどで代用可能だが取っつきづらい var line = reader.readLine() while(line != null) { ... line = reader.readLine() }
  26. 26. var、while メソッド内での利用であれば許容する valはJavaでfinalをつけるかどうかくらいの感覚で使い分けるの がよさそう
  27. 27. mutableコレクション
  28. 28. mutableコレクション ループしながら詰め替えるような処理で使いがち val list = ... val map = mutable.Map("some" -> 0, "none" -> 0) list.foreach { x => if (x.nonEmpty) { map.put("some", map("some") + 1) } else { map.put("none", map("none") + 1) } }
  29. 29. mutableコレクション ループしながら詰め替えるような処理で使いがち val list = ... val map = mutable.Map("some" -> 0, "none" -> 0) list.foreach { x => if (x.nonEmpty) { map.put("some", map("some") + 1) } else { map.put("none", map("none") + 1) } }
  30. 30. mutableコレクション メソッド内での利用であれば許容する 戻り値として返す際にimmutableなコレクションに変換する 使わなくても済むものはimmutableなコレクションを使うように啓 蒙していく val map = list.groupBy(_.nonEmpty) .map { case (nonEmpty, values) => if(nonEmpty) "some" -> values.size else "none" -> values.size }
  31. 31. return
  32. 32. return Ealry returnやループ処理中からのreturnなどが使われがち def hello(names: Seq[String]): String = { if(name.isEmpty) return "" ... } 戻り値の型を明記しないといけなくなる コンパイル後に例外(ControlThrowable)で実現されるケースが ある
  33. 33. return Ealry returnやループ処理中からのreturnなどが使われがち def hello(names: Seq[String]): String = { if(name.isEmpty) return "" ... } 戻り値の型を明記しないといけなくなる コンパイル後に例外(ControlThrowable)で実現されるケースが ある
  34. 34. return 実際に問題になるケースは少ないので許容してもよいのでは そもそも例外をThrowableでキャッチしない try { ... } catch { case NonFatal(t) => ... }
  35. 35. 例外
  36. 36. 例外 エラーを戻り値で返すか?Eitherなどで返すか? def findUser(): Either[Exception, User] = { try { val user: User = ... Right(user) } catch { case e: Exception => Left(e) } }
  37. 37. 例外 エラーを戻り値で返すか?Eitherなどで返すか? def findUser(): Either[Exception, User] = { try { val user: User = ... Right(user) } catch { case e: Exception => Left(e) } }
  38. 38. 例外 Eitherで返そうとすると 例外の発生は防げないので変換が必要になる for内包表記やEitherTなどが登場してしまう 通常は積極的に例外に倒してしまってもよいのでは? ただし非同期処理の場合は別
  39. 39. null
  40. 40. null
  41. 41. null 使うべき理由がまるでない がくぞー先生に消されてしまう Optionを使う Javaライブラリを使う部分は仕方ない
  42. 42. Option.get
  43. 43. Option.get 値が必ず入っているはずだと直接getしがち Noneチェックしてからgetしがち val opt: Option[String] = ... if(opt.isDefined){ val str = opt.get ... }
  44. 44. Option.get 値が必ず入っているはずだと直接getしがち Noneチェックしてからgetしがち val opt: Option[String] = ... if(opt.isDefined){ val str = opt.get ... }
  45. 45. Option.get opt.getOrElse("") などとする人が出現 getして明示的にエラーになる方がマシではある mapやforeachなどを使うよう啓蒙していく
  46. 46. for内包表記
  47. 47. for内包表記 モナモナするときに使う for { project <- findProject(projectId) user <- findUser(userId) } yield { registerComment(project, user, comment) }
  48. 48. for内包表記 モナモナするときに使う for { project <- findProject(projectId) user <- findUser(userId) } yield { registerComment(project, user, comment) }
  49. 49. for内包表記 無理して使わない コレクション操作やFutureのチェーンをシンプルに記述するため に使う その場合もmapやflatMapのシンタックスシュガーという認識があ ればよい 「モナド」って言わない
  50. 50. 型クラス
  51. 51. 型クラス implicitの使い方の一種 implicit val userInfoReads = Json.reads[UserInfoInfo] r.body.validate[UserInfo].fold( error => ..., form => ... ) sealed trait JsValue extends JsReadable { def validate[A](implicit rds: Reads[A]): JsResult[A] }
  52. 52. 型クラス implicitの使い方の一種 implicit val userInfoReads = Json.reads[UserInfoInfo] r.body.validate[UserInfo].fold( error => ..., form => ... ) sealed trait JsValue extends JsReadable { def validate[A](implicit rds: Reads[A]): JsResult[A] }
  53. 53. 型クラス フレームワークやライブラリで使っているケースが多い 使うだけであれば意識する必要はない(CanBuildFromを意識し なくてもScalaのコレクションは使える) play-jsonのReads/Writesのように自分で実装しないといけない ケースもあるが、そこまで躓くことはない印象(面倒なのはさてお き...) 「型クラス」って言わない
  54. 54. 結果 ● var、while ● mutableコレクション ● return ● 例外 ● null ● Option.get ● for内包表記 ● 型クラス
  55. 55. 最終的にはケースバイケース これはあくまでも判断の一例 プロダクトの方向性、今後のチーム運営も考えて決める チームのスキルが一様であればそれにあわせればよい
  56. 56. Scalaを使う人がもっと増えて欲しい 最初はみんな初心者だった Scalaで楽しくプログラミングをして欲しい 関数型プログラミングに興味のある人だけでなく、 それ以外の人たちにもScalaを使って欲しい Scalaを使っているのにというジレンマを感じることもある いろんな使い方ができるのもScalaの良いところ Scalaユーザが増えることで自分たちの選択肢も広がる
  57. 57. ご静聴ありがとうございました

×
Save this presentationTap To Close