SlideShare a Scribd company logo
1 of 68
Download to read offline
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 
(Manning) 
Peter Hilton 
Erik Bakker 
Francisco Canedo 
http://bit.ly/playscala2p
Business web app 
development
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
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.
With simplicity in the right places, 
building a web application with the 
Typesafe platform is* easier and 
faster than with PHP 
* probably 
@PeterHilton • 6
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://www.happymelly.com/about/ 
Several member organisations 
No head office or other central location 
@PeterHilton • 9
@PeterHilton • 10
@PeterHilton • 11
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
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
@PeterHilton • 15
@PeterHilton • 15
@PeterHilton • 15
/** 
* 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),
"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))
"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))
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(_))
@PeterHilton • 18
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))
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
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 
-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐
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
// Code example: Scala Slick database access 
// Nice: select * from LICENSE where id=? 
val query = Query(Licenses).filter(_.id === id)
// 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.?)
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
// 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) 
)
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
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
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
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/
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
One more thing… 
Halfway through the project, the customer 
decided to open source the application 
https://github.com/happymelly/teller 
@PeterHilton • 37
Case study: 
NIIOS
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
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
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 
-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐
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
// 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" 
)
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
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) 
} 
} 
}
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 Chrome’ is possible twice. 
One thing didn’t work: authentication via 
NTLM challenge-response on Microsoft IIS 
@PeterHilton • 51
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 Play and Scala make 
simple applications easier to build. 
Bonus: maintainability and performance
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
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
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
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 a start-ups usually include front-end 
dev and branding in ‘minimum viable’) 
@PeterHilton • 59
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
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
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
@PeterHilton 
http://hilton.org.uk/

More Related Content

What's hot

Html 5 in a big nutshell
Html 5 in a big nutshellHtml 5 in a big nutshell
Html 5 in a big nutshellLennart Schoors
 
.NET Recommended Resources
.NET Recommended Resources.NET Recommended Resources
.NET Recommended ResourcesGreg Sohl
 
API Workshop: Deep dive into REST APIs
API Workshop: Deep dive into REST APIsAPI Workshop: Deep dive into REST APIs
API Workshop: Deep dive into REST APIsTom Johnson
 
Writing code samples for API/SDK documentation
Writing code samples for API/SDK documentationWriting code samples for API/SDK documentation
Writing code samples for API/SDK documentationTom Johnson
 
API Documentation -- Presentation to East Bay STC Chapter
API Documentation -- Presentation to East Bay STC ChapterAPI Documentation -- Presentation to East Bay STC Chapter
API Documentation -- Presentation to East Bay STC ChapterTom Johnson
 
<img src="../i/r_14.png" />
<img src="../i/r_14.png" /><img src="../i/r_14.png" />
<img src="../i/r_14.png" />tutorialsruby
 
C# Security Testing and Debugging
C# Security Testing and DebuggingC# Security Testing and Debugging
C# Security Testing and DebuggingRich Helton
 
EE Squashed
EE SquashedEE Squashed
EE Squashedmarkhuot
 
How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016
How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016
How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016Codemotion
 
How To Become A Good C# Programmer
How To Become A Good C# ProgrammerHow To Become A Good C# Programmer
How To Become A Good C# ProgrammerLearnItFirst.com
 
Elixir in a nutshell - Ecosystem (session 1)
Elixir in a nutshell - Ecosystem (session 1)Elixir in a nutshell - Ecosystem (session 1)
Elixir in a nutshell - Ecosystem (session 1)Héla Ben Khalfallah
 
Bca sem 5 c# practical
Bca sem 5 c# practicalBca sem 5 c# practical
Bca sem 5 c# practicalHitesh Patel
 
Anant kochhar _revealing_the_secrets - ClubHack2009
Anant kochhar _revealing_the_secrets - ClubHack2009Anant kochhar _revealing_the_secrets - ClubHack2009
Anant kochhar _revealing_the_secrets - ClubHack2009ClubHack
 
I pad uicatalog_lesson02
I pad uicatalog_lesson02I pad uicatalog_lesson02
I pad uicatalog_lesson02Rich Helton
 
Migrating a large scale banking app to compose
Migrating a large scale banking app to composeMigrating a large scale banking app to compose
Migrating a large scale banking app to composeFatih Giris
 
Beyond the Basics, Debugging with Firebug and Web Inspector
Beyond the Basics, Debugging with Firebug and Web InspectorBeyond the Basics, Debugging with Firebug and Web Inspector
Beyond the Basics, Debugging with Firebug and Web InspectorSteven Roussey
 
Unbreaking Your Django Application
Unbreaking Your Django ApplicationUnbreaking Your Django Application
Unbreaking Your Django ApplicationOSCON Byrum
 

What's hot (19)

Html 5 in a big nutshell
Html 5 in a big nutshellHtml 5 in a big nutshell
Html 5 in a big nutshell
 
.NET Recommended Resources
.NET Recommended Resources.NET Recommended Resources
.NET Recommended Resources
 
API Workshop: Deep dive into REST APIs
API Workshop: Deep dive into REST APIsAPI Workshop: Deep dive into REST APIs
API Workshop: Deep dive into REST APIs
 
Writing code samples for API/SDK documentation
Writing code samples for API/SDK documentationWriting code samples for API/SDK documentation
Writing code samples for API/SDK documentation
 
API Documentation -- Presentation to East Bay STC Chapter
API Documentation -- Presentation to East Bay STC ChapterAPI Documentation -- Presentation to East Bay STC Chapter
API Documentation -- Presentation to East Bay STC Chapter
 
Take a Stroll in the Bazaar
Take a Stroll in the BazaarTake a Stroll in the Bazaar
Take a Stroll in the Bazaar
 
<img src="../i/r_14.png" />
<img src="../i/r_14.png" /><img src="../i/r_14.png" />
<img src="../i/r_14.png" />
 
C# Security Testing and Debugging
C# Security Testing and DebuggingC# Security Testing and Debugging
C# Security Testing and Debugging
 
EE Squashed
EE SquashedEE Squashed
EE Squashed
 
How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016
How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016
How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016
 
How To Become A Good C# Programmer
How To Become A Good C# ProgrammerHow To Become A Good C# Programmer
How To Become A Good C# Programmer
 
Elixir in a nutshell - Ecosystem (session 1)
Elixir in a nutshell - Ecosystem (session 1)Elixir in a nutshell - Ecosystem (session 1)
Elixir in a nutshell - Ecosystem (session 1)
 
Bca sem 5 c# practical
Bca sem 5 c# practicalBca sem 5 c# practical
Bca sem 5 c# practical
 
Anant kochhar _revealing_the_secrets - ClubHack2009
Anant kochhar _revealing_the_secrets - ClubHack2009Anant kochhar _revealing_the_secrets - ClubHack2009
Anant kochhar _revealing_the_secrets - ClubHack2009
 
I pad uicatalog_lesson02
I pad uicatalog_lesson02I pad uicatalog_lesson02
I pad uicatalog_lesson02
 
Laravel 5 and SOLID
Laravel 5 and SOLIDLaravel 5 and SOLID
Laravel 5 and SOLID
 
Migrating a large scale banking app to compose
Migrating a large scale banking app to composeMigrating a large scale banking app to compose
Migrating a large scale banking app to compose
 
Beyond the Basics, Debugging with Firebug and Web Inspector
Beyond the Basics, Debugging with Firebug and Web InspectorBeyond the Basics, Debugging with Firebug and Web Inspector
Beyond the Basics, Debugging with Firebug and Web Inspector
 
Unbreaking Your Django Application
Unbreaking Your Django ApplicationUnbreaking Your Django Application
Unbreaking Your Django Application
 

Similar to Scaling business app development with Play and Scala

From Knowledge Graphs to AI-powered SEO: Using taxonomies, schemas and knowle...
From Knowledge Graphs to AI-powered SEO: Using taxonomies, schemas and knowle...From Knowledge Graphs to AI-powered SEO: Using taxonomies, schemas and knowle...
From Knowledge Graphs to AI-powered SEO: Using taxonomies, schemas and knowle...Connected Data World
 
jsSaturday - PhoneGap and jQuery Mobile for SharePoint 2013
jsSaturday - PhoneGap and jQuery Mobile for SharePoint 2013jsSaturday - PhoneGap and jQuery Mobile for SharePoint 2013
jsSaturday - PhoneGap and jQuery Mobile for SharePoint 2013Kiril Iliev
 
SPTechCon DevDays - SharePoint & jQuery
SPTechCon DevDays - SharePoint & jQuerySPTechCon DevDays - SharePoint & jQuery
SPTechCon DevDays - SharePoint & jQueryMark Rackley
 
Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)Python Ireland
 
PHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsPHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsMichelangelo van Dam
 
Data Mining Open Ap Is
Data Mining Open Ap IsData Mining Open Ap Is
Data Mining Open Ap Isoscon2007
 
Java/Scala Lab: Борис Трофимов - Обжигающая Big Data.
Java/Scala Lab: Борис Трофимов - Обжигающая Big Data.Java/Scala Lab: Борис Трофимов - Обжигающая Big Data.
Java/Scala Lab: Борис Трофимов - Обжигающая Big Data.GeeksLab Odessa
 
Coding for marketers
Coding for marketersCoding for marketers
Coding for marketersRobin Lord
 
SPTechCon Boston 2015 - Utilizing jQuery in SharePoint
SPTechCon Boston 2015 - Utilizing jQuery in SharePointSPTechCon Boston 2015 - Utilizing jQuery in SharePoint
SPTechCon Boston 2015 - Utilizing jQuery in SharePointMark Rackley
 
SEO dataLayer 2: Entity Wars
SEO dataLayer 2: Entity WarsSEO dataLayer 2: Entity Wars
SEO dataLayer 2: Entity WarsPhil Pearce
 
Building Awesome API with Spring
Building Awesome API with SpringBuilding Awesome API with Spring
Building Awesome API with SpringVladimir Tsukur
 
(Updated) SharePoint & jQuery Guide
(Updated) SharePoint & jQuery Guide(Updated) SharePoint & jQuery Guide
(Updated) SharePoint & jQuery GuideMark Rackley
 
.NET Fest 2017. Михаил Щербаков. Механизмы предотвращения атак в ASP.NET Core
.NET Fest 2017. Михаил Щербаков. Механизмы предотвращения атак в ASP.NET Core.NET Fest 2017. Михаил Щербаков. Механизмы предотвращения атак в ASP.NET Core
.NET Fest 2017. Михаил Щербаков. Механизмы предотвращения атак в ASP.NET CoreNETFest
 
Evolving your Data Access with MongoDB Stitch
Evolving your Data Access with MongoDB StitchEvolving your Data Access with MongoDB Stitch
Evolving your Data Access with MongoDB StitchMongoDB
 
The SharePoint & jQuery Guide - Updated 1/14/14
The SharePoint & jQuery Guide - Updated 1/14/14The SharePoint & jQuery Guide - Updated 1/14/14
The SharePoint & jQuery Guide - Updated 1/14/14Mark Rackley
 
MongoDB at Giant Eagle by David Williams
MongoDB at Giant Eagle by David WilliamsMongoDB at Giant Eagle by David Williams
MongoDB at Giant Eagle by David WilliamsMongoDB
 
The SharePoint & jQuery Guide
The SharePoint & jQuery GuideThe SharePoint & jQuery Guide
The SharePoint & jQuery GuideMark Rackley
 
The SharePoint and jQuery Guide by Mark Rackley - SPTechCon
The SharePoint and jQuery Guide by Mark Rackley - SPTechConThe SharePoint and jQuery Guide by Mark Rackley - SPTechCon
The SharePoint and jQuery Guide by Mark Rackley - SPTechConSPTechCon
 
CloudML talk at DevFest Madurai 2016
CloudML talk at DevFest Madurai 2016 CloudML talk at DevFest Madurai 2016
CloudML talk at DevFest Madurai 2016 Karthik Padmanabhan
 
Building Social Enterprise with Ruby and Salesforce
Building Social Enterprise with Ruby and SalesforceBuilding Social Enterprise with Ruby and Salesforce
Building Social Enterprise with Ruby and SalesforceRaymond Gao
 

Similar to Scaling business app development with Play and Scala (20)

From Knowledge Graphs to AI-powered SEO: Using taxonomies, schemas and knowle...
From Knowledge Graphs to AI-powered SEO: Using taxonomies, schemas and knowle...From Knowledge Graphs to AI-powered SEO: Using taxonomies, schemas and knowle...
From Knowledge Graphs to AI-powered SEO: Using taxonomies, schemas and knowle...
 
jsSaturday - PhoneGap and jQuery Mobile for SharePoint 2013
jsSaturday - PhoneGap and jQuery Mobile for SharePoint 2013jsSaturday - PhoneGap and jQuery Mobile for SharePoint 2013
jsSaturday - PhoneGap and jQuery Mobile for SharePoint 2013
 
SPTechCon DevDays - SharePoint & jQuery
SPTechCon DevDays - SharePoint & jQuerySPTechCon DevDays - SharePoint & jQuery
SPTechCon DevDays - SharePoint & jQuery
 
Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)
 
PHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsPHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the tests
 
Data Mining Open Ap Is
Data Mining Open Ap IsData Mining Open Ap Is
Data Mining Open Ap Is
 
Java/Scala Lab: Борис Трофимов - Обжигающая Big Data.
Java/Scala Lab: Борис Трофимов - Обжигающая Big Data.Java/Scala Lab: Борис Трофимов - Обжигающая Big Data.
Java/Scala Lab: Борис Трофимов - Обжигающая Big Data.
 
Coding for marketers
Coding for marketersCoding for marketers
Coding for marketers
 
SPTechCon Boston 2015 - Utilizing jQuery in SharePoint
SPTechCon Boston 2015 - Utilizing jQuery in SharePointSPTechCon Boston 2015 - Utilizing jQuery in SharePoint
SPTechCon Boston 2015 - Utilizing jQuery in SharePoint
 
SEO dataLayer 2: Entity Wars
SEO dataLayer 2: Entity WarsSEO dataLayer 2: Entity Wars
SEO dataLayer 2: Entity Wars
 
Building Awesome API with Spring
Building Awesome API with SpringBuilding Awesome API with Spring
Building Awesome API with Spring
 
(Updated) SharePoint & jQuery Guide
(Updated) SharePoint & jQuery Guide(Updated) SharePoint & jQuery Guide
(Updated) SharePoint & jQuery Guide
 
.NET Fest 2017. Михаил Щербаков. Механизмы предотвращения атак в ASP.NET Core
.NET Fest 2017. Михаил Щербаков. Механизмы предотвращения атак в ASP.NET Core.NET Fest 2017. Михаил Щербаков. Механизмы предотвращения атак в ASP.NET Core
.NET Fest 2017. Михаил Щербаков. Механизмы предотвращения атак в ASP.NET Core
 
Evolving your Data Access with MongoDB Stitch
Evolving your Data Access with MongoDB StitchEvolving your Data Access with MongoDB Stitch
Evolving your Data Access with MongoDB Stitch
 
The SharePoint & jQuery Guide - Updated 1/14/14
The SharePoint & jQuery Guide - Updated 1/14/14The SharePoint & jQuery Guide - Updated 1/14/14
The SharePoint & jQuery Guide - Updated 1/14/14
 
MongoDB at Giant Eagle by David Williams
MongoDB at Giant Eagle by David WilliamsMongoDB at Giant Eagle by David Williams
MongoDB at Giant Eagle by David Williams
 
The SharePoint & jQuery Guide
The SharePoint & jQuery GuideThe SharePoint & jQuery Guide
The SharePoint & jQuery Guide
 
The SharePoint and jQuery Guide by Mark Rackley - SPTechCon
The SharePoint and jQuery Guide by Mark Rackley - SPTechConThe SharePoint and jQuery Guide by Mark Rackley - SPTechCon
The SharePoint and jQuery Guide by Mark Rackley - SPTechCon
 
CloudML talk at DevFest Madurai 2016
CloudML talk at DevFest Madurai 2016 CloudML talk at DevFest Madurai 2016
CloudML talk at DevFest Madurai 2016
 
Building Social Enterprise with Ruby and Salesforce
Building Social Enterprise with Ruby and SalesforceBuilding Social Enterprise with Ruby and Salesforce
Building Social Enterprise with Ruby and Salesforce
 

More from Peter Hilton

Naming guidelines for professional programmers
Naming guidelines for professional programmersNaming guidelines for professional programmers
Naming guidelines for professional programmersPeter Hilton
 
E-Prime: English for scientific writing
E-Prime: English for scientific writing E-Prime: English for scientific writing
E-Prime: English for scientific writing Peter Hilton
 
How to write maintainable code
How to write maintainable codeHow to write maintainable code
How to write maintainable codePeter Hilton
 
Documentation avoidance for developers
Documentation avoidance for developersDocumentation avoidance for developers
Documentation avoidance for developersPeter Hilton
 
Meeting-avoidance for self-managing developers
Meeting-avoidance for self-managing developersMeeting-avoidance for self-managing developers
Meeting-avoidance for self-managing developersPeter Hilton
 
How to write good comments
How to write good commentsHow to write good comments
How to write good commentsPeter Hilton
 
Play framework: lessons learned
Play framework: lessons learnedPlay framework: lessons learned
Play framework: lessons learnedPeter Hilton
 
How to name things: the hardest problem in programming
How to name things: the hardest problem in programmingHow to name things: the hardest problem in programming
How to name things: the hardest problem in programmingPeter Hilton
 

More from Peter Hilton (9)

Naming guidelines for professional programmers
Naming guidelines for professional programmersNaming guidelines for professional programmers
Naming guidelines for professional programmers
 
Beautiful code
Beautiful codeBeautiful code
Beautiful code
 
E-Prime: English for scientific writing
E-Prime: English for scientific writing E-Prime: English for scientific writing
E-Prime: English for scientific writing
 
How to write maintainable code
How to write maintainable codeHow to write maintainable code
How to write maintainable code
 
Documentation avoidance for developers
Documentation avoidance for developersDocumentation avoidance for developers
Documentation avoidance for developers
 
Meeting-avoidance for self-managing developers
Meeting-avoidance for self-managing developersMeeting-avoidance for self-managing developers
Meeting-avoidance for self-managing developers
 
How to write good comments
How to write good commentsHow to write good comments
How to write good comments
 
Play framework: lessons learned
Play framework: lessons learnedPlay framework: lessons learned
Play framework: lessons learned
 
How to name things: the hardest problem in programming
How to name things: the hardest problem in programmingHow to name things: the hardest problem in programming
How to name things: the hardest problem in programming
 

Recently uploaded

The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?XfilesPro
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsSnow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsHyundai Motor Group
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 

Recently uploaded (20)

The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptxVulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsSnow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 

Scaling business app development with Play and Scala

  • 1. Scaling business app development with Play & Scala @PeterHilton http://hilton.org.uk/
  • 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. Business web app development
  • 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. 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. With simplicity in the right places, building a web application with the Typesafe platform is* easier and faster than with PHP * probably @PeterHilton • 6
  • 8. robin-berjon / CC BY-SA 2.0
  • 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
  • 12.
  • 13. 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
  • 14. 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
  • 18. /** * 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),
  • 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. "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))
  • 21. 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(_))
  • 23. 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))
  • 24. 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
  • 25. 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 -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐
  • 26. 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
  • 27.
  • 28. // Code example: Scala Slick database access // Nice: select * from LICENSE where id=? val query = Query(Licenses).filter(_.id === id)
  • 29. // 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.?)
  • 30. 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
  • 31. // 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) )
  • 32.
  • 33. 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
  • 34.
  • 35. 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
  • 36.
  • 37. 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
  • 38.
  • 39. 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/
  • 40. 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
  • 41.
  • 42. One more thing… Halfway through the project, the customer decided to open source the application https://github.com/happymelly/teller @PeterHilton • 37
  • 44. 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
  • 45.
  • 46.
  • 47.
  • 48.
  • 49. 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
  • 50. 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 -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐
  • 51. 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
  • 52. // 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" )
  • 53. 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
  • 54. 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) } } }
  • 55. play-plugins-mailer Sending e-mail. Send asynchronously from an Akka actor. @PeterHilton • 50 It Just Works.
  • 56. 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
  • 57. Scaling app dev: lessons learned
  • 58. 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
  • 59. 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
  • 60. 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
  • 61. 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
  • 62.
  • 64. 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
  • 65. 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
  • 66. 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
  • 67. 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