Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
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
740
presentation of the Play! Framework
yanns
0
280
Other Decks in Programming
See All in Programming
AI主導のプログラミング学習アプリを作ってみた
econanringo
0
180
個人開発者よ、Honoを使え(おじさんver)
tanahiro2010
2
270
Simple Storage Service(S3) is not simple
iwatsukayura
0
310
[2026-10-09]一枚の布で作らなくてもいい。 信頼性は「パッチワーク」で紡がれる~既存の運用と新しい可能性をつなぎ合わせてきたCREの話~
tosite
0
110
Unity6 URPによる海底をテーマにしたVJシステムの解説 | Unity Shader 完全に理解した 勉強会
gam0022
0
370
コードレビューのボトルネックを"する側"と"される側"の両面から解消する
yub0n
2
1.7k
[JA] Domain Modeling with Vanilla Rails: 「操作」から再考するRailsの設計論
yasaichi
4
750
AI-Powered Domain-Driven Design
ziobrando
0
240
複雑なUIコンポーネントとの ⻑い付き合い⽅:波及するバグからテスト戦略を経て、安全な再設計へ
mixplace
0
450
HTML-in-Canvasで作る未来のWeb UI表現
clockmaker
5
5.2k
當我們開始不讀 Code - AI Agent 時代,Code Review 與 Clean Code 還剩下什麼?
jame2408
1
300
3回つくってわかった、 定期実行ジョブ基盤の本質情報
takai
0
610
Featured
See All Featured
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
260
Accessibility Awareness
sabderemane
1
250
The untapped power of vector embeddings
frankvandijk
2
1.9k
A better future with KSS
kneath
240
18k
The World Runs on Bad Software
bkeepers
PRO
72
12k
First, design no harm
axbom
PRO
2
1.3k
Visualization
eitanlees
153
17k
Agile that works and the tools we love
rasmusluckow
331
22k
Odyssey Design
rkendrick25
PRO
2
880
Chasing Engaging Ingredients in Design
codingconduct
0
370
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
560
The #1 spot is gone: here's how to win anyway
tamaranovitovic
4
1.2k
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