Scala
Refactoring
Tomer Gabel, Scala Matsuri 2016
for Fun and Profit
楽しく役立つ Scala リファクタリング
Agenda
• For the next 40
minutes, we’ll:
– Look at examples
– Discuss patterns
– … and anti-patterns
– Showcase refactoring
techniques
例を通してパターンとアンチパターンを議論し、
リファクタリングのテクニックを説明する
Our Victim
• … is ScalaChess
– Provides a full domain
model for chess
– Good test coverage
– High quality code
– MIT license
– Integrated in lichess.org* ScalaChess is an open-source project by Thibault Duplessis
チェスのドメインモデルを備えるScalaChessを例にする
高品質でlichess.orgと統合されたMITライセンスのOSS
THE LAY OF THE
LAND前線の状況
Stringly Typed
“Used to describe an implementation
that needlessly relies on strings when
programmer & refactor friendly options
are available.”
-- Coding
Horror
アンチパターン:Stringly Typed
型付けできる所で不必要に文字列に頼った実装のこと
Stringly Typed
• Examples:
– Carrying unparsed data around
– Using empty strings instead of Options
case class Person(name: String, location: String)
def nearest(to: Person, all: List[Person]): Person = {
val geo: Point = Point.parse(to.location)
all.minBy(p => geo.distanceTo(Point.parse(p.location)))
}
1. Inefficient (space/time)
2. Error handling all over the place
3. What’s with all the boilerplate?
Stringly Typed の例1:
パースしてないデータを持ち回す
Stringly Typed
• Examples:
– Carrying unparsed data around
– Using empty strings instead of Options
case class Person(name: String, location: Point)
def nearest(to: Person, all: List[Person]): Person =
all.minBy(p => to.location distanceTo p.location)
1. Efficient (only parsed once)
2. Sane error handling
3. Zero boilerplate!
パース後のデータを使うことで効率的で、
エラー処理が容易に、お決まりの処理も不要になる
Stringly Typed
• Examples:
– Carrying unparsed data around
– Using empty strings instead of Options
case class Person(firstName: String, lastName: String)
def render(p: Person): String =
s"""
|<div id='first-name'>${p.firstName}</div>
|<div id='last-name'>${p.lastName}</div>
""".stripMargin
1. Nothing enforces emptiness check!
2. Scala has a great type for these :-)
Stringly Typed の例2:
Option の代わりに空文字を使う
REAL-WORLD EXAMPLE TIME!
Collective Abuse
• Scala has a massive
collection library
• Loads of built-ins too
– Case classes
– Functions and partials
– Tuples, tuples, tuples
• Fairly easy to abuse
Scalaにはたくさんのコレクション、caseクラス、関数、
タプルがある。これらは、実は簡単に濫用できてしまう
Collective Abuse
• Common anti-patterns:
– Too many inline steps
– Tuple overload
val actors: List[(Int, String, Double)] = // ...
def bestActor(query: String) =
actors.filter(_._2 contains query)
.sortBy(-_._3)
.map(_._1)
.headOption
1. What does this even do?!
2. How does data flow here?
アンチパターン:
一行に処理を詰め込み過ぎる
Collective Abuse
• Common anti-patterns:
– Too many inline steps
– Tuple overload
val actors: List[(Int, String, Double)] = // ...
def bestActor(query: String) = {
val matching = actors.filter(_._2 contains query)
val bestByScore = matching.sortBy(-_._3).headOption
bestByScore.map(_._1)
} Name intermediate steps!
中間状態に名前を付けよう!
Collective Abuse
• Common anti-patterns:
– Too many inline steps
– Tuple overload
val actors: List[(Int, String, Double)] = // ...
def bestActor(query: String) =
actors.filter(_._2 contains query)
.sortBy(-_._3)
.map(_._1)
.headOption
What’s with all these
underscores?
アンチパターン:
タプルの使いすぎ
Collective Abuse
• Common anti-patterns:
– Too many inline steps
– Tuple overload
case class Actor(id: Int, name: String, score: Double)
def bestActor(query: String, actors: List[Actor]) =
actors.filter(_.name contains query)
.sortBy(-_.score)
.map(_.id)
.headOption
Scala classes are cheap.
Use them.
Scala ではcaseクラスを簡単に定義できる
どんどん使おう
REAL-WORLD EXAMPLE TIME!
Questions?
tomer@tomergabel.com
@tomerg
http://il.linkedin.com/in/tomergabel
WE’RE DONE
HERE!

Scala Refactoring for Fun and Profit (Japanese subtitles)

  • 1.
    Scala Refactoring Tomer Gabel, ScalaMatsuri 2016 for Fun and Profit 楽しく役立つ Scala リファクタリング
  • 2.
    Agenda • For thenext 40 minutes, we’ll: – Look at examples – Discuss patterns – … and anti-patterns – Showcase refactoring techniques 例を通してパターンとアンチパターンを議論し、 リファクタリングのテクニックを説明する
  • 3.
    Our Victim • …is ScalaChess – Provides a full domain model for chess – Good test coverage – High quality code – MIT license – Integrated in lichess.org* ScalaChess is an open-source project by Thibault Duplessis チェスのドメインモデルを備えるScalaChessを例にする 高品質でlichess.orgと統合されたMITライセンスのOSS
  • 4.
    THE LAY OFTHE LAND前線の状況
  • 5.
    Stringly Typed “Used todescribe an implementation that needlessly relies on strings when programmer & refactor friendly options are available.” -- Coding Horror アンチパターン:Stringly Typed 型付けできる所で不必要に文字列に頼った実装のこと
  • 6.
    Stringly Typed • Examples: –Carrying unparsed data around – Using empty strings instead of Options case class Person(name: String, location: String) def nearest(to: Person, all: List[Person]): Person = { val geo: Point = Point.parse(to.location) all.minBy(p => geo.distanceTo(Point.parse(p.location))) } 1. Inefficient (space/time) 2. Error handling all over the place 3. What’s with all the boilerplate? Stringly Typed の例1: パースしてないデータを持ち回す
  • 7.
    Stringly Typed • Examples: –Carrying unparsed data around – Using empty strings instead of Options case class Person(name: String, location: Point) def nearest(to: Person, all: List[Person]): Person = all.minBy(p => to.location distanceTo p.location) 1. Efficient (only parsed once) 2. Sane error handling 3. Zero boilerplate! パース後のデータを使うことで効率的で、 エラー処理が容易に、お決まりの処理も不要になる
  • 8.
    Stringly Typed • Examples: –Carrying unparsed data around – Using empty strings instead of Options case class Person(firstName: String, lastName: String) def render(p: Person): String = s""" |<div id='first-name'>${p.firstName}</div> |<div id='last-name'>${p.lastName}</div> """.stripMargin 1. Nothing enforces emptiness check! 2. Scala has a great type for these :-) Stringly Typed の例2: Option の代わりに空文字を使う
  • 9.
  • 10.
    Collective Abuse • Scalahas a massive collection library • Loads of built-ins too – Case classes – Functions and partials – Tuples, tuples, tuples • Fairly easy to abuse Scalaにはたくさんのコレクション、caseクラス、関数、 タプルがある。これらは、実は簡単に濫用できてしまう
  • 11.
    Collective Abuse • Commonanti-patterns: – Too many inline steps – Tuple overload val actors: List[(Int, String, Double)] = // ... def bestActor(query: String) = actors.filter(_._2 contains query) .sortBy(-_._3) .map(_._1) .headOption 1. What does this even do?! 2. How does data flow here? アンチパターン: 一行に処理を詰め込み過ぎる
  • 12.
    Collective Abuse • Commonanti-patterns: – Too many inline steps – Tuple overload val actors: List[(Int, String, Double)] = // ... def bestActor(query: String) = { val matching = actors.filter(_._2 contains query) val bestByScore = matching.sortBy(-_._3).headOption bestByScore.map(_._1) } Name intermediate steps! 中間状態に名前を付けよう!
  • 13.
    Collective Abuse • Commonanti-patterns: – Too many inline steps – Tuple overload val actors: List[(Int, String, Double)] = // ... def bestActor(query: String) = actors.filter(_._2 contains query) .sortBy(-_._3) .map(_._1) .headOption What’s with all these underscores? アンチパターン: タプルの使いすぎ
  • 14.
    Collective Abuse • Commonanti-patterns: – Too many inline steps – Tuple overload case class Actor(id: Int, name: String, score: Double) def bestActor(query: String, actors: List[Actor]) = actors.filter(_.name contains query) .sortBy(-_.score) .map(_.id) .headOption Scala classes are cheap. Use them. Scala ではcaseクラスを簡単に定義できる どんどん使おう
  • 15.
  • 16.

Editor's Notes

  • #10 Source: http://stackoverflow.com/questions/5564074/scala-http-operations
  • #11 Source: http://scalaz.github.io/scalaz/scalaz-2.9.1-6.0.4/doc.sxr/scalaz/example/ExampleApplicative.scala.html
  • #12 Photo source: https://flic.kr/p/3xcrQG
  • #13 Image source: http://www.flickeringmyth.com/2015/06/fallout-4-graphics-and-why-visual-demands-are-dumb.html
  • #18 Image source: https://thisistwitchy.files.wordpress.com/2013/04/oh-the-horror.jpg
  • #19 Image source: http://onlinesalesstepbystep.com/wp-content/uploads/2014/08/Toppling-books.jpg
  • #24 Photo source: https://flic.kr/p/3xcrQG