scala refactoring for fun and profit (japanese subtitles)

16
Scala Refactorin g Tomer Gabel, Scala Matsuri 2016 for Fun and Profit 楽楽楽楽楽楽 Scala 楽楽楽楽楽楽楽楽

Upload: tomer-gabel

Post on 16-Apr-2017

5.067 views

Category:

Engineering


1 download

TRANSCRIPT

Page 1: Scala Refactoring for Fun and Profit (Japanese subtitles)

Scala Refactorin

gTomer Gabel, Scala Matsuri 2016

for Fun and Profit

楽しく役立つ Scala リファクタリング

Page 2: Scala Refactoring for Fun and Profit (Japanese subtitles)

Agenda• For the next 40

minutes, we’ll:– Look at examples

– Discuss patterns

– … and anti-patterns– Showcase

refactoring techniques例を通してパターンとアンチパターンを議論し、

リファクタリングのテクニックを説明する

Page 3: Scala Refactoring for Fun and Profit (Japanese subtitles)

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

Page 4: Scala Refactoring for Fun and Profit (Japanese subtitles)

THE LAY OF THE LAND前線の状況

Page 5: Scala Refactoring for Fun and Profit (Japanese subtitles)

Stringly Typed“Used to describe an implementation that needlessly relies on strings when programmer & refactor friendly options are available.” -- Coding Horror

アンチパターン: Stringly Typed型付けできる所で不必要に文字列に頼った実装のこと

Page 6: Scala Refactoring for Fun and Profit (Japanese subtitles)

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

place3. What’s with all the

boilerplate?

Stringly Typed の例 1: パースしてないデータを持ち回す

Page 7: Scala Refactoring for Fun and Profit (Japanese subtitles)

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 handling3. Zero boilerplate!

パース後のデータを使うことで効率的で、エラー処理が容易に、お決まりの処理も不要になる

Page 8: Scala Refactoring for Fun and Profit (Japanese subtitles)

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 の代わりに空文字を使う

Page 9: Scala Refactoring for Fun and Profit (Japanese subtitles)

REAL-WORLD EXAMPLE TIME!

Page 10: Scala Refactoring for Fun and Profit (Japanese subtitles)

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 クラス、関数、タプルがある。これらは、実は簡単に濫用できてしまう

Page 11: Scala Refactoring for Fun and Profit (Japanese subtitles)

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?アンチパターン:

一行に処理を詰め込み過ぎる

Page 12: Scala Refactoring for Fun and Profit (Japanese subtitles)

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!

中間状態に名前を付けよう!

Page 13: Scala Refactoring for Fun and Profit (Japanese subtitles)

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?

アンチパターン:タプルの使いすぎ

Page 14: Scala Refactoring for Fun and Profit (Japanese subtitles)

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 クラスを簡単に定義できるどんどん使おう

Page 15: Scala Refactoring for Fun and Profit (Japanese subtitles)

REAL-WORLD EXAMPLE TIME!

Page 16: Scala Refactoring for Fun and Profit (Japanese subtitles)

Questions?

[email protected]@tomerghttp://il.linkedin.com/in/tomergabel

WE’RE DONE HERE!