Your SlideShare is downloading. ×
0
Scala in Goozy       Alexey Zlobin, e-Legion       Alexey.Zlobin@gmail.com       @CheatEx
Index1. Goozy overview2. Scalas place3. Lift4. Cake pattern in scale5. Scalaz and other fancy stuff6. Summary
What is Goozy?A social network built aroundthe concept of sticky note ● A note could be left   anywhere in the Web. ● It i...
Top-level architecture
Scalas placeAPI serverMain functions: ● Storage access ● Background tasks (feed writing) ● Email sending ● Text indexing
Why scala?● Fast● Сoncise● Expressive● Advanced OO● Some functional stuff   ○ Simple concurrency● All Java legacy  available
The team● 2 persons● Strong Java background● Fancy about technologies● Love to try new things
Lift       Utilized features:        ● REST        ● JSON serialisation       Thats it...
Lift: issuesLocalisation performance ● Hand-made localisation on standard resource bundles   gave 4 times throughput impro...
Goozy API logical structureApplication is composedfrom three layers.Each layer consists fromseveral similarcomponents. Lik...
Conceptual problems● Components of each level depend from each other● Components most likely have several dependencies  fr...
The solution: cake pattern● Each logically closed piece  of functionality is  represented as component● Dependencies are  ...
Cake pattern: consequences+ All top-level architecture   - Long dependency listsis expressed in one less         ● Poor de...
scalaz.Validation                    One sweet morning I sent a                    link to the colleague...               ...
Initial solution: domain exceptionsclass GoozzyException(   val message: String) extendsException(message)case class UserN...
Error handling: own error typeabstract class Error(  val httpCode: Int,  val code: String)abstract class PermissionError( ...
Validations and exceptionsProblem: exceptions are hereSolution: catchem and convert!
Validations and exceptions1. Define the "converter"2. Write some utilities to make them more accessible
One more error for whatever happencase class ExceptionalError(   @transient exception: Throwable) extendsInternalError
The converterFunction is a perfect abstraction!val dispatchException: Function[   Throwable,   Error] = {   case UserNotFo...
Useful utils: generictype GzVal[+OUT] = Validation[Error, OUT]def safeVal[T]: Catch[GzVal[T]] =  handling(classOf[Throwabl...
Useful utils: specificJust a trivial code which parses strings, extractsvalues from mongo objects, etc.See my blog for det...
Validation: the good thingSome code was pretty:for {   data <- getData(recordId)   userData <- getUserData(userId)   permi...
Conversion: the problemBut some other code was...
Not so prettydef readFields(rec: DBObject, ...): GzVal[Fields] = {  val deletedBy =   for (userId <- get[ObjectId](note, "...
Improved solution1. Dont play haskell2. Play java3. ...when it is easier
Error handling: big picture
Validation: pros and cons+ Comprehensible error      - Monads and Applicativesaggregation and reporting   cause massive br...
Lessons1. Always prefer simple tools2. Options and Eithers (Validations): they really work    ○ It is possible to live wit...
References1. http://www.assembla.   com/spaces/liftweb/wiki/REST_Web_Services - REST   support in Lift2. http://jonasboner...
Upcoming SlideShare
Loading in...5
×

"Scala in Goozy", Alexey Zlobin

1,645

Published on

Talk in Scala in Goozy (http://goozy.com/), by Alexey @CheatEx Zlobin, at scalaby#8

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,645
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
3
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of ""Scala in Goozy", Alexey Zlobin "

  1. 1. Scala in Goozy Alexey Zlobin, e-Legion Alexey.Zlobin@gmail.com @CheatEx
  2. 2. Index1. Goozy overview2. Scalas place3. Lift4. Cake pattern in scale5. Scalaz and other fancy stuff6. Summary
  3. 3. What is Goozy?A social network built aroundthe concept of sticky note ● A note could be left anywhere in the Web. ● It is associated with particular page element.Central UI concept: usersrelated feed with all new notesand comments
  4. 4. Top-level architecture
  5. 5. Scalas placeAPI serverMain functions: ● Storage access ● Background tasks (feed writing) ● Email sending ● Text indexing
  6. 6. Why scala?● Fast● Сoncise● Expressive● Advanced OO● Some functional stuff ○ Simple concurrency● All Java legacy available
  7. 7. The team● 2 persons● Strong Java background● Fancy about technologies● Love to try new things
  8. 8. Lift Utilized features: ● REST ● JSON serialisation Thats it...
  9. 9. Lift: issuesLocalisation performance ● Hand-made localisation on standard resource bundles gave 4 times throughput improvement.Very memory-consuming JSON serialisation. ● Not so efficient PrettyPrinter is used ● Functional-styled string escapingPoor code style ● Extremely long map-match-if hierarchies ● Mutable, difficult to debug LiftRules design
  10. 10. Goozy API logical structureApplication is composedfrom three layers.Each layer consists fromseveral similarcomponents. LikeUserController,UserService, etc.
  11. 11. Conceptual problems● Components of each level depend from each other● Components most likely have several dependencies from the previous level● A lot of common stuff inside a level ○ Every storage needs a DB connection ○ Every service needs an entire storage system and access to text indexes ○ Etc...
  12. 12. The solution: cake pattern● Each logically closed piece of functionality is represented as component● Dependencies are expressed as self-types● Common features expressed as mix-ins● Common combinations of functionality are expressed as mix-ins of several components
  13. 13. Cake pattern: consequences+ All top-level architecture - Long dependency listsis expressed in one less ● Poor design?than 100 LOC file - Implicit dependency on mix-+ Compile-time in order (linearisation strikesdependency checks back) ● Prefer def and lazy+ The biggest file isaround 1000 LOC - A bit unclear how to deal with several dependencies of the same type but different runtime implementation
  14. 14. scalaz.Validation One sweet morning I sent a link to the colleague... On the next morning we had a new dependency and totally refactored request parameters analysis. Now everything is validated.
  15. 15. Initial solution: domain exceptionsclass GoozzyException( val message: String) extendsException(message)case class UserNotFound( userId: String) extendsGoozzyException( "user " + userId + " not found")
  16. 16. Error handling: own error typeabstract class Error( val httpCode: Int, val code: String)abstract class PermissionError( code: String) extendsValidationError(403, code)case class Banned( userId: String, groupId: String) extendsPermissionError("BANNED")
  17. 17. Validations and exceptionsProblem: exceptions are hereSolution: catchem and convert!
  18. 18. Validations and exceptions1. Define the "converter"2. Write some utilities to make them more accessible
  19. 19. One more error for whatever happencase class ExceptionalError( @transient exception: Throwable) extendsInternalError
  20. 20. The converterFunction is a perfect abstraction!val dispatchException: Function[ Throwable, Error] = { case UserNotFound(name) => MissedEntity(name, "user") ... //dont remove it!!! case t => ExceptionalError(t) }
  21. 21. Useful utils: generictype GzVal[+OUT] = Validation[Error, OUT]def safeVal[T]: Catch[GzVal[T]] = handling(classOf[Throwable]) by { e => dispatchException(e).fail }def safe[T](block: => T): GzVal[T] = safeVal( block.success )def editData(up: Edit): GzVal[Data] = safeVal { //all the dangerous stuff here }
  22. 22. Useful utils: specificJust a trivial code which parses strings, extractsvalues from mongo objects, etc.See my blog for details...
  23. 23. Validation: the good thingSome code was pretty:for { data <- getData(recordId) userData <- getUserData(userId) permission <- checkPermission(data, userData) newData <- updateData(data)} yield { //all dirty hacks there}
  24. 24. Conversion: the problemBut some other code was...
  25. 25. Not so prettydef readFields(rec: DBObject, ...): GzVal[Fields] = { val deletedBy = for (userId <- get[ObjectId](note, "deleted_by"); user <- getUserData(userId).toSuccess(MissedEntity(...))) yield user for { id <- get[String](rec, "_id") content <- get[String](rec, "content") updated <- asValidOption(get[DateTime](rec, "upd")) //twelve more user <- getUserById(userId, currentUserId map (new ObjectId(_))) .toSuccess( MissedEntity(userId.toString, "user"): ValidationError) } yield DataRecord(/*you wont see it*/)}
  26. 26. Improved solution1. Dont play haskell2. Play java3. ...when it is easier
  27. 27. Error handling: big picture
  28. 28. Validation: pros and cons+ Comprehensible error - Monads and Applicativesaggregation and reporting cause massive brain damage+ The only imaginable wayto deal with 20+ request - Complicated error reportsparameters with 2-3 from the compilerconstraints on each - You cant just ignore+ Unified approach to possibility of runtimerequest validation and exceptionruntime error handling+ Type-level check forcorrect error handling
  29. 29. Lessons1. Always prefer simple tools2. Options and Eithers (Validations): they really work ○ It is possible to live with both exceptions and eithers ○ Performance consequences are not clear ○ Some times I had to use things far behind my understanding (sequence, traverse)3. Server-side testing is difficult ○ Testing approach should be established before any code is written
  30. 30. References1. http://www.assembla. com/spaces/liftweb/wiki/REST_Web_Services - REST support in Lift2. http://jonasboner.com/2008/10/06/real-world-scala- dependency-injection-di.html - complete cake pattern intro3. https://gist.github.com/970717 - easy Validation example4. http://www.scala-lang. org/api/current/scala/util/control/Exception$.html - built-in DSL for exception handling
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×