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.
Scaling business app 
development with 
Play & Scala 
@PeterHilton 
http://hilton.org.uk/
M A N N I N G 
Covers Play 2 
Peter Hilton 
Erik Bakker 
Francisco Canedo 
FOREWORD BY James Ward 
Play for Scala 
(Mannin...
Business web app 
development
Business applications 
Business applications support things like 
data management, 
process visibility and 
process automa...
Business app development projects 
Development cost is the toughest issue. 
@PeterHilton • 5 
The following is a true stor...
With simplicity in the right places, 
building a web application with the 
Typesafe platform is* easier and 
faster than w...
Case study: 
Happy Melly
robin-berjon / CC BY-SA 2.0
Happy Melly 
‘Happy Melly is a network of businesses 
that self-organize around a purpose: 
creating happy workers.’ 
http...
@PeterHilton • 10
@PeterHilton • 11
Working with an experienced remote 
product owner 
@PeterHilton • 13 
Release early: 
no ‘sprint 0’ - first release on day...
Technical approach 
Play Framework 2.1 (later upgraded to 2.2) 
Scala 2.10 on JDK 1.7 
Slick 1.0 
MySQL 5.6 
Twitter Boots...
@PeterHilton • 15
@PeterHilton • 15
@PeterHilton • 15
/** 
* HTML form mapping for creating and editing. 
*/ 
def organisationForm(implicit request: 
SecuredRequest[_]) = 
Form...
"name" -­‐> nonEmptyText, 
"street1" -­‐> optional(text), 
"street2" -­‐> optional(text), 
"city" -­‐> optional(text), 
"p...
"name" -­‐> nonEmptyText, 
"street1" -­‐> optional(text), 
"street2" -­‐> optional(text), 
"city" -­‐> optional(text), 
"p...
private def validateWebUrl(url: String): Boolean = { 
try { 
val uri = new java.net.URI(url) 
val validScheme = ValidURLSc...
@PeterHilton • 18
private val FacebookDomain = "facebook.com" 
private val LinkedInDomain = "linkedin.com" 
private val GoogleDomain = "goog...
Simplifying front-end development 
Twitter Bootstrap 
No custom CSS or JavaScript* 
Master-detail pages 
(HTML tables, str...
http://cloc.sourceforge.net v 1.58 
-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­...
How to cheat at front-end dev 
We only supported the latest version of 
Google Chrome 
… and the usual pain just went away...
// Code example: Scala Slick database access 
// Nice: select * from LICENSE where id=? 
val query = Query(Licenses).filte...
// Code example: Scala Slick database access 
// Nice: select * from LICENSE where id=? 
val query = Query(Licenses).filte...
Scalariform 
Source code formatter, integrated with sbt 
We liked it so much we set it up to 
reformat code on every compi...
// project/Build.sbt … 
val main = play.Project(appName, appVersion, appDependencies 
resolvers += Resolver.url("sbt-­‐plu...
SecureSocial 
Social network authentication: 
Twitter, Facebook, Google, LinkedIn 
Less effort and better UX than the usua...
DataTables 
HTML tables with client-side filter and sort, 
in this case from server-side HTML tables. 
http://datatables.n...
pegdown & JSoup 
Markdown processing - an easy way to use 
standard HTML forms to edit HTML 
https://github.com/sirthias/p...
Joda Money 
Currency arithmetic and conversion API. 
Money type for an amount with a currency. 
Arithmetic and currency co...
Lessons learned 
You can save a lot of time on front-end 
development if you cheat. 
Development is very fast with two 
ex...
One more thing… 
Halfway through the project, the customer 
decided to open source the application 
https://github.com/hap...
Case study: 
NIIOS
Netherlands Institute for 
Innovative Ocular Surgery (NIIOS) 
Independent eye surgery clinic in 
Rotterdam, the Netherland...
Technical approach 
Play Framework 2.2 
Scala 2.10 on JDK 1.7 
Slick 2.0 
PostgreSQL 9.3 
Twitter Bootstrap 2 
… and jXLS,...
http://cloc.sourceforge.net v 1.58 
-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­...
jXLS 
Parse and generate Excel spreadsheets 
More useful than CSV because it supports 
workbooks with multiple sheets 
@Pe...
// build.sbt 
libraryDependencies ++= Seq( 
jdbc, 
"com.github.tototoshi" %% "slick-­‐joda-­‐mapper" % "1.1.0", 
"com.type...
WebJars 
JavaScript/front-end library management 
Specify dependencies in sbt 
Use Play reverse routing to resolve URLs: 
...
class EmailActor extends Actor { 
override def receive = { 
case m@EmailMessage(to, subject, body) => { 
import com.typesa...
play-plugins-mailer 
Sending e-mail. 
Send asynchronously from an Akka actor. 
@PeterHilton • 50 
It Just Works.
Lessons learned 
Development is fast and predictable if 
you’ve used the same architecture before. 
‘We only support Chrom...
Scaling app dev: 
lessons learned
Scale down 
@PeterHilton • 53 
High-performance technology can 
scale down, as well as up. 
Who knew? 
It turns out that P...
Get Play framework benefits 
Template system allows simple HTML and 
using existing front-end frameworks. 
HTML form valid...
Get Scala benefits 
Strong types capture the domain model 
more explicitly and clearly (DDD FTW!) 
Less verbose code, with...
Scale down the architecture 
No web front-end development 
(no custom JavaScript or CSS) 
Standard action-based MVC 
(serv...
Scaling projects: 
lessons learned
Scaling down the scope 
The first version of a business application 
has a lot in common with a start-up’s MVP 
(although ...
Scaling up productivity 
Throughput. 
Cycle time. 
One developer on the team needs to know 
enough about agile software de...
Scaling down the team 
Scale down the architecture first. 
The team size trade-off is: 
communication overhead (big team) ...
Vertical and horizontal scaling 
In this context, vertical scaling is about 
making each developer more productive. 
Horiz...
@PeterHilton 
http://hilton.org.uk/
Scaling business app development with Play and Scala
Scaling business app development with Play and Scala
Scaling business app development with Play and Scala
Scaling business app development with Play and Scala
Scaling business app development with Play and Scala
Scaling business app development with Play and Scala
Scaling business app development with Play and Scala
Scaling business app development with Play and Scala
Scaling business app development with Play and Scala
Scaling business app development with Play and Scala
Scaling business app development with Play and Scala
Scaling business app development with Play and Scala
Upcoming SlideShare
Loading in …5
×

Scaling business app development with Play and Scala

1,497 views

Published on

Faster web development with Play and Scala

Published in: Technology

Scaling business app development with Play and Scala

  1. 1. Scaling business app development with Play & Scala @PeterHilton http://hilton.org.uk/
  2. 2. M A N N I N G Covers Play 2 Peter Hilton Erik Bakker Francisco Canedo FOREWORD BY James Ward Play for Scala (Manning) Peter Hilton Erik Bakker Francisco Canedo http://bit.ly/playscala2p
  3. 3. Business web app development
  4. 4. Business applications Business applications support things like data management, process visibility and process automation. A special-purpose intranet application may only have 10-100 users. @PeterHilton • 4
  5. 5. Business app development projects Development cost is the toughest issue. @PeterHilton • 5 The following is a true story of how Scala made us awesome. Scaling is usually for runtime performance This is not that talk.
  6. 6. With simplicity in the right places, building a web application with the Typesafe platform is* easier and faster than with PHP * probably @PeterHilton • 6
  7. 7. Case study: Happy Melly
  8. 8. robin-berjon / CC BY-SA 2.0
  9. 9. Happy Melly ‘Happy Melly is a network of businesses that self-organize around a purpose: creating happy workers.’ http://www.happymelly.com/about/ Several member organisations No head office or other central location @PeterHilton • 9
  10. 10. @PeterHilton • 10
  11. 11. @PeterHilton • 11
  12. 12. Working with an experienced remote product owner @PeterHilton • 13 Release early: no ‘sprint 0’ - first release on day one Public Internet test server: Play/Scala web app hosted on Cloudbees Continuous delivery - release per feature Push to master → test server deployment
  13. 13. Technical approach Play Framework 2.1 (later upgraded to 2.2) Scala 2.10 on JDK 1.7 Slick 1.0 MySQL 5.6 Twitter Bootstrap 2 (later upgraded to 3) and some helpful libraries… @PeterHilton • 14
  14. 14. @PeterHilton • 15
  15. 15. @PeterHilton • 15
  16. 16. @PeterHilton • 15
  17. 17. /** * HTML form mapping for creating and editing. */ def organisationForm(implicit request: SecuredRequest[_]) = Form(mapping( "id" -­‐> ignored(Option.empty[Long]), "name" -­‐> nonEmptyText, "street1" -­‐> optional(text), "street2" -­‐> optional(text), "city" -­‐> optional(text), "province" -­‐> optional(text), "postCode" -­‐> optional(text), "country" -­‐> nonEmptyText, "vatNumber" -­‐> optional(text), "registrationNumber" -­‐> optional(text), "category" -­‐> optional(categoryMapping), "webSite" -­‐> optional(webUrl), "blog" -­‐> optional(webUrl), "active" -­‐> ignored(true),
  18. 18. "name" -­‐> nonEmptyText, "street1" -­‐> optional(text), "street2" -­‐> optional(text), "city" -­‐> optional(text), "province" -­‐> optional(text), "postCode" -­‐> optional(text), "country" -­‐> nonEmptyText, "vatNumber" -­‐> optional(text), "registrationNumber" -­‐> optional(text), "category" -­‐> optional(categoryMapping), "webSite" -­‐> optional(webUrl), "blog" -­‐> optional(webUrl), "active" -­‐> ignored(true), "created" -­‐> ignored(DateTime.now()), "createdBy" -­‐> ignored(request.user.fullName), "updated" -­‐> ignored(DateTime.now()), "updatedBy" -­‐> ignored(request.user.fullName) )(Organisation.apply)(Organisation.unapply))
  19. 19. "name" -­‐> nonEmptyText, "street1" -­‐> optional(text), "street2" -­‐> optional(text), "city" -­‐> optional(text), "province" -­‐> optional(text), "postCode" -­‐> optional(text), "country" -­‐> nonEmptyText, "vatNumber" -­‐> optional(text), "registrationNumber" -­‐> optional(text), "category" -­‐> optional(categoryMapping), "webSite" -­‐> optional(webUrl), "blog" -­‐> optional(webUrl), "active" -­‐> ignored(true), "created" -­‐> ignored(DateTime.now()), "createdBy" -­‐> ignored(request.user.fullName), "updated" -­‐> ignored(DateTime.now()), "updatedBy" -­‐> ignored(request.user.fullName) )(Organisation.apply)(Organisation.unapply))
  20. 20. private def validateWebUrl(url: String): Boolean = { try { val uri = new java.net.URI(url) val validScheme = ValidURLSchemes.contains( Option(uri.getScheme).getOrElse("").toLowerCase) val host = Option(uri.getHost).getOrElse("") val validDomain = DomainNameRegex.findFirstIn( host.toLowerCase).isDefined validScheme && validDomain } catch { case _: Throwable ⇒ false } } // Web site URL form mapping. val webUrl = text(maxLength = 1024) verifying ("error.url.web", validateWebUrl(_))
  21. 21. @PeterHilton • 18
  22. 22. private val FacebookDomain = "facebook.com" private val LinkedInDomain = "linkedin.com" private val GoogleDomain = "google.com" private def validateDomain(url: String, domain: String): Boolean = { try { val host = Option(new java.net.URI(url). getHost).getOrElse("").toLowerCase host == domain || host.endsWith("." + domain) } catch { case _: Throwable ⇒ false } } val facebookProfileUrl = webUrl verifying (error = "error.url.profile", validateDomain(_, FacebookDomain))
  23. 23. Simplifying front-end development Twitter Bootstrap No custom CSS or JavaScript* Master-detail pages (HTML tables, straightforward layout) Edit pages (mostly standard Bootstrap form layout) @PeterHilton • 20 * hardly any
  24. 24. http://cloc.sourceforge.net v 1.58 -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ Language files blank comment code -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ Scala 81 1063 2747 4494 HTML 40 321 0 2855 SQL 49 248 14 655 Javascript 5 30 150 284 CoffeeScript 1 15 3 51 XML 1 4 24 14 -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ SUM: 177 1681 2938 8353 -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐
  25. 25. How to cheat at front-end dev We only supported the latest version of Google Chrome … and the usual pain just went away Reminder: intranet application, few users, and an experienced product owner. @PeterHilton • 22
  26. 26. // Code example: Scala Slick database access // Nice: select * from LICENSE where id=? val query = Query(Licenses).filter(_.id === id)
  27. 27. // Code example: Scala Slick database access // Nice: select * from LICENSE where id=? val query = Query(Licenses).filter(_.id === id) // Nasty: select b.NUMBER, b.DATE, p.NAME, o.NAME from BOOKING b // inner join ACCOUNT a on (a.ID=b.FROM_ID) // left outer join PERSON p on (p.ID=a.PERSON_ID) // left outer join ORGANISATION o on (o.ID=a.ORGANISATION_ID) val query = for { entry ← BookingEntries ((fromAccount, fromPerson), fromOrganisation) ← Accounts leftJoin People on (_.personId === _.id) leftJoin Organisations on (_._1.organisationId === _.id) if fromAccount.id === entry.fromId } yield ( entry.bookingNumber, entry.bookingDate, fromPerson.name.?, fromOrganisation.name.?)
  28. 28. Scalariform Source code formatter, integrated with sbt We liked it so much we set it up to reformat code on every compilation and replace ASCII art arrows with ⇒ and ← @PeterHilton • 25 https://github.com/mdr/scalariform
  29. 29. // project/Build.sbt … val main = play.Project(appName, appVersion, appDependencies resolvers += Resolver.url("sbt-­‐plugin-­‐releases", url(" resolvers += Resolver.url("Objectify Play Snapshot Repository resolvers += Resolver.url("Objectify Play Repository", routesImport += "binders._" ).settings( // Reformat code before every compilation :) ScalariformKeys.preferences := FormattingPreferences(). setPreference(SpacesWithinPatternBinders, false). setPreference(PreserveSpaceBeforeArguments, true). setPreference(RewriteArrowSymbols, true) )
  30. 30. SecureSocial Social network authentication: Twitter, Facebook, Google, LinkedIn Less effort and better UX than the usual sign-up, log-in, reset password features @PeterHilton • 28 http://securesocial.ws
  31. 31. DataTables HTML tables with client-side filter and sort, in this case from server-side HTML tables. http://datatables.net DataTables-Bootstrap integrates styling. http://datatables.net/manual/styling/bootstrap @PeterHilton • 30
  32. 32. pegdown & JSoup Markdown processing - an easy way to use standard HTML forms to edit HTML https://github.com/sirthias/pegdown JSoup sanitises the resulting HTML using an HTML whitelist http://jsoup.org @PeterHilton • 32
  33. 33. Joda Money Currency arithmetic and conversion API. Money type for an amount with a currency. Arithmetic and currency conversion, with an explicit rounding policy. @PeterHilton • 34 http://www.joda.org/joda-money/
  34. 34. Lessons learned You can save a lot of time on front-end development if you cheat. Development is very fast with two experienced developers. Slick had a steep learning curve* and some scary queries, but we still liked it. * writing/publishing Slick tutorials helped @PeterHilton • 35
  35. 35. One more thing… Halfway through the project, the customer decided to open source the application https://github.com/happymelly/teller @PeterHilton • 37
  36. 36. Case study: NIIOS
  37. 37. Netherlands Institute for Innovative Ocular Surgery (NIIOS) Independent eye surgery clinic in Rotterdam, the Netherlands. ISO accreditation requires quality management and detailed reporting. Status quo: lots of spreadsheets. @PeterHilton • 39
  38. 38. Technical approach Play Framework 2.2 Scala 2.10 on JDK 1.7 Slick 2.0 PostgreSQL 9.3 Twitter Bootstrap 2 … and jXLS, webjars, play-plugins-mailer @PeterHilton • 44
  39. 39. http://cloc.sourceforge.net v 1.58 -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ Language files blank comment code -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ Scala 55 548 572 2497 HTML 20 179 0 1456 SQL 13 157 30 668 CoffeeScript 6 43 39 133 XML 2 8 6 39 -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ SUM: 96 935 647 4793 -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐
  40. 40. jXLS Parse and generate Excel spreadsheets More useful than CSV because it supports workbooks with multiple sheets @PeterHilton • 46 Simplifying data maintenance with spreadsheet integration
  41. 41. // build.sbt libraryDependencies ++= Seq( jdbc, "com.github.tototoshi" %% "slick-­‐joda-­‐mapper" % "1.1.0", "com.typesafe.slick" %% "slick" % "2.0.2", "com.typesafe.play" %% "play-­‐slick" % "0.6.0.1" , "net.sf.jxls" % "jxls-­‐core" % "1.0.5", "net.sf.jxls" % "jxls-­‐reader" % "1.0.5", "org.postgresql" % "postgresql" % "9.3-­‐1101-­‐jdbc41", "org.webjars" %% "webjars-­‐play" % "2.2.1-­‐2", "org.webjars" % "bootstrap" % "3.1.0", "org.webjars" % "datatables" % "1.10.0", "org.webjars" % "datatables-­‐bootstrap" % "2-­‐20120202-­‐2", "com.typesafe" %% "play-­‐plugins-­‐mailer" % "2.2.0" )
  42. 42. WebJars JavaScript/front-end library management Specify dependencies in sbt Use Play reverse routing to resolve URLs: @routes.WebJarAssets.at( WebJarAssets.locate("jquery.min.js")) @PeterHilton • 48
  43. 43. class EmailActor extends Actor { override def receive = { case m@EmailMessage(to, subject, body) => { import com.typesafe.plugin val mailer: MailerAPI = plugin.use[MailerPlugin].email mailer.setRecipient(to: _*) mailer.setSubject(subject) mailer.setFrom(from) mailer.send(body.trim) } } }
  44. 44. play-plugins-mailer Sending e-mail. Send asynchronously from an Akka actor. @PeterHilton • 50 It Just Works.
  45. 45. Lessons learned Development is fast and predictable if you’ve used the same architecture before. ‘We only support Chrome’ is possible twice. One thing didn’t work: authentication via NTLM challenge-response on Microsoft IIS @PeterHilton • 51
  46. 46. Scaling app dev: lessons learned
  47. 47. Scale down @PeterHilton • 53 High-performance technology can scale down, as well as up. Who knew? It turns out that Play and Scala make simple applications easier to build. Bonus: maintainability and performance
  48. 48. Get Play framework benefits Template system allows simple HTML and using existing front-end frameworks. HTML form validation API results in clear, understandable code. No XML. @PeterHilton • 54
  49. 49. Get Scala benefits Strong types capture the domain model more explicitly and clearly (DDD FTW!) Less verbose code, with immutable types, is easier to debug and maintain. Third-party Java libraries remain essential. @PeterHilton • 55
  50. 50. Scale down the architecture No web front-end development (no custom JavaScript or CSS) Standard action-based MVC (server-side form validation only) Database most familiar to the team (avoid surprises and getting stuck) No reactive programming (would be premature optimisation here) @PeterHilton • 56
  51. 51. Scaling projects: lessons learned
  52. 52. Scaling down the scope The first version of a business application has a lot in common with a start-up’s MVP (although a start-ups usually include front-end dev and branding in ‘minimum viable’) @PeterHilton • 59
  53. 53. Scaling up productivity Throughput. Cycle time. One developer on the team needs to know enough about agile software development to be able to get people using the software before the project gets cancelled. @PeterHilton • 60
  54. 54. Scaling down the team Scale down the architecture first. The team size trade-off is: communication overhead (big team) vs skills gaps (small team) @PeterHilton • 61
  55. 55. Vertical and horizontal scaling In this context, vertical scaling is about making each developer more productive. Horizontal scaling means more developers … at the cost of exponentially increasing overhead. @PeterHilton • 62
  56. 56. @PeterHilton http://hilton.org.uk/

×