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
150
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Scala tech talk
presentation of the Scala language for Java programmers
Yann Simon
October 07, 2013
More Decks by Yann Simon
See All by Yann Simon
Structure a Play application with the cake pattern (and test it)
yanns
1
730
presentation of the Play! Framework
yanns
0
270
Other Decks in Programming
See All in Programming
freee が目指す データ マネジメント戦略 AI-Ready 時代を支える 攻めのガバナンスとは
freee
PRO
0
520
私のClaude Code活用法 (個人開発編) - PHPerKaigi mini #4(2026/08/24)
panda_program
1
190
Japan Community Day at Kubecon + CloudNativeCon Japan 2026: Learning Container Privilege Control by Building My Own Low-Level Container Runtime
ternbusty
1
170
「寝てても仕事が進む」Claude Codeで組む第二の脳
tomoyafujita2016
0
370
片田舎のおっさん、 Swift Buildのダイアモンド問題解決の不具合修正PRを出すが、解決方法がキャッシュをしないようにすることであり、ビルド時間が伸びると言われてマージされないので高速化もする/swiftbuild
yimajo
0
310
実装をデザインガイドラインに追従させるための取り組み / 260731-dip-mosh-design-system
dachi023
0
7.9k
不幸な GC
chencmd
0
810
Webエンジニアなのにブラウザの仕組みがわからないので、Pythonで自作してみた
tatsuki12
4
1.1k
AI Readyの正体はデータマネジメントだ メダリオン2.0の最前線
freee
PRO
0
420
DynamoDBの基礎を振り返りながらベクトル検索機能を理解する
musan
2
240
自動化したのに回らない テスト運用の壁―AI時代の品質責任と生産性
mfunaki
0
530
【デモ】Kiroで体験する仕様駆動開発|設計からコーディングまでAIと進める開発フロー
cmkudo
0
490
Featured
See All Featured
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
260
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
420
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Designing for Performance
lara
611
70k
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
390
Code Reviewing Like a Champion
maltzj
528
40k
How to train your dragon (web standard)
notwaldorf
97
6.8k
A Soul's Torment
seathinner
6
3.5k
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
260
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
480
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
300
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
480
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