Upload
franco-lombardo
View
1.868
Download
1
Embed Size (px)
Citation preview
A first date with Scala
Franco LombardoXP User Group - Bergamo
http://www.francolombardo.net
Edward Hopper - Summertime
First of all, you must know…
http://www.francolombardo.net
…I’m not a Guru!!!
Scala: passport• IT was born in 2001 at the
Ecoles Polytechniques fédérales de Lausanne
• Firs public release in 2004• Ideated by Martin Odersky,
the father of Java “Generics”
• The compiler generates .class file for the JVM (someone says there’s also a version for .NET )
http://www.francolombardo.net
Claudio Destito – Auto-ritratto
Scala = SCAlable LAnguage
http://www.francolombardo.net
In order to “scale” you need solid basis!
• Widespread virtual machine• Libraries/frameworks/application servers created in Java are immediately available in Scala• Base syntax very close to Java, so it’s very appealing for a great number of programmers
The base of Scala is Java
Here is our star: Hello World!!!
http://www.francolombardo.net
package hello
import java.util.Date
object Hello extends Application { println("Yet another Hello World program")
val jvmVer = System.getProperty("java.version") println("Running on JMV " + jvmVer)
println("On " + new Date())}
Yet another Hello World programRunning on JMV 1.6.0_13On Sat May 23 17:36:34 CEST 2009
Output
Here is our star: Hello World!!!
http://www.francolombardo.net
package hello
import java.util.Date
object Hello extends Application { println("Yet another Hello World program")
val jvmVer = System.getProperty("java.version") println("Running on JMV " + jvmVer)
println("On " + new Date())}
Basic syntax very close to Java
Here is our star: Hello World!!!
http://www.francolombardo.net
package hello
import java.util.Date
object Hello extends Application { println("Yet another Hello World program")
val jvmVer = System.getProperty("java.version") println("Running on JMV " + jvmVer)
println("On " + new Date())}
Object from java.lang are imported by default
Here is our star: Hello World!!!
http://www.francolombardo.net
package hello
import java.util.Date
object Hello extends Application { println("Yet another Hello World program")
val jvmVer = System.getProperty("java.version") println("Running on JMV " + jvmVer)
println("On " + new Date())}
Object from Java libraries are easly avaible
Here is our star: Hello World!!!
http://www.francolombardo.net
package hello
import java.util.Date
object Hello extends Application { println("Yet another Hello World program")
val jvmVer = System.getProperty("java.version") println("Running on JMV " + jvmVer)
println("On " + new Date())}
Simplified syntax: semicolon is not mandatory
Here is our star: Hello World!!!
http://www.francolombardo.net
package hello
import java.util.Date
object Hello extends Application { println("Yet another Hello World program")
val jvmVer = System.getProperty("java.version") println("Running on JMV " + jvmVer)
println("On " + new Date())}
Simplified syntax: less code
Here is our star: Hello World!!!
http://www.francolombardo.net
package hello
import java.util.Date
object Hello extends Application { println("Yet another Hello World program")
val jvmVer = System.getProperty("java.version") println("Running on JMV " + jvmVer)
println("On " + new Date())}
Simplified syntax: type inference
http://www.francolombardo.net
//Java return customer.getOrder(40) .getRow(20) .getItem() .getWeight() * 2.5;
Type inference: have you ever seen it?
(OK, in this example we do not obey Demeter law, but it’s only an example…)
http://www.francolombardo.net
Tools for scalability: static typing
• The compiler gives lots of automatic tests on the code for free
• Enhanced refactorings• Better average performances (OK, not always, but
Scala substituted Ruby at Twitter for performances issues)
• Static typing is a clear and automatic tool for code documentation
http://www.francolombardo.net
Tools for scalbility: “pure” Object Orientation
• Every value is an object• Every operation is a method call (so we can
redefine operators easily) 2 + 5 //equals to... 2.+(5)
Syntactic tricks to improve readability:• Starting method names with letters is not mandatory• In some cases points and parenthesis are not mandatory
http://www.francolombardo.net
Tools for scalability: Object Orientation with Traits
• A problem of big Object Oriented systems: objects that can become very fat
Fernando Botero – Bailerina na barra
http://www.francolombardo.net
Tools for scalability: Object Orientation with Traits
//Javapublic class Customer {
public String name() { //some implementation… } public String address() { //some implementation }
• Fat objects: the Customer
http://www.francolombardo.net
Tools for scalability: Object Orientation with Traits
//Javapublic class Customer { //… public Bank preferredBank() { //some implementation… } public Solvability solvability() { //some implementation… }
• Fat objects: the Customer for accounting purposes
http://www.francolombardo.net
Tools for scalability: Object Orientation with Traits
//Javapublic class Customer { //… public Agent zoneAgent() { //some implementation… } public Boolean isToSendEMails() { //some implementation… }
• Fat Objects: the Customer for the CRM system
http://www.francolombardo.net
Tools for scalability: Object Orientation with Traits
//Javapublic class Customer { //… public Carrier[] carriers() { //some implementation… } public Discount[] discounts() { //some implementation… }
• Fat objects: the Customer for orders
http://www.francolombardo.net
Tools for scalability: Object Orientation with Traits
//Javapublic class Customer { //… public Priority schedulingPriority() { //some implementation… } public TechnicalInfo[] standards() { //some implementation… }
• Fat objects: the Customer for production
http://www.francolombardo.net
Tools for scalability: Object Orientation with Traits
• Fat objects: does inheritance help?Customer
name()address()
AccountingCustomer
preferredBank()
solvability()
CRMCustomer
zoneAgent()
isToSendEMails()
ProductionCustomer
schedulingPriority()
standards()
• What if I needed the preferred bank in the CRM module?
http://www.francolombardo.net
Tools for scalability: Object Orientation with Traits
//Scalacase class Customer(name: String, address: String)
trait accountingCstomer { def preferredBank = //some implementation def solvability = //some implementation}
trait CRMCustomer { def zoneAgent = //some implementation def isToSendEMail = //implementation}
• Fat objects: decomposing with Traits
http://www.francolombardo.net
Tools for scalability: Object Orientation with Traits
//Scalaval customer = new Customer(“Lombardo ltd", “Wall Street, 1") with CRMCustomer with AccountingCustomer
• Fat objects: decomposing with Traits
“Dynamic” type composition
http://www.francolombardo.net
Tools for scalability: functional programming
• Functions are base objects of the language, as strings and numbers
• Therefore functions can be arguments and return values of method calls
You can decompose the system in generic functions which you can reuse reducing duplications
Higher order functions
http://www.francolombardo.net
Tools for scalability: functional programming
• Functions don’t have a state: their results are based only on input values.
• A function evaluation has no side effects beside the computation of the result
• Reusing functions is simpler if we don’t need to reproduce a particular state
• We can test code more easily
Referential transparency
http://www.francolombardo.net
Tools for scalability: functional programming
An example: numeric integration…
http://www.francolombardo.net
Tools for scalability: functional programming
…I was joking, let’s use a more “concrete” example
//Here’s an order rowcase class OrderRow(description: String, price: Double, qty: Double) { def amount = price * qty}
//And an orderval order = List(OrderRow("Beer", 5.0, 2), OrderRow("Chips", 2.5, 1))
http://www.francolombardo.net
Tools for scalability: functional programming
//A traditional approach to VAT computation var total = 0.0 for (row <- order) { total += row.amount *0.2 } println("VAT (Total): " + total);
http://www.francolombardo.net
Tools for scalability: functional programming
//A traditional approach to VAT computation var total = 0.0 for (row <- order) { total += row.amount *0.2 } println("VAT (Total): " + total);
We merge 3 operations• Loop
http://www.francolombardo.net
Tools for scalability: functional programming
//A traditional approach to VAT computation var total = 0.0 for (row <- order) { total += row.amount *0.2 } println("VAT (Total): " + total);
We merge 3 operations• Loop• Accumulation
http://www.francolombardo.net
Tools for scalability: functional programming
//A traditional approach to VAT computation var total = 0.0 for (row <- order) { total += row.amount *0.2 } println("VAT (Total): " + total);
We merge 3 operations• Loop• Accumulation
• Computation
http://www.francolombardo.net
Tools for scalability: functional programming
//The computation: it’s a function we can assignval vat = (row: OrderRow) => row.amount * 0.2
//Composition of accumulation and computationdef composition(aggr: (Double, Double) => Double, calculus: (OrderRow => Double)) (partial: Double, row: OrderRow) = aggr(partial, calculus(row))
val totalVat = order.foldLeft(0.0)(composition(_+_, vat))
Let’s decompose these 3 operations
http://www.francolombardo.net
Tools for scalability: functional programming
val totalVat = order.foldLeft(0.0)(composition(_+_, vat))
Let’s decompose these 3 operations
• Loop//Java B b = start; for(final A a : listOfA) { b = method(b, a); } return b;
//ScalalistOfA.foldLeft(start)(method)
http://www.francolombardo.net
Tools for scalability: functional programming
val totalVat = order.foldLeft(0.0)(composition(_+_, vat))
Let’s decompose these 3 operations
• Loop• Accumulation
http://www.francolombardo.net
Tools for scalability: functional programming
val totalVat = order.foldLeft(0.0)(composition(_+_, vat))
Let’s decompose these 3 operations
• Loop• Accumulation• Computation
http://www.francolombardo.net
Tools for scalability: functional programming
val totalAmount = order.foldLeft(0.0)(composition(_+_, _.amount))val maxAmount = order.foldLeft(0.0)(composition(Math.max, _.amount))val maxVat = order.foldLeft(0.0)(composition(Math.max, vat))
We can recompose them in a different way
http://www.francolombardo.net
Structural types
def deleteAllRows(statement: java.sql.Statement) = statement.execute("DELETE FROM MYTABLE")
How can we test this method?
An hand written mock?
The java.sql.Statement interface has 41 methods!!!
(Well, I don’t like frameworks…)
http://www.francolombardo.net
Structural types
def deleteAllRows( statement: {def execute(sql: String): Boolean}) = statement.execute("DELETE FROM MYTABLE")
Let’s modify our method declaring only what we need
http://www.francolombardo.net
Structural types
def testDeleteAllRows() { val mockStatement = new { def execute(sql: String) = { println(sql) //Oppure qualsiasi cosa x test true //Valore di ritorno di execute } }
deleteAllRows(mockStatement)}
Now we can test our code easily
http://www.francolombardo.net
Implicit conversions
class RemoteStatement { def remoteExecute(sql: String) = { println(sql + " executed remotely :-)") true }}
What if we’d need to use a library for doing remote queries?
http://www.francolombardo.net
Implicit conversions
implicit def normalize(remote: RemoteStatement) = new {
def execute(sql: String) = remote.remoteExecute(sql) }
//I can use it even if it is not the exact type!deleteAllRows(new RemoteStatement)
No problem: we can convert on the fly!
http://www.francolombardo.net
Domain Specific Languages
val tenDollars = (4.0 USD) + (6.0 USD)
I’d like to write something like this
Andy Warhol– Dollar sign
http://www.francolombardo.net
Domain Specific Languages
abstract class Currency {def name: String;override def toString = name
}
object Euro extends Currency {def name ="EUR"
}
object Dollar extends Currency {def name = "USD"
}
No problem!
http://www.francolombardo.net
Domain Specific Languages
case class Money[C <: Currency](amount: Double, currency: C) { def + (otherMoney: Money[C]) =
new Money(amount + otherMoney.amount, currency)
override def toString = amount + " " + currency}
No problem!
http://www.francolombardo.net
Domain Specific Languages
object Money { implicit def doubleConverter(d: Double) = new { def EUR = { new Money(d, Euro) }
def USD = { new Money(d, Dollar) }}
No problem!
http://www.francolombardo.net
Domain Specific Languages
object Playground extends BasicClass { def main(args: Array[String]) { 10 PRINT "SCALA ROCKS!" 20 GOTO 10 RUN }}
With these tools we can write very exciting DSLs!
Example created by Szymon Jachim
See http://www.scala-lang.org/node/1403