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
今ならAmazon ECSのサービス間通信をどう選ぶか / Selection of ECS Interservice Communication 2025
tkikuc
19
3.5k
プロダクト志向ってなんなんだろうね
righttouch
PRO
0
160
Benchmark
sysong
0
270
PHPでWebSocketサーバーを実装しよう2025
kubotak
0
160
つよそうにふるまい、つよい成果を出すのなら、つよいのかもしれない
irof
1
300
CursorはMCPを使った方が良いぞ
taigakono
1
170
ruby.wasmで多人数リアルタイム通信ゲームを作ろう
lnit
2
270
Select API from Kotlin Coroutine
jmatsu
1
190
#kanrk08 / 公開版 PicoRubyとマイコンでの自作トレーニング計測装置を用いたワークアウトの理想と現実
bash0c7
1
420
High-Level Programming Languages in AI Era -Human Thought and Mind-
hayat01sh1da
PRO
0
180
WindowInsetsだってテストしたい
ryunen344
1
190
5つのアンチパターンから学ぶLT設計
narihara
1
110
Featured
See All Featured
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.7k
Speed Design
sergeychernyshev
32
1k
Visualization
eitanlees
146
16k
How GitHub (no longer) Works
holman
314
140k
How STYLIGHT went responsive
nonsquared
100
5.6k
The Cult of Friendly URLs
andyhume
79
6.5k
GitHub's CSS Performance
jonrohan
1031
460k
Adopting Sorbet at Scale
ufuk
77
9.4k
Optimising Largest Contentful Paint
csswizardry
37
3.3k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
7
700
The Straight Up "How To Draw Better" Workshop
denniskardys
234
140k
Into the Great Unknown - MozCon
thekraken
39
1.9k
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