effective scala (softshake 2013)

47
Effective Scala Mirco Dotta twitter: @mircodotta SoftShake 2013, Geneva

Upload: mircodotta

Post on 10-May-2015

6.453 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: Effective Scala (SoftShake 2013)

Effective Scala

Mirco Dottatwitter: @mircodotta

SoftShake 2013, Geneva

Page 2: Effective Scala (SoftShake 2013)

KEEP IT Simple!

Golden rule?

Page 3: Effective Scala (SoftShake 2013)
Page 4: Effective Scala (SoftShake 2013)

It is not because you

can, that you should

Page 5: Effective Scala (SoftShake 2013)
Page 6: Effective Scala (SoftShake 2013)

Optimize your use of

Scala to solve real world problems without explosions,

broken thumbs or bullet wounds

What’s this talk about?

Page 7: Effective Scala (SoftShake 2013)

Agenda•Style matters

•Mantras

•Collection-foo

•Implicits

Page 8: Effective Scala (SoftShake 2013)

Style matters

Page 9: Effective Scala (SoftShake 2013)

Learn the Scala wayYou know it when you got it

Scala ain’t Javanor Ruby

nor Haskellnor <INSERT known PL>

http://docs.scala-lang.org/style/

Page 10: Effective Scala (SoftShake 2013)

Abstract memberstrait Shape { val edges: Int}

class Triangle extends Shape { override def edges: Int = 3}

Why?

Because this doesn’t compile!

Page 11: Effective Scala (SoftShake 2013)

Abstract members

trait Shape { def edges: Int}

Always use def for abstract members!

Page 12: Effective Scala (SoftShake 2013)

You’ve to overridetrait Worker { def run(): Unit}

abstract class MyWorker extends Worker { override def run(): Unit = //...}

Page 13: Effective Scala (SoftShake 2013)

Don’t leak your types!trait Logger { def log(m: String): Unit}

object Logger { class StdLogger extends Logger { override def log(m: String): Unit = println(m) } def apply = new StdLogger() }

What’s the return type here?

Page 14: Effective Scala (SoftShake 2013)

Hide your secretsobject SauceFactory { def makeSecretSauce(): Sauce = { val ingredients = getMagicIngredients() val formula = getSecretFormula() SauceMaker.prepare(ingredients, formula) } def getMagicIngredients(): Ingredients = //... def getSecretFormula(): Formula = //...}

private!

Page 15: Effective Scala (SoftShake 2013)

Visibility modifiers

public (default)

package private[pkg]protected protected

private private

• Scala has very expressive visibility modifiers

• Access modifiers can be augmented with qualifiers

• nested packages have access to private classes

• Companion object/classes have access to each other private members!

everything you have in java, and much more

Did you know that...

Page 16: Effective Scala (SoftShake 2013)

Don’t blow the stack!

case class Node(value: Int, edges: List[Node]) def bfs(node: Node, pred: Node => Boolean): Option[Node] = { @scala.annotation.tailrec def search(acc: List[Node]): Option[Node] = acc match { case Nil => None case x :: xs => if (pred(x)) Some(x) else search(xs ::: xs.edges) } search(List(node))}

IF YOU THINK IT’S tailrecursive, SAY so!

Page 17: Effective Scala (SoftShake 2013)

String interpolation case class Complex(real: Int, im: Int) { override def toString: String = real + " + " + im + "i"}

case class Complex(real: Int, im: Int) { override def toString: String = s"$real + ${im}i"}

interpolator!

Page 18: Effective Scala (SoftShake 2013)

MantrasMantras

Page 19: Effective Scala (SoftShake 2013)

Use the REPL

Page 20: Effective Scala (SoftShake 2013)

Or the Worksheet ;-)

Page 21: Effective Scala (SoftShake 2013)

Write Expressions, not Statements

Page 22: Effective Scala (SoftShake 2013)

Expressions!

•shorter

•simpler

•Composable!

Page 23: Effective Scala (SoftShake 2013)

def home(): HttpPage = { var page: HttpPage = null try page = prepareHttpPage() catch { case _: TimeoutEx => page = TimeoutPage case _: Exception => page = NoPage } return page}

def home(): HttpPage = try prepareHttpPage() catch { case _: TimeoutEx => TimeoutPage case _: Exception => NoPage }

Page 24: Effective Scala (SoftShake 2013)

Expressions compose!def home(): HttpPage = try prepareHttpPage() catch { case _: TimeoutEx => TimeoutPage case _: Exception => NoPage }

Try..catch isan expression

This is a PartialFunction[Throwable,HttpPage]

def home(): HttpPage = try prepareHttpPage() catch timeoutCatch orElse noPageCatch

def timeoutCatch = { case _: TimeoutEx => TimeoutPage}def noPageCatch = { case _: Exception => NoPage} compose

!

Page 25: Effective Scala (SoftShake 2013)

Don’t use null

Page 26: Effective Scala (SoftShake 2013)

null is a disease

•nullcheks will spread

•code is brittle

•NPE will still happen

•assertions won’t help

Page 27: Effective Scala (SoftShake 2013)

Forget null, use Option

•no more “it may be null”

•type-safe

•documentation

Page 28: Effective Scala (SoftShake 2013)

def authenticate(session: HttpSession, username: Option[String], password: Option[String]) = for { user <- username pass <- password if canAuthenticate(user,pass) privileges <- privilegesFor(user) } yield inject(session, privileges)

Page 29: Effective Scala (SoftShake 2013)

But don’t overuse Optionsometime a null-object can be

a much better fit

def home(): HttpPage = try prepareHttpPage() catch { case _: TimeoutEx => TimeoutPage case _: Exception => NoPage }

Null Object!

Page 30: Effective Scala (SoftShake 2013)

Stay immutable

Page 31: Effective Scala (SoftShake 2013)

Immutability

•Simplifies reasoning

•simplifies reasoning

•simplifies reasoning

3 reasons why it matters?

Page 32: Effective Scala (SoftShake 2013)

ImmutabilityAllows co/contra variance

String[] a = {""};Object[] b = a;b[0] = 1;String value = a[0];

mutability

+ variance

----------------

Troubles

Java

java.lang.ArrayStoreException

Page 33: Effective Scala (SoftShake 2013)

Immutability

•correct equals & hashcode!

• it also simplifies reasoning about concurrency

•thread-safe by design

Page 34: Effective Scala (SoftShake 2013)

Immutability

•Mutability is still ok, but keep it in local scopes

•api methods should return immutable objects

Page 35: Effective Scala (SoftShake 2013)

program to an interface, not an implementation.

Do you want faster Scala compilation?

Page 36: Effective Scala (SoftShake 2013)

Collection-foo

Collection-foo

Page 37: Effective Scala (SoftShake 2013)

http://www.scala-lang.org/docu/files/collections-api/collections.html

Page 38: Effective Scala (SoftShake 2013)

Learn the API !=, ##, ++, ++:, +:, /:, /:\, :+, ::, :::, :\, <init>, ==, addString, aggregate, andThen, apply, applyOrElse, asInstanceOf, canEqual, collect, collectFirst, combinations, companion, compose, contains, containsSlice, copyToArray, copyToBuffer, corresponds, count, diff, distinct, drop, dropRight, dropWhile, endsWith, eq, equals, exists, filter, filterNot, find, flatMap, flatten, fold, foldLeft, foldRight, forall, foreach, genericBuilder, getClass, groupBy, grouped, hasDefiniteSize, hashCode, head, headOption, indexOf, indexOfSlice, indexWhere, indices, init, inits, intersect, isDefinedAt, isEmpty, isInstanceOf, isTraversableAgain, iterator, last, lastIndexOf, lastIndexOfSlice, lastIndexWhere, lastOption, length, lengthCompare, lift, map, mapConserve, max, maxBy, min, minBy, mkString, ne, nonEmpty, notify, notifyAll, orElse, padTo, par, partition, patch, permutations, prefixLength, product, productArity, productElement, productIterator, productPrefix, reduce, reduceLeft, reduceLeftOption, reduceOption, reduceRight, reduceRightOption, removeDuplicates, repr, reverse, reverseIterator, reverseMap, reverse_:::, runWith, sameElements, scan, scanLeft, scanRight, segmentLength, seq, size, slice, sliding, sortBy, sortWith, sorted, span, splitAt, startsWith, stringPrefix, sum, synchronized, tail, tails, take, takeRight, takeWhile, to, toArray, toBuffer, toIndexedSeq, toIterable, toIterator, toList, toMap, toSeq, toSet, toStream, toString, toTraversable, toVector, transpose, union, unzip, unzip3, updated, view, wait, withFilter, zip, zipAll, zipWithIndex

Page 39: Effective Scala (SoftShake 2013)

Know when to breakOutdef adultFriends(p: Person): Array[Person] = { val adults = // <- of type List for { friend <- p.friends // <- of type List if friend.age >= 18 } yield friend adults.toArray}

def adultFriends(p: Person): Array[Person] = (for { friend <- p.friends if friend.age >= 18 } yield friend)(collection.breakOut)

can we avoid the 2nd iteration?

Page 40: Effective Scala (SoftShake 2013)

Common pitfalldef getUsers: Seq[User]

Good question!

mutable or immutable?

import scala.collection.immutabledef getUsers: immutable.Seq[User]remedy

Page 41: Effective Scala (SoftShake 2013)

Implicits

Page 42: Effective Scala (SoftShake 2013)

Limit the scope of implicits

Page 43: Effective Scala (SoftShake 2013)

Implicit Resolution• implicits in the local scope

• Implicits defined in current scope (1)

• explicit imports (2)

• wildcard imports (3)

• parts of A type

• companion object of the type (and inherited types)

• companion objects of type arguments of the type

• outer objects for nested types

http://www.scala-lang.org/docu/files/ScalaReference.pdf

Page 44: Effective Scala (SoftShake 2013)

Implicit Scope (Parts)trait Logger { def log(m: String): Unit}

object Logger { implicit object StdLogger extends Logger { override def log(m: String): Unit = println(m) } def log(m: String)(implicit l: Logger) = l.log(m)}

Logger.log("Hello")

Page 45: Effective Scala (SoftShake 2013)

Looking ahead

Page 46: Effective Scala (SoftShake 2013)

Scala In DepthJoshua Suereth

Level up!

http://www.manning.com/suereth/

Page 47: Effective Scala (SoftShake 2013)

Effective Scala

Mirco Dottatwitter: @mircodotta

Thanks to @heathermiller for the presentation style