Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

“Insulin” for Scala’s Syntactic Diabetes

637 views

Published on

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.

Published in: Software
  • Be the first to comment

“Insulin” for Scala’s Syntactic Diabetes

  1. 1. “Insulin” for Scala’s Syntactic Diabetes Tzach Zohar // Kenshoo // Scalapeño 2016
  2. 2. OR: How to adopt Scala and survive source
  3. 3. source
  4. 4. Who am I NOT Chuck Norris! Scala “Advanced Beginner” / “Competent” System Architect @ Kenshoo
  5. 5. Who’s Kenshoo 10-year Tel-Aviv based startup Industry Leader in Digital Marketing Java + JavaScript shop http://kenshoo.com/
  6. 6. Scala @ Kenshoo 5 services written in Scala More to come... Internal Scala course on the go
  7. 7. What’s so scary?
  8. 8. trait GeneralizedCategory { type U <: Hom type =>:[A >: U#L <: U#H, B >: U#L <: U#H] = U#C[A, B] def id[A >: U#L <: U#H]: A =>: A def compose[A >: U#L <: U#H, B >: U#L <: U#H, C >: U#L <: U#H]( f: B =>: C, g: A =>: B): A =>: C def *[UY<:Hom](that : GeneralizedCategory {type U=UY}) = Category.ProductCategory[U,UY](this,that) } source
  9. 9. source
  10. 10. source def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That
  11. 11. Now for some sane examples source
  12. 12. 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 }
  13. 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 } 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 }
  14. 14. case class Profile() { … } case class ProfileId(id: Int) def loadProfile(profileId: ProfileId): Profile = ???
  15. 15. 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))
  16. 16. 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)
  17. 17. def loadInt(): Int = { … } def f(value: () => Int) = { … } f(() => 2 + loadInt())
  18. 18. def loadInt(): Int = { … } def f(value: () => Int) = { … } f(() => 2 + loadInt()) def f(value: => Int) = { … } f(2 + loadInt())
  19. 19. Too Much Sugar? source
  20. 20. Issues so far Too many ways to write the same thing Tradeoff between short and readable Advanced features getting in the way
  21. 21. Insulin to the rescue
  22. 22. 1. Style Guides source
  23. 23. 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!
  24. 24. 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”
  25. 25. 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
  26. 26. 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”
  27. 27. Style Guides def f(value: => Int) = ??? f(2 + 3) def f(value: () => Int) = ??? f(() => 2 + 3) “Avoid using call by name. Use () => T explicitly”
  28. 28. @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”
  29. 29. 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”
  30. 30. 2. Code Reviews source
  31. 31. Code Reviews Refer author to Style Guides Mix “Scala Levels” - juniors should review seniors’ code
  32. 32. Code Reviews
  33. 33. Code Reviews
  34. 34. Code Reviews [Only] methods which act as accessors [...] should be declared without parentheses, except if they have side effects
  35. 35. 3. Style Checkers source
  36. 36. Style Checkers Automate some of the (simpler) rules 1. Scalastyle (SBT/Gradle/Maven/Eclipse/IntelliJ) 2. Scalafmt (SBT/Vim/CLI/IntelliJ) [NEW]
  37. 37. ⌚ 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
  38. 38. 4. Scala Levels source
  39. 39. 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
  40. 40. Scala Levels Application Includes A1: Beginner Basic syntax; Simple Closures; Collections; For-expressions; … A2: Intermediate Pattern matching; Trait composition; (Tail) Recursion; … A3: Expert Folds; Streams + other lazy data structures; Actors; …
  41. 41. Scala Levels Library Includes L1: Junior Type parameters; Traits; Lazy vals; Currying; By-name parameters L2: Senior Variance; Existential types; Cake Pattern; Structural types; Extractors; … L3: Expert Early initializers; Abstract types; Implicit definitions; Higher-kinded types; …
  42. 42. source def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That
  43. 43. source
  44. 44. Conclusions
  45. 45. 1. Intermediate Scala works (might be better than Expert Java!) 2. Style and Feature-set can be controlled 3. No Chuck-Norrisness Required source
  46. 46. Thank You

×