Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Scala tech talk
Search
Yann Simon
October 07, 2013
Programming
0
140
Scala tech talk
presentation of the Scala language for Java programmers
Yann Simon
October 07, 2013
Tweet
Share
More Decks by Yann Simon
See All by Yann Simon
Structure a Play application with the cake pattern (and test it)
yanns
1
710
presentation of the Play! Framework
yanns
0
270
Other Decks in Programming
See All in Programming
「ちょっと古いから」って避けてた技術書、今だからこそ読もう
mottyzzz
11
6.8k
オープンソースソフトウェアへの解像度🔬
utam0k
16
3k
スマホから Youtube Shortsを見られないようにする
lemolatoon
27
32k
なぜGoのジェネリクスはこの形なのか? Featherweight Goが明かす設計の核心
ryotaros
7
1.1k
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
380
Go Conference 2025: Goで体感するMultipath TCP ― Go 1.24 時代の MPTCP Listener を理解する
takehaya
9
1.7k
Le côté obscur des IA génératives
pascallemerrer
0
150
PHPに関数型の魂を宿す〜PHP 8.5 で実現する堅牢なコードとは〜 #phpcon_hiroshima / phpcon-hiroshima-2025
shogogg
1
240
kiroとCodexで最高のSpec駆動開発を!!数時間で web3ネイティブなミニゲームを作ってみたよ!
mashharuki
0
570
私はどうやって技術力を上げたのか
yusukebe
43
19k
CSC305 Lecture 06
javiergs
PRO
0
240
Server Side Kotlin Meetup vol.16: 内部動作を理解して ハイパフォーマンスなサーバサイド Kotlin アプリケーションを書こう
ternbusty
3
200
Featured
See All Featured
GraphQLとの向き合い方2022年版
quramy
49
14k
Being A Developer After 40
akosma
91
590k
Making Projects Easy
brettharned
120
6.4k
Become a Pro
speakerdeck
PRO
29
5.6k
The Cost Of JavaScript in 2023
addyosmani
55
9k
Scaling GitHub
holman
463
140k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
The Straight Up "How To Draw Better" Workshop
denniskardys
238
140k
Code Reviewing Like a Champion
maltzj
526
40k
Building Adaptive Systems
keathley
44
2.8k
The Language of Interfaces
destraynor
162
25k
Transcript
Scala
Who am I?
Yann Simon @simon_yann
None
Why Scala?
Fear to lose job?
None
None
None
Java can be pain #1
public String createInvoiceName( Date invoiceDate, String invoiceId, String userId, String
firmId, boolean directInvoice, boolean firmInvoice, boolean electronic) { // ...
String newInvoiceId = invoiceCreator.createInvoiceName( new Date(), "45AE-45F", "872346", "abc-234", true,
false, false );
let's make it readable
String newInvoiceId = invoiceCreator.createInvoiceName( new Date(), // invoiceDate "45AE-45F", //
invoiceId "872346", // userId "abc-234", // firmId true, // directInvoice false, // firmInvoice false // electronic );
OO maybe?
public class NewInvoiceNameCommand { private final Date invoiceDate; private final
String invoiceId; private final String userId; private final String firmId; private final boolean directInvoice; private final boolean firmInvoice; private final boolean electronic; public NewInvoiceNameCommand( Date invoiceDate, String invoiceId, String userId, String firmId, boolean directInvoice, boolean firmInvoice, boolean electronic) { this.invoiceDate = invoiceDate; this.invoiceId = invoiceId; this.userId = userId; this.firmId = firmId; this.directInvoice = directInvoice; this.firmInvoice = firmInvoice; this.electronic = electronic; } public Date getInvoiceDate() { return invoiceDate; } public String getInvoiceId() { return invoiceId; } public String getUserId() { return userId; } public String getFirmId() { return firmId; } public boolean isDirectInvoice() { return directInvoice; } public boolean isFirmInvoice() { return firmInvoice; } public boolean isElectronic() { return electronic; } }
public String createInvoiceName( NewInvoiceNameCommand newInvoiceNameCommand) { // ... return "id";
} String newInvoiceId = invoiceCreator.createInvoiceName( newInvoiceNameCommand);
NewInvoiceNameCommand newInvoiceNameCommand = new NewInvoiceNameCommand( new Date(), "45AE-45F", "872346", "abc-234",
true, false, false );
builder pattern to the rescue
public class NewInvoiceNameCommand { public static class NewInvoiceNameCommandBuilder { private
Date invoiceDate; private String invoiceId; private String userId; private String firmId; private boolean directInvoice; private boolean firmInvoice; private boolean electronic; public NewInvoiceNameCommand build() { return new NewInvoiceNameCommand( invoiceDate, invoiceId, userId, firmId, directInvoice, firmInvoice, electronic); } public NewInvoiceNameCommandBuilder withInvoiceDate(Date invoiceDate) { this.invoiceDate = invoiceDate; return this; } public NewInvoiceNameCommandBuilder withInvoiceId(String invoiceId) { this.invoiceId = invoiceId; return this; } [...] } } private final Date invoiceDate; private final String invoiceId; private final String userId; private final String firmId; private final boolean directInvoice; private final boolean firmInvoice; private final boolean electronic; private NewInvoiceNameCommand( Date invoiceDate, String invoiceId, String userId, String firmId, boolean directInvoice, boolean firmInvoice, boolean electronic) { this.invoiceDate = invoiceDate; this.invoiceId = invoiceId; this.userId = userId; this.firmId = firmId; this.directInvoice = directInvoice; this.firmInvoice = firmInvoice; this.electronic = electronic; } public Date getInvoiceDate() { return invoiceDate; } public String getInvoiceId() { return invoiceId; } public String getUserId() { return userId; } public String getFirmId() { return firmId; } public boolean isDirectInvoice() { return directInvoice; } public boolean isFirmInvoice() { return firmInvoice; } public boolean isElectronic() { return electronic; }
NewInvoiceNameCommand newInvoiceNameCommand = new NewInvoiceNameCommand.NewInvoiceNameCommandBuilder() .withInvoiceDate(new Date()) .withInvoiceId("45AE-45F") .withUserId("872346") .withFirmId("abc-234")
.withDirectInvoice(true) .withFirmInvoice(false) .withElectronic(false) .build(); String newInvoiceId = invoiceCreator.createInvoiceName(newInvoiceNameCommand);
with default values
public class NewInvoiceNameCommand { public static class NewInvoiceNameCommandBuilder { private
Date invoiceDate; private String invoiceId; private String userId; private String firmId; private boolean directInvoice; private boolean firmInvoice; private boolean electronic; public NewInvoiceNameCommandBuilder() { // default values this.directInvoice = true; this.firmInvoice = false; } public NewInvoiceNameCommand build() { return new NewInvoiceNameCommand( invoiceDate, invoiceId, userId, firmId, directInvoice, firmInvoice, electronic); }
NewInvoiceNameCommand newInvoiceNameCommand = new NewInvoiceNameCommand.NewInvoiceNameCommandBuilder() .withInvoiceDate(new Date()) .withInvoiceId("45AE-45F") .withUserId("872346") .withFirmId("abc-234")
.withElectronic(false) .build(); String newInvoiceId = invoiceCreator.createInvoiceName(newInvoiceNameCommand);
better!
just need some glue
public class NewInvoiceNameCommand { public static class NewInvoiceNameCommandBuilder { private
Date invoiceDate; private String invoiceId; private String userId; private String firmId; private boolean directInvoice; private boolean firmInvoice; private boolean electronic; public NewInvoiceNameCommandBuilder() { // default values this.directInvoice = true; this.firmInvoice = false; } public NewInvoiceNameCommand build() { return new NewInvoiceNameCommand( invoiceDate, invoiceId, userId, firmId, directInvoice, firmInvoice, electronic); } public NewInvoiceNameCommandBuilder withInvoiceDate(Date invoiceDate) { this.invoiceDate = invoiceDate; return this; } public NewInvoiceNameCommandBuilder withInvoiceId(String invoiceId) { this.invoiceId = invoiceId; return this; } public NewInvoiceNameCommandBuilder withUserId(String userId) { this.userId = userId; return this; } public NewInvoiceNameCommandBuilder withFirmId(String firmId) { this.firmId = firmId; return this; } public NewInvoiceNameCommandBuilder withDirectInvoice(boolean directInvoice) { this.directInvoice = directInvoice; return this; } public NewInvoiceNameCommandBuilder withFirmInvoice(boolean firmInvoice) { this.firmInvoice = firmInvoice; return this; } public NewInvoiceNameCommandBuilder withElectronic(boolean electronic) { this.electronic = electronic; return this; } } private final Date invoiceDate; private final String invoiceId; private final String userId; private final String firmId; private final boolean directInvoice; private final boolean firmInvoice; private final boolean electronic; private NewInvoiceNameCommand( Date invoiceDate, String invoiceId, String userId, String firmId, boolean directInvoice, boolean firmInvoice, boolean electronic) { this.invoiceDate = invoiceDate; this.invoiceId = invoiceId; this.userId = userId; this.firmId = firmId; this.directInvoice = directInvoice; this.firmInvoice = firmInvoice; this.electronic = electronic; } public Date getInvoiceDate() { return invoiceDate; } public String getInvoiceId() { return invoiceId; } public String getUserId() { return userId; } public String getFirmId() { return firmId; } public boolean isDirectInvoice() { return directInvoice; } public boolean isFirmInvoice() { return firmInvoice; } public boolean isElectronic() { return electronic; } }
let's try with Scala
def createInvoiceName( invoiceDate: Date, invoiceId: String, userId: String, firmId: String,
directInvoice: Boolean, firmInvoice: Boolean, electronic: Boolean): String = { // ... }
val newInvoiceId = invoiceCreator.createInvoiceName( new Date, "45AE-45F", "872346", "abc-234", true,
false, false )
Scala can be ugly too (surprise #1)
val newInvoiceId = invoiceCreator.createInvoiceName( new Date, // invoiceDate "45AE-45F", //
invoiceId "872346", // userId "abc-234", // firmId true, // directInvoice false, // firmInvoice false // electronic )
comments exist in Scala (surprise #2)
val newInvoiceId = invoiceCreator.createInvoiceName( invoiceDate = new Date, invoiceId =
"45AE-45F", userId = "872346", firmId = "abc-234", directInvoice = true, firmInvoice = false, electronic = false )
Yes, named parameters!
and default values?
def createInvoiceName( invoiceDate: Date, invoiceId: String, userId: String, firmId: String,
directInvoice: Boolean = true, firmInvoice: Boolean = false, electronic: Boolean): String = {
val newInvoiceId = invoiceCreator.createInvoiceName( invoiceDate = new Date, invoiceId =
"45AE-45F", userId = "872346", firmId = "abc-234", electronic = false )
but I want a command object
case class NewInvoiceNameCommand ( invoiceDate: Date, invoiceId: String, userId: String,
firmId: String, directInvoice: Boolean = true, firmInvoice: Boolean = false, electronic: Boolean )
val newInvoiceNameCommand = NewInvoiceNameCommand ( invoiceDate = new Date, invoiceId
= "45AE-45F", userId = "872346", firmId = "abc-234", electronic = false ) val newInvoiceId = invoiceCreator.createInvoiceName( newInvoiceNameCommand)
Java can be pain #2
public int multiplyBy2(int number) { return number * 2; }
[...] public void multiplyUserInputBy2() { Integer userInput = null; multiplyBy2(userInput); }
def multiplyBy2(number: Int): Int = { number * 2 }
def multiplyUserInputBy2 { //val userInput: Int = null // does not compile //val userInput = Int.unbox(new Integer(null)) throws exception val userInput = 2 multiplyBy2(userInput) }
Java can be pain #3
public class User { private final String name; private final
String gender; private final Date dateOfBirth; public User(String name, String gender, Date dateOfBirth) { this.name = name; this.gender = gender; this.dateOfBirth = dateOfBirth; } public String getName() { return name; } public String getGender() { return gender; } public Date getDateOfBirth() { return dateOfBirth; } }
public class User { private final String name; private final
String gender; private final Date dateOfBirth; public User(String name, String gender, Date dateOfBirth) { this.name = name; this.gender = gender; this.dateOfBirth = dateOfBirth; } public String getName() { return name; } public String getGender() { return gender; } public Date getDateOfBirth() { return dateOfBirth; } public Integer getAge() { if (dateOfBirth == null) { return null; } Date now = new Date(); long difference = now.getTime() - dateOfBirth.getTime(); Calendar yearCalculator = Calendar.getInstance(); yearCalculator.setTimeInMillis(difference); return yearCalculator.get(Calendar.YEAR); } }
public class UserBusiness { private final UserRepository userRepository = new
UserRepository(); public boolean isUserAllowed(String name) { User user = userRepository.findUserByName(name); if (user != null) { if (user.getGender() != null && user.getGender().equals("F")) { if (user.getAge() != null && user.getAge() >= 18) { return true; } } } return false; } }
case class User ( name: String, gender: Option[String] = None,
dateOfBirth: Option[Date] = None ) { def age: Option[Int] = dateOfBirth.map { dob => calculateAge(dob) } private def calculateAge(dateOfBirth: Date): Int = { val now = new Date() val difference = now.getTime - dateOfBirth.getTime val yearCalculator = Calendar.getInstance() yearCalculator.setTimeInMillis(difference) yearCalculator.get(Calendar.YEAR) } }
class UserBusiness { val userRepository = new UserRepository() def isUserAllowed(name:
String): Boolean = { val allowedUser = for { user <- userRepository.findUserByName(name) gender <- user.gender if gender == "F" age <- user.age if age >= 18 } yield user allowedUser.isDefined } }
Bye bye NullPointerException
Asynchronous IO
Asynchronous IO - What?
None
None
None
Asynchronous IO - Why?
None
None
None
None
Asynchronous IO in Java
public Promise<JsonNode> searchStock(String query) { Promise<WS.Response> responsePromise = WS.url("http://localhost:9001/search") .setQueryParameter("query",
query) .get(); return responsePromise.map(new F.Function<WS.Response, JsonNode>() { @Override public JsonNode apply(WS.Response response) throws Throwable { if (response.getStatus() == 200) { JsonNode jsonNode = response.asJson(); return jsonNode.findPath("results"); } else { throw new Exception("Error calling search service.\nResponse status " + response.getStatus() + "\n"); } } }); }
Asynchronous IO in Scala
def searchStock(query: String): Future[Seq[JsObject]] = { WS.url("http://localhost:9001/search") .withQueryString("query" -> query)
.get() .map { response => response.status match { case 200 => (response.json \ "results").as[Seq[JsObject]] case _ => throw new Exception(s"Error calling search service.\nResponse status ${response.status}\n") } } }
Three sequential calls
public static Promise<Result> index(String userId) { Promise<User> user = backends.getUserById(userId);
Promise<List<Order>> orders = user.flatMap(new F.Function<User, Promise<List<Order>>>() { @Override public Promise<List<Order>> apply(User user) throws Throwable { return backends.getOrdersForUser(user.getEmail()); } }); Promise<List<Product>> products = orders.flatMap(new F.Function<List<Order>, Promise<List<Product>>>() { @Override public Promise<List<Product>> apply(List<Order> orders) throws Throwable { return backends.getProductsForOrders(orders); } }); Promise<List<Stock>> stocks = products.flatMap(new F.Function<List<Product>, Promise<List<Stock>>>() { @Override public Promise<List<Stock>> apply(List<Product> products) throws Throwable { return backends.getStocksForProducts(products); } }); Promise<List<Object>> promises = Promise.sequence(user, orders, products, stocks); return promises.map(new F.Function<List<Object>, Result>() { @Override public Result apply(List<Object> results) throws Throwable { User user = (User)results.get(0); List<Order> orders = (List<Order>)results.get(1); List<Product> products = (List<Product>)results.get(2); List<Stock> stocks = (List<Stock>)results.get(3); return ok(orders.size() + " order(s) for user " + user.getEmail()); } }); }
def index(userId: String) = Action.async { for { user <-
getUserById(userId) orders <- getOrdersForUser(user.email) products <- getProductsForOrders(orders) stocks <- getStocksForProducts(products) } yield Ok(s"${orders.size} order(s) for user ${user.email}") }
OK, I want to try Scala
Be careful
Scala can be pain #1
✗ slow compilation
✗ slow compilation incremental compilation ~run modules Scala 2.11
Scala can be pain #2
functional programming terrorists
use the most appropriate style for the problem (and for
the maintenance)
Scala can be pain #3
# Scala dev < Java
use this problem as opportunity Ex: “Yes, all of us
were quite experienced Java programmers. [...] Because we were all learning together, this worked really well.”
Online courses: Functional Programming Principles in Scala Principles of Reactive
Programming
Scala User Group Play framework User Group
Trainings http://www.leanovate.de/training/software/
I get it I want to try Scala
Integration in my project?
✔ Maven ✔ ANT ✔ SBT ✔ Gradle
Begin with scala-test?
test("content disposition parser extracts the filename") { val header =
"Attachment; filename=example.html" val filename = ContentDispositionHeader.parse(header).filename assert(filename === Some("example.html")) }
it should "replace ä with ae" in { SwiftLatinCharset.from("fooÄfoo") shouldEqual
"fooAefoo" SwiftLatinCharset.from("fooäfoo") shouldEqual "fooaefoo" }
Integration in my firm?
Continuous Integration
sbt test mvn test ...
✔ ✔ ✔
Scala ✔ Integrate with Java ✔ Integrate with existing build
✔ Usual tools
Build products ✔ efficient development ✔ motivated teams ✔ enable
SOA (async IO) ✔ less lines of code ✔ easier maintenance
✔ focus on your product!
thanks for your attention