SlideShare a Scribd company logo
Scala
Refactoring
Tomer Gabel, CodeMotion Tel-Aviv 2015
for Fun and Profit
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
– Long-lived
– High quality code
– MIT license
– Integrated in lichess.org
* ScalaChess is an open-source project by Thibault Duplessis
STARTING OFF
Naming Things
• New features complicate matters:
– Infix notation (a.k.a dot-free syntax)
case class Geo(lat: Double, long: Double) {
def distance(other: Geo): Double = // ...
}
val (center, location): Geo = // ...
if (centre.distance(location) <= radius)
Some(loc) else None
Naming Things
• New features complicate matters:
– Infix notation (a.k.a dot-free syntax)
case class Geo(lat: Double, long: Double) {
def distance(other: Geo): Double = // ...
}
val (center, location): Geo = // ...
if (centre distance location <= radius)
Some(loc) else None What language is this?
Naming Things
• New features complicate matters:
– Infix notation (a.k.a dot-free syntax)
case class Geo(lat: Double, long: Double) {
def distanceFrom(other: Geo): Double = //…
}
val (center, location): Geo = // ...
if (location distanceFrom center <= radius)
Some(loc) else None A little clearer now
Naming Things
• Oh, the humanity: Symbolic operators
case class Geo(lat: Double, long: Double) {
def <->(other: Geo): Double = // ...
}
val Geo(center, location) = // ...
if (loc <-> center <= radius)
Some(loc) else None
Why would you do that?!
Naming Things
• There are worse offenders. Take Dispatch:
import dispatch.Http
import Http._
val server = url("http://example.com")
val headers = Map("Accept" -> "application/json")
Http(server >>> System.out) // GET
Http(server <:< headers >>> System.out) // GET
Http(server << yourPostData >|) // POST
Naming Things
• There are worse offenders. Take scalaz:
def s[A](a: A) = a.success[List[String]]
val add3 = (x: Int) =>
(y: Int) =>
(z: Int) => x + y + z
val res = (7) <*> (s(8) <*> (s(9) ∘ add3))
assert(res == s(24))
REAL-WORLD EXAMPLE TIME!
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
• Examples:
– Passing dates as strings
– Carrying unparsed data around
– Using empty strings instead of Options
case class Person(name: String, created: String)
def resolveConflict(p1: Person, p2: Person): Person = {
val c1 = dateParser.parse(p1.created)
val c2 = dateParser.parse(p2.created)
if (c1 compareTo c2 > 0) p1 else p2
}
1. Parser needs to be well-known
2. Error handling all over the place
3. What’s with all the boilerplate?
Stringly Typed
• Examples:
– Passing dates as strings
– 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
• Examples:
– Passing dates as strings
– 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:
– Passing dates as strings
– 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 :-)
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
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.
REAL-WORLD EXAMPLE TIME!
Scoping
• Correct scoping is incredibly
important!
–Separation of concerns
–Code navigation and discovery
–Reduced autocompletion noise
Scoping
• Scala offers an
impressive toolbox:
– Nested scopes
– Companion objects
– Traits
– Visibility modifiers
– Type classes
Scoping
class User(var name: String,
var age: Int,
initialStatus: UserStatus = New) {
private var _status = initialStatus
def status = _status
def delete(): Unit = {
_status = Deleted
Mailer.notify(Mailer.userDeletion, this)
}
}
Mutable data ⇒ Boilerplate
SoC broken!
EXAMPLE TIME!
https://github.com/holograph/scala-refactoring
Scoping
• Lessons learned:
–Keep logic and data separate
–Case classes are your friends!
–Add “aspects” via type classes
Scoping
• Rules of the road:
–Keep your public API small
–Make everything else private
–Put helpers in companions
–… or via implicit extensions
Questions?
tomer@tomergabel.com
@tomerg
http://il.linkedin.com/in/tomergabel
WE’RE DONE
HERE!

More Related Content

PPTX
Speaking Scala: Refactoring for Fun and Profit (Workshop)
PDF
Few simple-type-tricks in scala
PDF
Ponies and Unicorns With Scala
PDF
A Scala Corrections Library
PPTX
A Brief Intro to Scala
PDF
SE 20016 - programming languages landscape.
PPTX
From Ruby to Scala
PDF
High Wizardry in the Land of Scala
Speaking Scala: Refactoring for Fun and Profit (Workshop)
Few simple-type-tricks in scala
Ponies and Unicorns With Scala
A Scala Corrections Library
A Brief Intro to Scala
SE 20016 - programming languages landscape.
From Ruby to Scala
High Wizardry in the Land of Scala

What's hot (20)

PPTX
PDF
Scala jargon cheatsheet
ODP
A Tour Of Scala
PPTX
Scala fundamentals
PDF
Demystifying Shapeless
PPTX
Scala Refactoring for Fun and Profit (Japanese subtitles)
PDF
Scala : language of the future
PDF
Scala introduction
PPTX
Practically Functional
PDF
Introduction to Scala for Java Developers
PDF
Weaving Dataflows with Silk - ScalaMatsuri 2014, Tokyo
ODP
10 Things I Hate About Scala
PDF
Introduction To Scala
PDF
Scala In The Wild
PDF
Spark workshop
PDF
The Evolution of Scala / Scala進化論
PDF
Brief tour of psp-std
PDF
Scala - just good for Java shops?
PDF
Live coding scala 'the java of the future'
PDF
Scala in Practice
Scala jargon cheatsheet
A Tour Of Scala
Scala fundamentals
Demystifying Shapeless
Scala Refactoring for Fun and Profit (Japanese subtitles)
Scala : language of the future
Scala introduction
Practically Functional
Introduction to Scala for Java Developers
Weaving Dataflows with Silk - ScalaMatsuri 2014, Tokyo
10 Things I Hate About Scala
Introduction To Scala
Scala In The Wild
Spark workshop
The Evolution of Scala / Scala進化論
Brief tour of psp-std
Scala - just good for Java shops?
Live coding scala 'the java of the future'
Scala in Practice
Ad

Viewers also liked (10)

PPTX
унікальні рослини і тварини (підсумковий проект)
PPSX
Deferred Action (DACA)
PPTX
Nii情報リテラシー研修 20151120 大阪大・久保山_参考事例
PPTX
Contentstrategie en -aanpak ABN AMRO @ Content Club 30 juni 2016
PDF
What would hhappen if payday loans are outlawed
PDF
Power tools in Java
PPTX
ICT AS Level Software AQA
PPTX
Hanz and Franz
PPTX
7 Mistakes Professionals Make on Social Media
PDF
FAWZEY CV LATEST UPDATE-3
унікальні рослини і тварини (підсумковий проект)
Deferred Action (DACA)
Nii情報リテラシー研修 20151120 大阪大・久保山_参考事例
Contentstrategie en -aanpak ABN AMRO @ Content Club 30 juni 2016
What would hhappen if payday loans are outlawed
Power tools in Java
ICT AS Level Software AQA
Hanz and Franz
7 Mistakes Professionals Make on Social Media
FAWZEY CV LATEST UPDATE-3
Ad

Similar to Scala Refactoring for Fun and Profit (20)

PDF
(How) can we benefit from adopting scala?
PDF
Scala in Places API
PPTX
Taxonomy of Scala
PPTX
Scala for curious
PPTX
Scala Back to Basics: Type Classes
PDF
Scala for Java Programmers
PPTX
Proposals for new function in Java SE 9 and beyond
PDF
The Scala Programming Language
ODP
PPT
Scala introduction
PDF
Scala: Functioneel programmeren in een object georiënteerde wereld
PDF
Scala @ TechMeetup Edinburgh
PDF
Pune Clojure Course Outline
PDF
Meet scala
PDF
Scala: Object-Oriented Meets Functional, by Iulian Dragos
PPTX
scala-101
PDF
Lecture 3
PDF
From Java to Scala - advantages and possible risks
PPTX
Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...
PPTX
BASE Meetup: "Analysing Scala Puzzlers: Essential and Accidental Complexity i...
(How) can we benefit from adopting scala?
Scala in Places API
Taxonomy of Scala
Scala for curious
Scala Back to Basics: Type Classes
Scala for Java Programmers
Proposals for new function in Java SE 9 and beyond
The Scala Programming Language
Scala introduction
Scala: Functioneel programmeren in een object georiënteerde wereld
Scala @ TechMeetup Edinburgh
Pune Clojure Course Outline
Meet scala
Scala: Object-Oriented Meets Functional, by Iulian Dragos
scala-101
Lecture 3
From Java to Scala - advantages and possible risks
Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...
BASE Meetup: "Analysing Scala Puzzlers: Essential and Accidental Complexity i...

More from Tomer Gabel (20)

PDF
How shit works: Time
PDF
Nondeterministic Software for the Rest of Us
PDF
Slaying Sacred Cows: Deconstructing Dependency Injection
PDF
An Abridged Guide to Event Sourcing
PDF
How shit works: the CPU
PDF
How Shit Works: Storage
PDF
Java 8 and Beyond, a Scala Story
PDF
The Wix Microservice Stack
PDF
Onboarding at Scale
PPTX
Scala in the Wild
PPTX
Put Your Thinking CAP On
PPTX
Leveraging Scala Macros for Better Validation
PDF
A Field Guide to DSL Design in Scala
PPTX
Functional Leap of Faith (Keynote at JDay Lviv 2014)
PDF
5 Bullets to Scala Adoption
PPTX
Nashorn: JavaScript that doesn’t suck (ILJUG)
PPTX
Lab: JVM Production Debugging 101
PPTX
DevCon³: Scala Best Practices
PPTX
Maven for Dummies
PPTX
Scala in practice
How shit works: Time
Nondeterministic Software for the Rest of Us
Slaying Sacred Cows: Deconstructing Dependency Injection
An Abridged Guide to Event Sourcing
How shit works: the CPU
How Shit Works: Storage
Java 8 and Beyond, a Scala Story
The Wix Microservice Stack
Onboarding at Scale
Scala in the Wild
Put Your Thinking CAP On
Leveraging Scala Macros for Better Validation
A Field Guide to DSL Design in Scala
Functional Leap of Faith (Keynote at JDay Lviv 2014)
5 Bullets to Scala Adoption
Nashorn: JavaScript that doesn’t suck (ILJUG)
Lab: JVM Production Debugging 101
DevCon³: Scala Best Practices
Maven for Dummies
Scala in practice

Recently uploaded (20)

PDF
Machine learning based COVID-19 study performance prediction
PPTX
cloud_computing_Infrastucture_as_cloud_p
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
NewMind AI Weekly Chronicles - August'25-Week II
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PPT
Teaching material agriculture food technology
PDF
Assigned Numbers - 2025 - Bluetooth® Document
PPTX
Tartificialntelligence_presentation.pptx
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Spectral efficient network and resource selection model in 5G networks
PPTX
Spectroscopy.pptx food analysis technology
PDF
Mushroom cultivation and it's methods.pdf
PPTX
1. Introduction to Computer Programming.pptx
PDF
Approach and Philosophy of On baking technology
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
Empathic Computing: Creating Shared Understanding
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Machine learning based COVID-19 study performance prediction
cloud_computing_Infrastucture_as_cloud_p
Reach Out and Touch Someone: Haptics and Empathic Computing
Building Integrated photovoltaic BIPV_UPV.pdf
gpt5_lecture_notes_comprehensive_20250812015547.pdf
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
NewMind AI Weekly Chronicles - August'25-Week II
Mobile App Security Testing_ A Comprehensive Guide.pdf
Teaching material agriculture food technology
Assigned Numbers - 2025 - Bluetooth® Document
Tartificialntelligence_presentation.pptx
Diabetes mellitus diagnosis method based random forest with bat algorithm
Spectral efficient network and resource selection model in 5G networks
Spectroscopy.pptx food analysis technology
Mushroom cultivation and it's methods.pdf
1. Introduction to Computer Programming.pptx
Approach and Philosophy of On baking technology
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
Empathic Computing: Creating Shared Understanding
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...

Scala Refactoring for Fun and Profit

  • 1. Scala Refactoring Tomer Gabel, CodeMotion Tel-Aviv 2015 for Fun and Profit
  • 2. Agenda • For the next 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 – Long-lived – High quality code – MIT license – Integrated in lichess.org * ScalaChess is an open-source project by Thibault Duplessis
  • 5. Naming Things • New features complicate matters: – Infix notation (a.k.a dot-free syntax) case class Geo(lat: Double, long: Double) { def distance(other: Geo): Double = // ... } val (center, location): Geo = // ... if (centre.distance(location) <= radius) Some(loc) else None
  • 6. Naming Things • New features complicate matters: – Infix notation (a.k.a dot-free syntax) case class Geo(lat: Double, long: Double) { def distance(other: Geo): Double = // ... } val (center, location): Geo = // ... if (centre distance location <= radius) Some(loc) else None What language is this?
  • 7. Naming Things • New features complicate matters: – Infix notation (a.k.a dot-free syntax) case class Geo(lat: Double, long: Double) { def distanceFrom(other: Geo): Double = //… } val (center, location): Geo = // ... if (location distanceFrom center <= radius) Some(loc) else None A little clearer now
  • 8. Naming Things • Oh, the humanity: Symbolic operators case class Geo(lat: Double, long: Double) { def <->(other: Geo): Double = // ... } val Geo(center, location) = // ... if (loc <-> center <= radius) Some(loc) else None Why would you do that?!
  • 9. Naming Things • There are worse offenders. Take Dispatch: import dispatch.Http import Http._ val server = url("http://example.com") val headers = Map("Accept" -> "application/json") Http(server >>> System.out) // GET Http(server <:< headers >>> System.out) // GET Http(server << yourPostData >|) // POST
  • 10. Naming Things • There are worse offenders. Take scalaz: def s[A](a: A) = a.success[List[String]] val add3 = (x: Int) => (y: Int) => (z: Int) => x + y + z val res = (7) <*> (s(8) <*> (s(9) ∘ add3)) assert(res == s(24))
  • 12. THE LAY OF THE LAND
  • 13. Stringly Typed “Used to describe an implementation that needlessly relies on strings when programmer & refactor friendly options are available.” -- Coding Horror
  • 14. Stringly Typed • Examples: – Passing dates as strings – Carrying unparsed data around – Using empty strings instead of Options case class Person(name: String, created: String) def resolveConflict(p1: Person, p2: Person): Person = { val c1 = dateParser.parse(p1.created) val c2 = dateParser.parse(p2.created) if (c1 compareTo c2 > 0) p1 else p2 } 1. Parser needs to be well-known 2. Error handling all over the place 3. What’s with all the boilerplate?
  • 15. Stringly Typed • Examples: – Passing dates as strings – 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?
  • 16. Stringly Typed • Examples: – Passing dates as strings – 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!
  • 17. Stringly Typed • Examples: – Passing dates as strings – 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 :-)
  • 19. 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
  • 20. 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?
  • 21. 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!
  • 22. 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?
  • 23. 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.
  • 25. Scoping • Correct scoping is incredibly important! –Separation of concerns –Code navigation and discovery –Reduced autocompletion noise
  • 26. Scoping • Scala offers an impressive toolbox: – Nested scopes – Companion objects – Traits – Visibility modifiers – Type classes
  • 27. Scoping class User(var name: String, var age: Int, initialStatus: UserStatus = New) { private var _status = initialStatus def status = _status def delete(): Unit = { _status = Deleted Mailer.notify(Mailer.userDeletion, this) } } Mutable data ⇒ Boilerplate SoC broken!
  • 29. Scoping • Lessons learned: –Keep logic and data separate –Case classes are your friends! –Add “aspects” via type classes
  • 30. Scoping • Rules of the road: –Keep your public API small –Make everything else private –Put helpers in companions –… or via implicit extensions

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
  • #19: Image source: https://thisistwitchy.files.wordpress.com/2013/04/oh-the-horror.jpg
  • #20: Image source: http://onlinesalesstepbystep.com/wp-content/uploads/2014/08/Toppling-books.jpg
  • #25: Photo source: https://flic.kr/p/3xcrQG
  • #27: Photo source: https://flic.kr/p/c4QJzC
  • #29: Photo source: https://flic.kr/p/3xcrQG