13
Globus Scala Laboratory. Iteration #2

Scala laboratory: Globus. iteration #2

Embed Size (px)

Citation preview

GlobusScala Laboratory. Iteration #2

Goals of the iteration

● Refactor your code to master all of the concepts below:○ options○ Try / Either / Validation instead of exception○ collections○ patterns (pimp-my-library, type-class)

● Add persistence and REST-endpoint

Monads 101: collections● using map, flatMap, filter etc.

http://www.brunton-spall.co.uk/post/2011/12/02/map-map-and-flatmap-in-scala● Martin Odersky recommends using for-comprehensions as more readable

val opt1: Option[T] = getOpt() val opt2: Option[T] = getOpt() for { val1 <- opt1 val2 <- opt2 } yield useOpts(val1, val2)

Monads 101: Option● there should be no nulls, checks for nulls and NPE in

Scala● when something may not be defined at some point of time, use Option[T]● Option’s are composable: map / flatMap / for-comprehensions● List(Some(“1”), None).flatMap(_.toInt) is List(1) ● null might only occur, when you interop with Java

○ Option(null) is None

Monads 101: Try / Eitherhttp://danielwestheide.com/blog/2012/12/26/the-neophytes-guide-to-scala-part-6-error-handling-with-try.html

def loadByLogin(login: String): User = { this.query(_.login == login) match { case head::Nil => head case Nil => throw new Errors.EntityNotFoundError("User $login does not exist.") }}

def loadByLogin(login: String): Either[String,User] = { this.query(_.login == login) match { case head::Nil => Right(head) case Nil => Left("User $login does not exist.") }}

Type Systemhttp://www.slideshare.net/remeniuk/ss-13598474

● type bounds: http://docs.scala-lang.org/tutorials/tour/upper-type-bounds.html● view bounds: http://stackoverflow.com/a/4467012/354067● context bounds (“type class” pattern): http://stackoverflow.com/a/4467012/354067

Patterns. Cakehttp://jonasboner.com/2008/10/06/real-world-scala-dependency-injection-di/

trait UserRepositoryComponent { def initializeUser(user: User): User}

trait AuthenticationServiceComponent { this: UserRepositoryComponent =>

def foo = initializeUser(...)}

Patterns. Type-classhttp://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html

trait DAO[T] { def findAll: Seq[T] }

implicit object UserDAO extends DAO[User]{ def findAll = ... }

object Cache { def init[T : DAO]: Seq[T] = ... implicitly[DAO[T]].findAll ... }

Testing: Scalatest, ScalaCheck, Mockitohttp://www.slideshare.net/remeniuk/testing-in-scala-adform-research

class IntegrationSpec extends Specification { "Application" should { "work from within a browser" in new WithBrowser { browser.goTo("http://localhost:" + port) browser.pageSource must contain("Login") } }}

Persistence: MongoDB● Casbah, de facto standard for working with Mongo from Scala

http://mongodb.github.io/casbah/tutorial.html ● offers nice DSL similar to native query language in Mongo

JSON serialization● play json: https://www.playframework.com/documentation/2.1.1/ScalaJsonInception ● straightforward serialization of case classes:

import play.api.libs.json._

implicit val personWrites = Json.format[Person]