Upload
vasil-remeniuk
View
358
Download
1
Embed Size (px)
Citation preview
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.") }}
Implicits
● parameters http://daily-scala.blogspot.com/2010/04/implicit-parameters.html
● conversions and “pimp-my-library” patternhttp://www.codecommit.com/blog/ruby/implicit-conversions-more-powerful-than-
dynamic-typing
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
REST Endpoints: Spray HTTPhttp://spray.io/documentation/1.1-SNAPSHOT/spray-routing/
import spray.routing.SimpleRoutingApp
object Main extends App with SimpleRoutingApp { implicit val system = ActorSystem("my-system")
startServer(interface = "localhost", port = 8080) { path("hello") { get { complete { <h1>Say hello to spray</h1> } } } }}
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]