See http://www.scalapeno.org.il/#!tzach-zohar/jwhyy:
One of the most common criticisms of Scala, and indeed one of the most concerning ones - is its "Syntactic Diabetes": There's so much "Syntactic Sugar" - so many different ways to code the same thing - that developers might easily get lost. This makes many developers and organizations weary of adopting Scala as a primary language, fearing the training and maintenance costs this problem might entail.
In this talk we'll explain the problem through some real-life examples from Kenshoo's 2- year experience with Scala, and move on to the solutions applied at Kenshoo and elsewhere to resolve this. Among these, we'll discuss style guides, automatic style checkers, Odersky's "Scala Levels", code review tips and more.
If you're a developer thinking about trying Scala out, or a Scala enthusiast trying to convince your teammates or bosses to do so - this talk is for you.
13. val tuples = List((1, 374), (3, 42), (5, 693))
val ids = tuples.map(_._1)
val ids = tuples.map(tuple => tuple._1)
val ids = tuples.map { tuple => tuple._1 }
14. val tuples = List((1, 374), (3, 42), (5, 693))
val ids = tuples.map(_._1)
val ids = tuples.map(tuple => tuple._1)
val ids = tuples.map { tuple => tuple._1 }
val ids = tuples.map(t => t match { case (id, value)=> id })
val ids = tuples.map(_ match { case (id, value) => id })
val ids = tuples.map({ case (id, value) => id })
val ids = tuples.map { case (id, value) => id }
val ids = tuples.map { case (id, _) => id }
15. case class Profile() { … }
case class ProfileId(id: Int)
def loadProfile(profileId: ProfileId): Profile = ???
16. case class Profile() { … }
case class ProfileId(id: Int)
def loadProfile(profileId: ProfileId): Profile = ???
loadProfile(ProfileId(3))
loadProfile(new ProfileId(3))
loadProfile(profileId = ProfileId(3))
loadProfile(profileId = new ProfileId(3))
17. case class Profile() { … }
case class ProfileId(id: Int)
implicit def toId(i :Int): ProfileId = ProfileId(i)
def loadProfile(profileId: ProfileId): Profile = ???
loadProfile(ProfileId(3))
loadProfile(new ProfileId(3))
loadProfile(profileId = ProfileId(3))
loadProfile(profileId = new ProfileId(3))
loadProfile(3)
loadProfile(profileId = 3)
24. Style Guides
1. The basic: Official Scala-Lang Style Guide
2. The conservative: Databricks' Scala Style Guide
3. The exhaustive: Twitter's Effective Scala
4. Your own!
25. Style Guides
implicit def toId(i :Int): ProfileId = ProfileId(i)
loadProfile(ProfileId(3))
loadProfile(3)
“Do not use implicits to do automatic
conversions between similar datatypes”
26. Style Guides
“Avoid infix notation for methods
that aren't symbolic methods”
list map func
string contains "foo"
list.map(func)
string.contains("foo")
val x = y + 2
27. Style Guides
val ids = tuples.map(t => t match { case (id, value)=> id })
val ids = tuples.map(_ match { case (id, value) => id })
val ids = tuples.map { case (id, value) => id }
val ids = tuples.map { case (id, _) => id }
“Use pattern matching directly in function
definitions whenever applicable”
28. Style Guides
def f(value: => Int) = ???
f(2 + 3)
def f(value: () => Int) = ???
f(() => 2 + 3)
“Avoid using call by name.
Use () => T explicitly”
29. @throws[IOException]
def mightThrowException(): Int
def neverThrowsException(): Option[Int]
def neverThrowsException(): Try[Int]
def neverThrowsException(): Either[Int, String]
def neverThrowsException(): MyResult
Style Guides
“Scala provides an exception facility, but do not
use it for commonplace errors”
30. val ids = tuples.map(_._1)
val ids = tuples.map(tuple => tuple._1)
val ids = tuples.map { case (id, value) => id }
val ids = tuples.map { case (id, _) => id }
Style Guides
“Avoid using tuple field names
like _1, prefer pattern matching or
a dedicated case class”
37. Style Checkers
Automate some of the (simpler) rules
1. Scalastyle (SBT/Gradle/Maven/Eclipse/IntelliJ)
2. Scalafmt (SBT/Vim/CLI/IntelliJ) [NEW]
38. ⌚ 18:45:25 ➜ sbt scalastyle
[info] Loading project definition from /.../project
[info] Set current project to myProject (in build file:/.../)
[warn] MyJob.scala:31:6: parameter.number.message
[error]MyService.scala:42:6: public.methods.have.type.message
[info] Processed 42 file(s)
[info] Found 1 errors
[info] Found 2 warnings
[info] Found 0 infos
[info] Finished in 39 ms
Style Checkers
40. Scala Levels
Application Programmer Library Designer
A1: Beginner L1: Junior
A2: Intermediate L2: Senior
A3: Expert L3: Expert
Defined by Martin Odersky in a 2011 post