SlideShare a Scribd company logo
1 of 48
Download to read offline
Solid and Sustainable 
Development in Scala 
Kazuhiro Sera @seratch 
ScalikeJDBC / Skinny Framework 
Founder & Lead Developer
Ask Me Later! 
• 3 mags for questioners at the end of this 
session! Don’t miss it! 
2
Who Am I 
• Kazuhiro Sera • @seratch on Twitter/GitHub • Scala enthusiast since 2010 • ScalikeJDBC, Skinny Framework, AWScala 
founder & project lead • A web developer at M3, Inc (We’re a Gold 
Sponsor)
Introduce 
My(Our) Products
ScalikeJDBC 
• scalikejdbc.org • “Scala-like JDBC” • Provides Scala-ish APIs • Started as a better querulous / Anorm • “Just write SQL and get things done” • QueryDSL for smoothness & type-safety • Stable enough: lots of companies already 
use it in production
Dependencies 
// build.sbt or project/Build.scala! 
! 
scalaVersion := “2.11.2” // or “2.10.4”! 
! 
libraryDependencies ++= Seq(! 
“org.scalikejdbc” %% “scalikejdbc” % “2.1.1”,! 
“com.h2database” % “h2” % “1.4.181”,! 
“ch.qos.logback” % “logback-classic” % “1.1.2”! 
)
Basic Usage 
import scalikejdbc._! 
! 
ConnectionPool.singleton(! 
“jdbc:h2:mem:matsuri”, ! 
“user”, “secret”)! 
SQL statement! 
(PreparedStatement) 
! 
DB autoCommit { implicit session =>! 
Side effect ! 
with DB connection 
sql”create table attendee (name varchar(32))”.execute.apply()! 
val name = “seratch”! 
sql”insert into attendee (name) values ($name)”.update.apply()! 
}! 
! 
val names: Seq[String] = DB readOnly { implicit s =>! 
sql”select name from attendee”! 
.map(_.string(“name”)).list.apply()! 
} 
execute/update! 
(JDBC operation) 
Extractor
QueryDSL 
import scalikejdbc._! 
case class Attendee(name: String)! 
object Attendee extends SQLSyntaxSupport[Attendee] {! 
def apply(rs: WrappedResultSet, a: ResultName[Attendee]) = ! 
new Attendee(rs.get(a.name)) 
}! 
! 
implicit val session = AutoSession! 
! 
! 
val a = Attendee.syntax(“a”)! 
val seratch: Option[Attendee] = withSQL {! 
QueryDSL! 
(Mostly SQL) 
Actual SQL Query 
select.from(Attendee as a).where.eq(a.name, “seratch”)! 
}.map(rs => new Attendee(rs, a)).single.apply()! 
! 
// select a.name as n_on_a from attendee a where a.name = ?
Skinny Framework 
• skinny-framework.org • “Scala on Rails” • For Rails / Play1 lovers • 1.0.0 was out on 28th March • Already several experiences in production • Full-stack features: Web infrastructure, 
Scaffold generator, ORM, DB migration, 
JSON stuff, HTTP client, Mail sender, Job 
workers, Assets controller, etc..
Boot in 2 minutes 
! 
// install skinny command! 
brew tap skinny-framework/alt! 
brew install skinny! 
! 
// create app and start! 
skinny new myapp! 
cd myapp! 
skinny run! 
! 
// access localhost:8080 from your browser!
Model (DAO) 
import skinny.orm._! 
Entity 
import scalikejdbc._! 
! 
case class User(id: Long, name: Option[String])! 
! 
// companion: data mapper! 
object User extends SkinnyCRUDMapper[User] {! 
def defaultAlias = createAlias(“u”)! 
def extract(rs: WrappedResultSet, u: ResultName[User])! 
= autoConstruct(rs, u) 
}! 
CRUD Mapper Object! 
! 
(No need to be companion) 
User.findById(123)! 
User.count()! 
User.createWithAttributes(‘name -> “Alice”)! 
User.updateById(123).withAttributes(‘name -> “Bob”)! 
User.deleteBy(sqls.eq(u.name, “Bob”)) 
Smooth APIs
Controller + Route 
package controller! 
class UsersController extends ApplicationController {! 
def showUsers = {! 
set(“users”, User.findAll())! 
render(“/users/index”) 
} 
}! 
! 
// Routings! 
object Controllers {! 
Set value in request scope! 
(Visible in views) 
Expects “src/main/webapp/! 
WEB-INF/views/users/index.html.ssp” 
val users = new UsersController with Routes {! 
get(“/users/”)(showUsers).as(‘showUsers) 
}! 
def mount(ctx: ServletContext): Unit = {! 
users.mount(ctx)! 
} 
}
View Template 
// src/main/webapp/WEB-INF/views/users/index.html.ssp! 
! 
<%@val users: Seq[User] %>! 
! 
<table class=“table”>! 
#for (user <- users)! 
<tr>! 
<td>${user.id}</td>! 
<td>${user.name}</td>! 
</tr>! 
#end! 
</table> 
import from request scope 
Loop, if/else syntax! 
in Scalate
Web Development 
• Interactive feedback loop is most 
important especially when changing UI • Actually Scala compilation is so slow that 
waiting view templates compilation makes 
developers much stressed • Skinny doesn’t compile all the view 
templates when developing (unlike Twirl)
My Good Parts 
for Solid and Safe 
Development
My Good Parts 
•Simplified Class-based OOP And 
Immutable Data Structure 
•Working On Problems Without 
Overkill Abstraction 
•Writing Tests Without Question 
•Keep Infrastructure Lightweight 
•No Surprises For Newcomer
Simplified Class-based 
OOP 
And Immutable 
Data Structure
Class-based OOP 
• Already so popular (Java, Ruby, Python ..) • Old style is friendly with mutability (e.g. 
setters, bang methods), but that’s not a 
prerequisite • OOP can be more solid and safer by 
keeping immutability and avoiding 
inheritance anti-patterns
Scala or Java 8? 
• Scala case class is simpler than Java 
beans with (great) Lombok • Scala high-order functions are simpler 
than Java 8 Stream API • Immutability is well-treated in Scala • Fairness: Java decisively beats Scala in 
comparison with compilation speed..
Immutability 
• Do away with mutable states • Re-assignment? No way! Don’t use `var` • Immutability makes your apps not only 
scalable but also more solid • When you modify a case class, call 
#copy() and return new state instead of 
using setters for mutability inside
Immutable Entity 
// entity with behaviors! 
case class User(id: Long, name: Option[String])! 
extends SkinnyRecord[User] {! 
override def skinnyCRUDMapper = User 
}! 
// data mapper! 
object User extends SkinnyCRUDMapper[User] {! 
override def defaultAlias = createAlias(“u”)! 
override def extract(rs: WrappedResultSet, u: ResultName[User])! 
= autoConstruct(rs, u) 
}! 
! 
val noNames: Seq[User] = User.where(‘name -> “”).apply()! 
val anons: Seq[User] = noNames.map { user => ! 
user.copy(name = “Anonymous”).save()! 
} 
Both of “noNames” and 
“anons” are immutable
Trait Chaos 
• Mixing traits can show you terrible chaos • We should have self-discipline • Prefer `override` modifier to detect API 
changes when mixing many traits • Collect the same sort of traits and place 
them in same place to avoid code 
duplication or unwanted complexity
Web Controller 
package controller! 
class MainController extends ApplicationController ! 
with concern.TimeLogging {! 
def index = logElapsedTime { render(“/main/index”) }! 
}! 
! 
// for controllers! 
package controller.concern! 
trait TimeLogging { self: SkinnyController with Logging =>! 
The “concern” just follows Rails style. 
Anyway, naming should be simple and! 
easy-to-understand for anyone 
def millis: Long = System.currentTimeMillis ! 
def logElapsedTime[A](action: => A): A = {! 
val before = millis! 
val result = action! 
logger.debug(“Elapsed time: ${millis - before} millis”)! 
result 
}! 
}
Coding Style Tips 
• Use sbt-scalariform without question 
(similar: go-lang’s fmt) • Don’t toss similar classes or traits into 
single scala file except `sealed` pattern • Don’t place classes under different 
package directory (although it’s possible) • Do you really need cake pattern? • Prefer eloquent method signature than 
explaining a lot in scaladocs
Working On 
Problems Without 
Overkill Abstraction
The Real As-Is 
• Abstraction often improves things, but 
that’s not always the best way to solve 
real-world problems • I/O issue is a typical case that we should 
comprehend problems as-is • Database access / SQL is not a collection 
but just an external I/O operation • Overkill abstraction makes your code 
difficult to maintain for other developers
Don’t Hide the SQL 
• “You don’t need another DSL to access 
relational databases” - Anorm • You must recognize what is working 
effectively in the SQL layer • Utility to write DAO easily is fine but 
hiding SQL is not good • Need to grab the cause from raw queries 
when dealing with troubles (comfortable 
logging also can help)
SQL Ops As-Is 
// A programmer belongs to a company and has several skills! 
! 
implicit val session = AutoSession! 
! 
val p: Option[Programmer] = withSQL {! 
I believe everybody can 
understand this code 
select.from(Programmer as p)! 
.leftJoin(Company as c).on(p.companyId, c.id)! 
.leftJoin(ProgrammerSkill as ps).on(ps.programmerId, p.id)! 
.leftJoin(Skill as s).on(ps.skillId, s.id)! 
.where.eq(p.id, 123).and.isNull(p.deletedAt)! 
}! 
.one(rs => Programmer(rs, p, c))! 
Extracts one-to-many 
.toMany(rs => Skill.opt(rs, s))! 
relationships here 
.map { (programmer, skills) => programmer.copy(skills = skills) }! 
.single! 
.apply()
Skinny ORM 
• ORM built on ScalikeJDBC • Highly inspired by Rails ActiveRecord • SQL queries for CRUD apps are common 
enough, so it’s reasonable to avoid writing 
mostly same code everywhere • Skinny ORM doesn't prevent you from 
using ScaikeJDBC APIs directly • A part of Skinny Framework but you can 
use it in Play apps too
Dependencies 
// build.sbt or project/Build.scala! 
! 
scalaVersion := “2.11.2” // or “2.10.4”! 
! 
libraryDependencies ++= Seq(! 
//“org.scalikejdbc” %% “scalikejdbc” % “2.1.1”,! 
“org.skinny-framework” %% “skinny-orm” % “1.3.1”,! 
“com.h2database” % “h2” % “1.4.181”,! 
“ch.qos.logback” % “logback-classic” % “1.1.2”! 
)
Mappers 
// entities! 
case class Company(id: Long, name: String)! 
case class Employee(id: Long, name: String,! 
companyId: Long, company: Option[Company])! 
! 
// mappers! 
object Company extends SkinnyCRUDMapper[Company] {! 
def extract(rs: WrappedResultSet, rn: ResultName[Company]) =! 
autoConstruct(rs, rn) 
}! 
object Employee extends SkinnyCRUDMapper[Employee] {! 
def extract(rs: WrappedResultSet, rn: ResultName[Employee]) =! 
autoConstruct(rs, rn, “company”)! 
// simple association definition! 
lazy val companyRef = belongsTo[Company](! 
Company, (e, c) => e.copy(company = c)) 
}
Reasonable? 
Right, these CRUD operations are not SQL-ish. However, I believe 
they’re reasonable because these patterns are already common enough. 
! 
! 
val companyId = Company.createWithAttributes(‘name -> “Sun”)! 
val empId = Employee.createWithAttributes(! 
‘name -> “Alice”, ‘companyId -> companyId)! 
! 
val emp: Option[Employee] = Employee.findById(empId)! 
val empWithCompany: Option[Employee] = ! 
Employee.joins(companyRef).findById(123)! 
! 
Company.updateById(companyId).withAttributes(‘name -> “Oracle”)! 
! 
val e = Employee.defaultAlias! 
Employee.deleteBy(sqls.eq(e.id, empId))! 
Using ScalikeJBDC API! 
Company.deleteById(companyId) 
is also possible
Writing Tests 
Without 
Question
Not Only Compiler 
• It’s true that compiler helps you by 
detecting mistakes in coding • Writing tests is a reasonable way to verify 
your code meets requirements / 
specifications as expected • You can’t skip automated tests even if 
your apps are written in Scala
scoverage 
• At this time, the only option available for 
us is scoverage (SCCT inheritor) • Add the dependency into your projects 
right now if you don’t use it yet
Keep 
Infrastructure 
Lightweight
Avoid SBT Hacks 
• sbt is not so easy for Scala newbies, 
upgrading sbt is all the more so • Play depends on sbt version (e.g. Play 2.1 
w/ sbt 0.12), upgrading Play is about not 
only Play API changes but sbt things • Your own sbt plugins/hacks make your 
projects difficult to maintain for a long 
period and involve others • Don’t try to do everything there
Skinny TaskRunner 
• Just want a simple and “rake”-like task 
runner (no sbt plugin) • Simplistic but pragmatic idea: “mainClass” 
of “task” sbt project can be dispatcher of 
task runner system • Tasks are written in Scala (no sbt plugin) • Not only writing code but upgrading 
scala/sbt version become pretty easy
Tasks 
// sbt settings! 
// mainClass := Some("TaskRunner")! 
! 
// task/src/main/scala/TaskRunner.scala! 
object TaskRunner extends skinny.task.TaskLauncher {! 
register("assets:precompile", (params) => {! 
val buildDir = params.headOption.getOrElse(“build")! 
// AssetsPrecompileTask is a Scala object! 
skinny.task.AssetsPrecompileTask.main(Array(buildDir))! 
})! 
}! 
Pure Scala function! 
! 
// skinny task:run assets:precompile [dir] 
task name 
mainClass as the dispatcher
Use Only Essentials 
• The same issue as Ruby gems, what’s 
worse, Scala’s eco-system is still so 
smaller than Ruby’s one • Binary incompatibility makes existing 
libraries outdated every Scala major 
version release • Are you really ready to fork them? • Using Java assets (e.g. commons) 
internally is also worth thinking about
No Surprises 
for Newcomer
Can Feel Welcome? 
• Is joining your Scala projects easy? Can 
newcomer understand overview at once? • Don’t stick to doing on the sbt, don’t 
disfavor using other tools (e.g. Grunt) • Well-known style (e.g. Rails style) is 
preferred for collaborative works • Is asynchronosity really required now? • Indeed, your DSL is very simple but easy 
to modify them (for others)?
Newcomers may not 
know Scala well. 
Attract them to Scala! 
(Don’t scare them)
AMA! #ScalaMatsuri2 
• Unconference tomorrow • “Ask Me Anything” • ScalikeJDBC • Skinny Framework • AWScala • Anything else!
Questions?
Questions?
Questions?
Thanks 
• Amazing “Maturi Urakata” (the 
conference volunteer staff) • Great invited speakers • You all here!

More Related Content

What's hot

Concurrency in Scala - the Akka way
Concurrency in Scala - the Akka wayConcurrency in Scala - the Akka way
Concurrency in Scala - the Akka way
Yardena Meymann
 
Building Concurrent WebObjects applications with Scala
Building Concurrent WebObjects applications with ScalaBuilding Concurrent WebObjects applications with Scala
Building Concurrent WebObjects applications with Scala
WO Community
 
Fast Web Applications Development with Ruby on Rails on Oracle
Fast Web Applications Development with Ruby on Rails on OracleFast Web Applications Development with Ruby on Rails on Oracle
Fast Web Applications Development with Ruby on Rails on Oracle
Raimonds Simanovskis
 
Using Ruby on Rails with legacy Oracle databases
Using Ruby on Rails with legacy Oracle databasesUsing Ruby on Rails with legacy Oracle databases
Using Ruby on Rails with legacy Oracle databases
Raimonds Simanovskis
 
Mastering Java Bytecode - JAX.de 2012
Mastering Java Bytecode - JAX.de 2012Mastering Java Bytecode - JAX.de 2012
Mastering Java Bytecode - JAX.de 2012
Anton Arhipov
 

What's hot (20)

Scala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghScala @ TechMeetup Edinburgh
Scala @ TechMeetup Edinburgh
 
55 New Features in Java 7
55 New Features in Java 755 New Features in Java 7
55 New Features in Java 7
 
Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)
 
[Start] Scala
[Start] Scala[Start] Scala
[Start] Scala
 
Scala Introduction
Scala IntroductionScala Introduction
Scala Introduction
 
Java 7 Whats New(), Whats Next() from Oredev
Java 7 Whats New(), Whats Next() from OredevJava 7 Whats New(), Whats Next() from Oredev
Java 7 Whats New(), Whats Next() from Oredev
 
Concurrency in Scala - the Akka way
Concurrency in Scala - the Akka wayConcurrency in Scala - the Akka way
Concurrency in Scala - the Akka way
 
Extending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on RailsExtending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on Rails
 
JavaFX 2 and Scala - Like Milk and Cookies (33rd Degrees)
JavaFX 2 and Scala - Like Milk and Cookies (33rd Degrees)JavaFX 2 and Scala - Like Milk and Cookies (33rd Degrees)
JavaFX 2 and Scala - Like Milk and Cookies (33rd Degrees)
 
Akka and the Zen of Reactive System Design
Akka and the Zen of Reactive System DesignAkka and the Zen of Reactive System Design
Akka and the Zen of Reactive System Design
 
Scala active record
Scala active recordScala active record
Scala active record
 
Building Concurrent WebObjects applications with Scala
Building Concurrent WebObjects applications with ScalaBuilding Concurrent WebObjects applications with Scala
Building Concurrent WebObjects applications with Scala
 
JavaOne 2011 - JVM Bytecode for Dummies
JavaOne 2011 - JVM Bytecode for DummiesJavaOne 2011 - JVM Bytecode for Dummies
JavaOne 2011 - JVM Bytecode for Dummies
 
Fast Web Applications Development with Ruby on Rails on Oracle
Fast Web Applications Development with Ruby on Rails on OracleFast Web Applications Development with Ruby on Rails on Oracle
Fast Web Applications Development with Ruby on Rails on Oracle
 
Scala coated JVM
Scala coated JVMScala coated JVM
Scala coated JVM
 
Using Ruby on Rails with legacy Oracle databases
Using Ruby on Rails with legacy Oracle databasesUsing Ruby on Rails with legacy Oracle databases
Using Ruby on Rails with legacy Oracle databases
 
Demystifying Oak Search
Demystifying Oak SearchDemystifying Oak Search
Demystifying Oak Search
 
User defined-functions-cassandra-summit-eu-2014
User defined-functions-cassandra-summit-eu-2014User defined-functions-cassandra-summit-eu-2014
User defined-functions-cassandra-summit-eu-2014
 
Mastering Java Bytecode - JAX.de 2012
Mastering Java Bytecode - JAX.de 2012Mastering Java Bytecode - JAX.de 2012
Mastering Java Bytecode - JAX.de 2012
 
Short intro to scala and the play framework
Short intro to scala and the play frameworkShort intro to scala and the play framework
Short intro to scala and the play framework
 

Viewers also liked

GitBucket: The perfect Github clone by Scala
GitBucket: The perfect Github clone by ScalaGitBucket: The perfect Github clone by Scala
GitBucket: The perfect Github clone by Scala
takezoe
 
芸者東京とScala〜おみせやさんから脳トレクエストまでの軌跡〜
芸者東京とScala〜おみせやさんから脳トレクエストまでの軌跡〜芸者東京とScala〜おみせやさんから脳トレクエストまでの軌跡〜
芸者東京とScala〜おみせやさんから脳トレクエストまでの軌跡〜
scalaconfjp
 
Scala Warrior and type-safe front-end development with Scala.js
Scala Warrior and type-safe front-end development with Scala.jsScala Warrior and type-safe front-end development with Scala.js
Scala Warrior and type-safe front-end development with Scala.js
takezoe
 

Viewers also liked (15)

GitBucket: The perfect Github clone by Scala
GitBucket: The perfect Github clone by ScalaGitBucket: The perfect Github clone by Scala
GitBucket: The perfect Github clone by Scala
 
Introduction to Spark SQL and Catalyst / Spark SQLおよびCalalystの紹介
Introduction to Spark SQL and Catalyst / Spark SQLおよびCalalystの紹介Introduction to Spark SQL and Catalyst / Spark SQLおよびCalalystの紹介
Introduction to Spark SQL and Catalyst / Spark SQLおよびCalalystの紹介
 
Scarab: SAT-based Constraint Programming System in Scala / Scala上で実現された制約プログラ...
Scarab: SAT-based Constraint Programming System in Scala / Scala上で実現された制約プログラ...Scarab: SAT-based Constraint Programming System in Scala / Scala上で実現された制約プログラ...
Scarab: SAT-based Constraint Programming System in Scala / Scala上で実現された制約プログラ...
 
Scalable Generator: Using Scala in SIer Business (ScalaMatsuri)
Scalable Generator: Using Scala in SIer Business (ScalaMatsuri)Scalable Generator: Using Scala in SIer Business (ScalaMatsuri)
Scalable Generator: Using Scala in SIer Business (ScalaMatsuri)
 
[ScalaMatsuri] グリー初のscalaプロダクト!チャットサービス公開までの苦労と工夫
[ScalaMatsuri] グリー初のscalaプロダクト!チャットサービス公開までの苦労と工夫[ScalaMatsuri] グリー初のscalaプロダクト!チャットサービス公開までの苦労と工夫
[ScalaMatsuri] グリー初のscalaプロダクト!チャットサービス公開までの苦労と工夫
 
sbt, past and future / sbt, 傾向と対策
sbt, past and future / sbt, 傾向と対策sbt, past and future / sbt, 傾向と対策
sbt, past and future / sbt, 傾向と対策
 
Weaving Dataflows with Silk - ScalaMatsuri 2014, Tokyo
Weaving Dataflows with Silk - ScalaMatsuri 2014, TokyoWeaving Dataflows with Silk - ScalaMatsuri 2014, Tokyo
Weaving Dataflows with Silk - ScalaMatsuri 2014, Tokyo
 
芸者東京とScala〜おみせやさんから脳トレクエストまでの軌跡〜
芸者東京とScala〜おみせやさんから脳トレクエストまでの軌跡〜芸者東京とScala〜おみせやさんから脳トレクエストまでの軌跡〜
芸者東京とScala〜おみせやさんから脳トレクエストまでの軌跡〜
 
Scala が支える医療系ウェブサービス #jissenscala
Scala が支える医療系ウェブサービス #jissenscalaScala が支える医療系ウェブサービス #jissenscala
Scala が支える医療系ウェブサービス #jissenscala
 
Scala@SmartNews_20150221
Scala@SmartNews_20150221Scala@SmartNews_20150221
Scala@SmartNews_20150221
 
Scala@SmartNews AdFrontend を Scala で書いた話
Scala@SmartNews AdFrontend を Scala で書いた話Scala@SmartNews AdFrontend を Scala で書いた話
Scala@SmartNews AdFrontend を Scala で書いた話
 
ビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscala
ビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscalaビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscala
ビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscala
 
あなたのScalaを爆速にする7つの方法
あなたのScalaを爆速にする7つの方法あなたのScalaを爆速にする7つの方法
あなたのScalaを爆速にする7つの方法
 
Scala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentationScala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentation
 
Scala Warrior and type-safe front-end development with Scala.js
Scala Warrior and type-safe front-end development with Scala.jsScala Warrior and type-safe front-end development with Scala.js
Scala Warrior and type-safe front-end development with Scala.js
 

Similar to Solid And Sustainable Development in Scala

Intro to node.js - Ran Mizrahi (28/8/14)
Intro to node.js - Ran Mizrahi (28/8/14)Intro to node.js - Ran Mizrahi (28/8/14)
Intro to node.js - Ran Mizrahi (28/8/14)
Ran Mizrahi
 
Typesafe stack - Scala, Akka and Play
Typesafe stack - Scala, Akka and PlayTypesafe stack - Scala, Akka and Play
Typesafe stack - Scala, Akka and Play
Luka Zakrajšek
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
Fabio Franzini
 

Similar to Solid And Sustainable Development in Scala (20)

Wider than rails
Wider than railsWider than rails
Wider than rails
 
Scala Frustrations
Scala FrustrationsScala Frustrations
Scala Frustrations
 
Beginning Scala with Skinny Framework #jjug_ccc
Beginning Scala with Skinny Framework #jjug_cccBeginning Scala with Skinny Framework #jjug_ccc
Beginning Scala with Skinny Framework #jjug_ccc
 
Modern Front-End Development
Modern Front-End DevelopmentModern Front-End Development
Modern Front-End Development
 
Alberto Paro - Hands on Scala.js
Alberto Paro - Hands on Scala.jsAlberto Paro - Hands on Scala.js
Alberto Paro - Hands on Scala.js
 
Scala Italy 2015 - Hands On ScalaJS
Scala Italy 2015 - Hands On ScalaJSScala Italy 2015 - Hands On ScalaJS
Scala Italy 2015 - Hands On ScalaJS
 
Intro to node.js - Ran Mizrahi (27/8/2014)
Intro to node.js - Ran Mizrahi (27/8/2014)Intro to node.js - Ran Mizrahi (27/8/2014)
Intro to node.js - Ran Mizrahi (27/8/2014)
 
Intro to node.js - Ran Mizrahi (28/8/14)
Intro to node.js - Ran Mizrahi (28/8/14)Intro to node.js - Ran Mizrahi (28/8/14)
Intro to node.js - Ran Mizrahi (28/8/14)
 
Play framework
Play frameworkPlay framework
Play framework
 
Typesafe stack - Scala, Akka and Play
Typesafe stack - Scala, Akka and PlayTypesafe stack - Scala, Akka and Play
Typesafe stack - Scala, Akka and Play
 
Alberto Maria Angelo Paro - Isomorphic programming in Scala and WebDevelopmen...
Alberto Maria Angelo Paro - Isomorphic programming in Scala and WebDevelopmen...Alberto Maria Angelo Paro - Isomorphic programming in Scala and WebDevelopmen...
Alberto Maria Angelo Paro - Isomorphic programming in Scala and WebDevelopmen...
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Rack
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
 
Day 2 - Intro to Rails
Day 2 - Intro to RailsDay 2 - Intro to Rails
Day 2 - Intro to Rails
 
MSc Enterprise Systems Development Guest Lecture at UniS (2/12/09)
MSc Enterprise Systems Development Guest Lecture at UniS (2/12/09)MSc Enterprise Systems Development Guest Lecture at UniS (2/12/09)
MSc Enterprise Systems Development Guest Lecture at UniS (2/12/09)
 
Play Framework and Activator
Play Framework and ActivatorPlay Framework and Activator
Play Framework and Activator
 
Spark Job Server and Spark as a Query Engine (Spark Meetup 5/14)
Spark Job Server and Spark as a Query Engine (Spark Meetup 5/14)Spark Job Server and Spark as a Query Engine (Spark Meetup 5/14)
Spark Job Server and Spark as a Query Engine (Spark Meetup 5/14)
 
BP-6 Repository Customization Best Practices
BP-6 Repository Customization Best PracticesBP-6 Repository Customization Best Practices
BP-6 Repository Customization Best Practices
 
Ruby On Rails
Ruby On RailsRuby On Rails
Ruby On Rails
 

More from Kazuhiro Sera

Future on Servlet #scala_ks
Future on Servlet #scala_ksFuture on Servlet #scala_ks
Future on Servlet #scala_ks
Kazuhiro Sera
 
テストの運用について #m3dev
テストの運用について #m3devテストの運用について #m3dev
テストの運用について #m3dev
Kazuhiro Sera
 

More from Kazuhiro Sera (20)

All I learned while working on a Scala OSS project for over six years #ScalaM...
All I learned while working on a Scala OSS project for over six years #ScalaM...All I learned while working on a Scala OSS project for over six years #ScalaM...
All I learned while working on a Scala OSS project for over six years #ScalaM...
 
Contributing to Scala OSS from East Asia #ScalaMatsuri
 Contributing to Scala OSS from East Asia #ScalaMatsuri Contributing to Scala OSS from East Asia #ScalaMatsuri
Contributing to Scala OSS from East Asia #ScalaMatsuri
 
Skinny Meetup Tokyo 2 日本語スライド
Skinny Meetup Tokyo 2 日本語スライドSkinny Meetup Tokyo 2 日本語スライド
Skinny Meetup Tokyo 2 日本語スライド
 
Skinny 2 Update
Skinny 2 UpdateSkinny 2 Update
Skinny 2 Update
 
Seasar ユーザだったプログラマが目指す OSS の世界展開 #seasarcon
Seasar ユーザだったプログラマが目指す OSS の世界展開 #seasarconSeasar ユーザだったプログラマが目指す OSS の世界展開 #seasarcon
Seasar ユーザだったプログラマが目指す OSS の世界展開 #seasarcon
 
Java エンジニアチームが始めやすい Scala コーディングスタイル #ichigayageek
Java エンジニアチームが始めやすい Scala コーディングスタイル #ichigayageekJava エンジニアチームが始めやすい Scala コーディングスタイル #ichigayageek
Java エンジニアチームが始めやすい Scala コーディングスタイル #ichigayageek
 
Future on Servlet #scala_ks
Future on Servlet #scala_ksFuture on Servlet #scala_ks
Future on Servlet #scala_ks
 
Servlet と Future の関わり方 #scala_ks
Servlet と Future の関わり方 #scala_ksServlet と Future の関わり方 #scala_ks
Servlet と Future の関わり方 #scala_ks
 
マイクロサービス運用の所感 #m3dev
マイクロサービス運用の所感 #m3devマイクロサービス運用の所感 #m3dev
マイクロサービス運用の所感 #m3dev
 
Scala on Rails #rakutentech
Scala on Rails #rakutentechScala on Rails #rakutentech
Scala on Rails #rakutentech
 
[Japanese] Skinny Framework で始める Scala #jjug_ccc #ccc_r24
[Japanese] Skinny Framework で始める Scala #jjug_ccc #ccc_r24[Japanese] Skinny Framework で始める Scala #jjug_ccc #ccc_r24
[Japanese] Skinny Framework で始める Scala #jjug_ccc #ccc_r24
 
Skinny Framework 1.0.0
Skinny Framework 1.0.0Skinny Framework 1.0.0
Skinny Framework 1.0.0
 
Skinny Framework Progress Situation
Skinny Framework Progress SituationSkinny Framework Progress Situation
Skinny Framework Progress Situation
 
Skinny Framework 進捗どうですか? #fud_scala
Skinny Framework 進捗どうですか? #fud_scalaSkinny Framework 進捗どうですか? #fud_scala
Skinny Framework 進捗どうですか? #fud_scala
 
テストの運用について #m3dev
テストの運用について #m3devテストの運用について #m3dev
テストの運用について #m3dev
 
めんどくさくない Scala #kwkni_scala
めんどくさくない Scala #kwkni_scalaめんどくさくない Scala #kwkni_scala
めんどくさくない Scala #kwkni_scala
 
歌舞伎座.tech 1 LT - ScalikeJDBC Async & Skinny Framework #kbkz_tech
歌舞伎座.tech 1 LT - ScalikeJDBC Async & Skinny Framework #kbkz_tech歌舞伎座.tech 1 LT - ScalikeJDBC Async & Skinny Framework #kbkz_tech
歌舞伎座.tech 1 LT - ScalikeJDBC Async & Skinny Framework #kbkz_tech
 
Kabukiza.tech 1 LT - ScalikeJDBC-Async & Skinny Framework #kbkz_tech
Kabukiza.tech 1 LT - ScalikeJDBC-Async & Skinny Framework #kbkz_techKabukiza.tech 1 LT - ScalikeJDBC-Async & Skinny Framework #kbkz_tech
Kabukiza.tech 1 LT - ScalikeJDBC-Async & Skinny Framework #kbkz_tech
 
テストを書くのが嫌いな君へ #m3dev
テストを書くのが嫌いな君へ #m3devテストを書くのが嫌いな君へ #m3dev
テストを書くのが嫌いな君へ #m3dev
 
Skinny Controllers, Skinny Models
Skinny Controllers, Skinny ModelsSkinny Controllers, Skinny Models
Skinny Controllers, Skinny Models
 

Solid And Sustainable Development in Scala

  • 1. Solid and Sustainable Development in Scala Kazuhiro Sera @seratch ScalikeJDBC / Skinny Framework Founder & Lead Developer
  • 2. Ask Me Later! • 3 mags for questioners at the end of this session! Don’t miss it! 2
  • 3. Who Am I • Kazuhiro Sera • @seratch on Twitter/GitHub • Scala enthusiast since 2010 • ScalikeJDBC, Skinny Framework, AWScala founder & project lead • A web developer at M3, Inc (We’re a Gold Sponsor)
  • 5. ScalikeJDBC • scalikejdbc.org • “Scala-like JDBC” • Provides Scala-ish APIs • Started as a better querulous / Anorm • “Just write SQL and get things done” • QueryDSL for smoothness & type-safety • Stable enough: lots of companies already use it in production
  • 6. Dependencies // build.sbt or project/Build.scala! ! scalaVersion := “2.11.2” // or “2.10.4”! ! libraryDependencies ++= Seq(! “org.scalikejdbc” %% “scalikejdbc” % “2.1.1”,! “com.h2database” % “h2” % “1.4.181”,! “ch.qos.logback” % “logback-classic” % “1.1.2”! )
  • 7. Basic Usage import scalikejdbc._! ! ConnectionPool.singleton(! “jdbc:h2:mem:matsuri”, ! “user”, “secret”)! SQL statement! (PreparedStatement) ! DB autoCommit { implicit session =>! Side effect ! with DB connection sql”create table attendee (name varchar(32))”.execute.apply()! val name = “seratch”! sql”insert into attendee (name) values ($name)”.update.apply()! }! ! val names: Seq[String] = DB readOnly { implicit s =>! sql”select name from attendee”! .map(_.string(“name”)).list.apply()! } execute/update! (JDBC operation) Extractor
  • 8. QueryDSL import scalikejdbc._! case class Attendee(name: String)! object Attendee extends SQLSyntaxSupport[Attendee] {! def apply(rs: WrappedResultSet, a: ResultName[Attendee]) = ! new Attendee(rs.get(a.name)) }! ! implicit val session = AutoSession! ! ! val a = Attendee.syntax(“a”)! val seratch: Option[Attendee] = withSQL {! QueryDSL! (Mostly SQL) Actual SQL Query select.from(Attendee as a).where.eq(a.name, “seratch”)! }.map(rs => new Attendee(rs, a)).single.apply()! ! // select a.name as n_on_a from attendee a where a.name = ?
  • 9. Skinny Framework • skinny-framework.org • “Scala on Rails” • For Rails / Play1 lovers • 1.0.0 was out on 28th March • Already several experiences in production • Full-stack features: Web infrastructure, Scaffold generator, ORM, DB migration, JSON stuff, HTTP client, Mail sender, Job workers, Assets controller, etc..
  • 10. Boot in 2 minutes ! // install skinny command! brew tap skinny-framework/alt! brew install skinny! ! // create app and start! skinny new myapp! cd myapp! skinny run! ! // access localhost:8080 from your browser!
  • 11. Model (DAO) import skinny.orm._! Entity import scalikejdbc._! ! case class User(id: Long, name: Option[String])! ! // companion: data mapper! object User extends SkinnyCRUDMapper[User] {! def defaultAlias = createAlias(“u”)! def extract(rs: WrappedResultSet, u: ResultName[User])! = autoConstruct(rs, u) }! CRUD Mapper Object! ! (No need to be companion) User.findById(123)! User.count()! User.createWithAttributes(‘name -> “Alice”)! User.updateById(123).withAttributes(‘name -> “Bob”)! User.deleteBy(sqls.eq(u.name, “Bob”)) Smooth APIs
  • 12. Controller + Route package controller! class UsersController extends ApplicationController {! def showUsers = {! set(“users”, User.findAll())! render(“/users/index”) } }! ! // Routings! object Controllers {! Set value in request scope! (Visible in views) Expects “src/main/webapp/! WEB-INF/views/users/index.html.ssp” val users = new UsersController with Routes {! get(“/users/”)(showUsers).as(‘showUsers) }! def mount(ctx: ServletContext): Unit = {! users.mount(ctx)! } }
  • 13. View Template // src/main/webapp/WEB-INF/views/users/index.html.ssp! ! <%@val users: Seq[User] %>! ! <table class=“table”>! #for (user <- users)! <tr>! <td>${user.id}</td>! <td>${user.name}</td>! </tr>! #end! </table> import from request scope Loop, if/else syntax! in Scalate
  • 14. Web Development • Interactive feedback loop is most important especially when changing UI • Actually Scala compilation is so slow that waiting view templates compilation makes developers much stressed • Skinny doesn’t compile all the view templates when developing (unlike Twirl)
  • 15. My Good Parts for Solid and Safe Development
  • 16. My Good Parts •Simplified Class-based OOP And Immutable Data Structure •Working On Problems Without Overkill Abstraction •Writing Tests Without Question •Keep Infrastructure Lightweight •No Surprises For Newcomer
  • 17. Simplified Class-based OOP And Immutable Data Structure
  • 18. Class-based OOP • Already so popular (Java, Ruby, Python ..) • Old style is friendly with mutability (e.g. setters, bang methods), but that’s not a prerequisite • OOP can be more solid and safer by keeping immutability and avoiding inheritance anti-patterns
  • 19. Scala or Java 8? • Scala case class is simpler than Java beans with (great) Lombok • Scala high-order functions are simpler than Java 8 Stream API • Immutability is well-treated in Scala • Fairness: Java decisively beats Scala in comparison with compilation speed..
  • 20. Immutability • Do away with mutable states • Re-assignment? No way! Don’t use `var` • Immutability makes your apps not only scalable but also more solid • When you modify a case class, call #copy() and return new state instead of using setters for mutability inside
  • 21. Immutable Entity // entity with behaviors! case class User(id: Long, name: Option[String])! extends SkinnyRecord[User] {! override def skinnyCRUDMapper = User }! // data mapper! object User extends SkinnyCRUDMapper[User] {! override def defaultAlias = createAlias(“u”)! override def extract(rs: WrappedResultSet, u: ResultName[User])! = autoConstruct(rs, u) }! ! val noNames: Seq[User] = User.where(‘name -> “”).apply()! val anons: Seq[User] = noNames.map { user => ! user.copy(name = “Anonymous”).save()! } Both of “noNames” and “anons” are immutable
  • 22. Trait Chaos • Mixing traits can show you terrible chaos • We should have self-discipline • Prefer `override` modifier to detect API changes when mixing many traits • Collect the same sort of traits and place them in same place to avoid code duplication or unwanted complexity
  • 23. Web Controller package controller! class MainController extends ApplicationController ! with concern.TimeLogging {! def index = logElapsedTime { render(“/main/index”) }! }! ! // for controllers! package controller.concern! trait TimeLogging { self: SkinnyController with Logging =>! The “concern” just follows Rails style. Anyway, naming should be simple and! easy-to-understand for anyone def millis: Long = System.currentTimeMillis ! def logElapsedTime[A](action: => A): A = {! val before = millis! val result = action! logger.debug(“Elapsed time: ${millis - before} millis”)! result }! }
  • 24. Coding Style Tips • Use sbt-scalariform without question (similar: go-lang’s fmt) • Don’t toss similar classes or traits into single scala file except `sealed` pattern • Don’t place classes under different package directory (although it’s possible) • Do you really need cake pattern? • Prefer eloquent method signature than explaining a lot in scaladocs
  • 25. Working On Problems Without Overkill Abstraction
  • 26. The Real As-Is • Abstraction often improves things, but that’s not always the best way to solve real-world problems • I/O issue is a typical case that we should comprehend problems as-is • Database access / SQL is not a collection but just an external I/O operation • Overkill abstraction makes your code difficult to maintain for other developers
  • 27. Don’t Hide the SQL • “You don’t need another DSL to access relational databases” - Anorm • You must recognize what is working effectively in the SQL layer • Utility to write DAO easily is fine but hiding SQL is not good • Need to grab the cause from raw queries when dealing with troubles (comfortable logging also can help)
  • 28. SQL Ops As-Is // A programmer belongs to a company and has several skills! ! implicit val session = AutoSession! ! val p: Option[Programmer] = withSQL {! I believe everybody can understand this code select.from(Programmer as p)! .leftJoin(Company as c).on(p.companyId, c.id)! .leftJoin(ProgrammerSkill as ps).on(ps.programmerId, p.id)! .leftJoin(Skill as s).on(ps.skillId, s.id)! .where.eq(p.id, 123).and.isNull(p.deletedAt)! }! .one(rs => Programmer(rs, p, c))! Extracts one-to-many .toMany(rs => Skill.opt(rs, s))! relationships here .map { (programmer, skills) => programmer.copy(skills = skills) }! .single! .apply()
  • 29. Skinny ORM • ORM built on ScalikeJDBC • Highly inspired by Rails ActiveRecord • SQL queries for CRUD apps are common enough, so it’s reasonable to avoid writing mostly same code everywhere • Skinny ORM doesn't prevent you from using ScaikeJDBC APIs directly • A part of Skinny Framework but you can use it in Play apps too
  • 30. Dependencies // build.sbt or project/Build.scala! ! scalaVersion := “2.11.2” // or “2.10.4”! ! libraryDependencies ++= Seq(! //“org.scalikejdbc” %% “scalikejdbc” % “2.1.1”,! “org.skinny-framework” %% “skinny-orm” % “1.3.1”,! “com.h2database” % “h2” % “1.4.181”,! “ch.qos.logback” % “logback-classic” % “1.1.2”! )
  • 31. Mappers // entities! case class Company(id: Long, name: String)! case class Employee(id: Long, name: String,! companyId: Long, company: Option[Company])! ! // mappers! object Company extends SkinnyCRUDMapper[Company] {! def extract(rs: WrappedResultSet, rn: ResultName[Company]) =! autoConstruct(rs, rn) }! object Employee extends SkinnyCRUDMapper[Employee] {! def extract(rs: WrappedResultSet, rn: ResultName[Employee]) =! autoConstruct(rs, rn, “company”)! // simple association definition! lazy val companyRef = belongsTo[Company](! Company, (e, c) => e.copy(company = c)) }
  • 32. Reasonable? Right, these CRUD operations are not SQL-ish. However, I believe they’re reasonable because these patterns are already common enough. ! ! val companyId = Company.createWithAttributes(‘name -> “Sun”)! val empId = Employee.createWithAttributes(! ‘name -> “Alice”, ‘companyId -> companyId)! ! val emp: Option[Employee] = Employee.findById(empId)! val empWithCompany: Option[Employee] = ! Employee.joins(companyRef).findById(123)! ! Company.updateById(companyId).withAttributes(‘name -> “Oracle”)! ! val e = Employee.defaultAlias! Employee.deleteBy(sqls.eq(e.id, empId))! Using ScalikeJBDC API! Company.deleteById(companyId) is also possible
  • 34. Not Only Compiler • It’s true that compiler helps you by detecting mistakes in coding • Writing tests is a reasonable way to verify your code meets requirements / specifications as expected • You can’t skip automated tests even if your apps are written in Scala
  • 35. scoverage • At this time, the only option available for us is scoverage (SCCT inheritor) • Add the dependency into your projects right now if you don’t use it yet
  • 37. Avoid SBT Hacks • sbt is not so easy for Scala newbies, upgrading sbt is all the more so • Play depends on sbt version (e.g. Play 2.1 w/ sbt 0.12), upgrading Play is about not only Play API changes but sbt things • Your own sbt plugins/hacks make your projects difficult to maintain for a long period and involve others • Don’t try to do everything there
  • 38. Skinny TaskRunner • Just want a simple and “rake”-like task runner (no sbt plugin) • Simplistic but pragmatic idea: “mainClass” of “task” sbt project can be dispatcher of task runner system • Tasks are written in Scala (no sbt plugin) • Not only writing code but upgrading scala/sbt version become pretty easy
  • 39. Tasks // sbt settings! // mainClass := Some("TaskRunner")! ! // task/src/main/scala/TaskRunner.scala! object TaskRunner extends skinny.task.TaskLauncher {! register("assets:precompile", (params) => {! val buildDir = params.headOption.getOrElse(“build")! // AssetsPrecompileTask is a Scala object! skinny.task.AssetsPrecompileTask.main(Array(buildDir))! })! }! Pure Scala function! ! // skinny task:run assets:precompile [dir] task name mainClass as the dispatcher
  • 40. Use Only Essentials • The same issue as Ruby gems, what’s worse, Scala’s eco-system is still so smaller than Ruby’s one • Binary incompatibility makes existing libraries outdated every Scala major version release • Are you really ready to fork them? • Using Java assets (e.g. commons) internally is also worth thinking about
  • 41. No Surprises for Newcomer
  • 42. Can Feel Welcome? • Is joining your Scala projects easy? Can newcomer understand overview at once? • Don’t stick to doing on the sbt, don’t disfavor using other tools (e.g. Grunt) • Well-known style (e.g. Rails style) is preferred for collaborative works • Is asynchronosity really required now? • Indeed, your DSL is very simple but easy to modify them (for others)?
  • 43. Newcomers may not know Scala well. Attract them to Scala! (Don’t scare them)
  • 44. AMA! #ScalaMatsuri2 • Unconference tomorrow • “Ask Me Anything” • ScalikeJDBC • Skinny Framework • AWScala • Anything else!
  • 48. Thanks • Amazing “Maturi Urakata” (the conference volunteer staff) • Great invited speakers • You all here!