Dynamic languages have many benefits but static languages with compile-time checking can also be expressive. The document discusses the rise of dynamic languages on the Java Virtual Machine like Groovy and how they provide benefits like concise syntax and runtime programmability while static languages provide safety through compile-time checking. It then outlines Chris Richardson's presentation agenda on dynamic languages, favorite Groovy features, frustrations with Groovy, and the Scala language which aims to provide both expressiveness and compile-time checking.
Take control of your SAP testing with UiPath Test Suite
Dynamic Languages: the next big thing for the JVM or an evolutionary dead end
1. Dynamic Languages: the
next big thing for the JVM or
an evolutionary dead end?
Chris Richardson
Author of POJOs in Action
Founder of Cloud Tools and Cloud Foundry
y
Chris Richardson Consulting, Inc
www.chrisrichardson.net
2. Overall presentation g
p goal
Dynamic languages have many
benefits
But
Static languages, which have the
languages
safety net of compile-time
checking,
checking can be just as expressive
4/8/2009 Slide 2
Copyright (c) 2009 Chris Richardson. All rights reserved.
3. About Chris
Grew up in England and live in Oakland, CA
•
Over 20+ years of software development
•
experience including 12 years of Java
Author of POJOs in Action
•
Speaker at JavaOne, SpringOne, NFJS,
•
JavaPolis, Spring Experience, etc.
Chair of the eBIG Java SIG in Oakland
•
(www.ebig.org)
Run the Groovy/Grails meetup
•
(http://java.meetup.com/161)
Run a consulting and training company that
u co su t g a d t a g co pa y t at
•
helps organizations reduce development costs
and increase effectiveness
Founder of Cloud Tools, an open-source project
•
for deploying Java applications on Amazon EC2:
http://code.google.com/p/cloudtools
http://code google com/p/cloudtools
Founder of a startup that provides outsourced,
•
automated, and Java-centric datacenter
management on the cloud:
www.cloudfoundry.com
y
4/8/2009 Slide 3
Copyright (c) 2009 Chris Richardson. All rights reserved.
4. Agenda
g
The fall and rise of dynamic
languages
Favorite Groovy features
The frustration of using Groovy
Scala: expressiveness and compile-
p p
time checking
4/8/2009 Slide 4
Copyright (c) 2009 Chris Richardson. All rights reserved.
5. Dynamic vs. static languages
Dynamic (run-time) Static (compile-time)
Types associated with Types associated with
values rather than variables
variables Compile-time
Ability to define new checking of language
program elements at elements and types
runtime Not a new idea
Not a new idea: either:
Lisp – 1958! Algol 60
SmallTalk - 1980
anObject.someMethod(someArgs)
4/8/2009 Slide 5
Copyright (c) 2009 Chris Richardson. All rights reserved.
6. LISP/CLOS – an early (late 1980s)
dynamic language
y gg
(defclass Account ()
((account-id :accessor account-id :initarg :account-id)
Develop by adding and
(balance :accessor account-balance :initarg :balance))
changing p g
g g program
)
elements in a running VM
(defmethod debit ((Account account) amount)
(decf (account-balance account) amount))
(defmethod credit ((Account account) amount)
(incf (account balance account) amount))
(account-balance
CL-USER 5 > (setq a (make-instance 'account :account-id quot;abc123quot; :balance 10.0))
#<ACCOUNT 200C05AF>
CL-USER 6 > (describe a)
#<ACCOUNT 200C05AF> is an ACCOUNT
ACCOUNT-ID quot;abc123quot;
BALANCE 10.0
CL-USER
CL USER 7 > (debit a 5)
5.0
CL-USER 8 > (describe a)
#<ACCOUNT 200C05AF> is an ACCOUNT
ACCOUNT-ID
ACCOUNT ID quot; b 123quot;
quot;abc123quot;
BALANCE 5.0
4/8/2009 6
Copyright (c) 2009 Chris Richardson. All rights reserved.
7. … a very dynamic language
yy gg
(
(defclass Account ()
Existing instances
((account-id :accessor account-id :initarg :account-id)
are updated when
(balance :accessor account-balance :initarg :balance)
the class is redefined
(description :accessor account-description :initarg :description))
)
CL-USER 9 > (describe a)
#<ACCOUNT 2168DCBF> is an ACCOUNT
ACCOUNT-ID quot;abc123quot;
BALANCE 10.0
DESCRIPTION #<unbound slot>
CL-USER 10 > (setf (account-description a) quot;checking accountquot;)
quot;checking accountquot;
CL-USER 11 > (describe a)
#<ACCOUNT 2168DCBF> is an ACCOUNT
ACCOUNT-ID quot;abc123quot;
BALANCE 10.0
DESCRIPTION quot;checking accountquot;
4/8/2009 7
Copyright (c) 2009 Chris Richardson. All rights reserved.
8. Ruby on Rails woke up Java
y p
Ruby on Rails:
Significantly more productive
Simplicity of Convention over
Configuration
C fi ti
Motivated the Java community to
improve
Reopened the debate about
programming l
i languages
4/8/2009 Slide 8
Copyright (c) 2009 Chris Richardson. All rights reserved.
9. Dynamic languages on the JVM
y gg
JRuby
http://jruby.codehaus.org
p //j y g
Ruby on the JVM
Jython
http://www.jython.org/Project
p // jy g/ j
Python on the JVM
Clojure
http://clojure.org/
p j g
Functional programming language
Software Transactional Memory
…
Groovy
http://groovy.codehaus.org/
Java-compatible, dynamic language
4/8/2009 Slide 9
Copyright (c) 2009 Chris Richardson. All rights reserved.
10. Small…
4/8/2009 Slide 10
Copyright (c) 2009 Chris Richardson. All rights reserved.
11. … but growing
g g
4/8/2009 Slide 11
Copyright (c) 2009 Chris Richardson. All rights reserved.
12. Agenda
g
The fall and rise of dynamic
languages
Favorite Groovy features
The frustration of using Groovy
Scala: expressiveness and compile-
p p
time checking
4/8/2009 Slide 12
Copyright (c) 2009 Chris Richardson. All rights reserved.
13. About Groovy
y
Object-oriented, dynamic language
Java compatible
Runs on the JVM
Made popular by the Grails
framework:
Rails-like productivity
Using robust Java frameworks including
g g
Spring and Hibernate
4/8/2009 Slide 13
Copyright (c) 2009 Chris Richardson. All rights reserved.
14. Things I like: Java compatible
g p
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
Java-like syntax
class EC2RequestExecutor {
Use Java libraries
Log logger = LogFactory.getLog(getClass())
public String calculateRFC2104HMAC(String data, String key) {
try {
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(quot;UTF8quot;),
HMAC_SHA1_ALGORITHM)
Mac
M mac = M Mac.getInstance(HMAC_SHA1_ALGORITHM)
tI t (HMAC SHA1 ALGORITHM)
mac.init(signingKey)
byte[] rawHmac = mac.doFinal(data.getBytes())
return new String(Base64.encodeBase64(rawHmac))
}
catch (Exception e) {
throw new RuntimeException(quot;Failed to generate HMAC : quot;, e)
}
}
4/8/2009 Slide 14
Copyright (c) 2009 Chris Richardson. All rights reserved.
15. Groovy is concise and expressive
y p
def configureAsMaster() {
writeFile fileName: quot;/etc/my.cnfquot;, templateName: quot;/templates/master.my.cnfquot;
restartService quot;mysqldquot;
exec command: quot;mysql -u rootquot;,
templateName: quot;/templates/createSchema.sqlquot;,
/templates/createSchema.sql , No parens
Keyword parameters
templateArgs: [schemaSpec: schemaSpec]
executeSchemaScripts()
}
class TomcatServer { tomcatServer.contexts
No
N get…()
t ()
def getContexts() {
webApps.context
}
}
4/8/2009 Slide 15
Copyright (c) 2009 Chris Richardson. All rights reserved.
16. Literals for lists and maps
p
def myList = [“a”, “b”, “c”]
def params = ['Action': 'RunInstances',
'MinCount': n.toString(), 'MaxCount': n.toString(),
' ImageId': awsProperties.quot;imageId.${instanceType}quot;,
'KeyName': awsProperties.keyName,
' InstanceType': instanceType] + extraParams
def response = requestor executeRequest(params)
requestor.executeRequest(params)
4/8/2009 Slide 16
Copyright (c) 2009 Chris Richardson. All rights reserved.
17. GStrings
g
def schemaScript = quot;quot;quot;
DROP SCHEMA IF EXISTS ${schemaSpec.name};
CREATE SCHEMA ${schemaSpec.name};
quot;quot;quot;
4/8/2009 Slide 17
Copyright (c) 2009 Chris Richardson. All rights reserved.
18. Closures
public EC2Server findInstance(String instanceId) {
def
d f server = servers.find {i t
fi d {instanceId == it i t
Id it.instanceId}
Id}
if (server)
return server
else throw new RuntimeException( )
RuntimeException(….)
}
Simplified collection processing
4/8/2009 Slide 18
Copyright (c) 2009 Chris Richardson. All rights reserved.
19. Closures – new control structures
public class Ssh {
p
public Object withTunnel(String publicDnsName, int localPort, int remotePort, Closure closure) {
j ( gp , , , )
SshConnection sshConnection = makeSshConnection(publicDnsName);
try {
sshConnection.connect()
…
return closure.call()
} finally {
fi ll
sshConnection.close()
}
}
}
class EC2 {
String snapshotEbsVolume(String hostName, EbsVolume ebsVolume, String schemaName) {
int localPort = PortUtil.allocatePort()
def result = ssh.withTunnel(hostName, localPort, 3306) {
( , , )
…
}
return (String)result
}
}
4/8/2009 Slide 19
Copyright (c) 2009 Chris Richardson. All rights reserved.
20. An interactive shell
Great for experimentation and learning
4/8/2009 Slide 20
Copyright (c) 2009 Chris Richardson. All rights reserved.
21. Simple reusable code
p
Java:
interface Quackable {
void quack();
q ();
complexity of
l it f
}
generics
class QuackableContainer<T extends Quackable>
void add(T element) {
element.quack();
…
}
…
}
Groovy: just assume that
c ass Quac ab eCo ta e
class QuackableContainer {
there is a quack()
void add(T element) {
method
element.quack()
…
}
4/8/2009 Slide 21
Copyright (c) 2009 Chris Richardson. All rights reserved.
22. Groovy metaclasses
y
public class StringMetaclassExampleTest extends GroovyTestCase {
void testAddMethodToString() {
String.metaClass.doubleString = { -> delegate + delegate }
String.metaClass.static.makePowerString = { String s, int n ->
def result = s
n.times { result = result.doubleString() }
result
}
assertEquals quot;CommunityOne EastCommunityOne Eastquot;,
quot;CommunityOne Eastquot;.doubleString()
CommunityOne East doubleString()
assertEquals quot;NewYorkNewYorkNewYorkNewYorkquot;,
String.makePowerString(quot;NewYorkquot;, 2)
}
}
Runtime definition of program elements
pg
4/8/2009 Slide 22
Copyright (c) 2009 Chris Richardson. All rights reserved.
23. Method Missing
g
public class ClassWithMissingMethods {
Object methodMissing(String name, args) {
Closure method = makeMethodImplementation(name)
if (method) {
method(args)
} else {
throw new MissingMethodException(name, getClass(), args)
}
}
def makeMethodImplementation(String name) {
….
}
}
def foo = new ClassWithMissingMethods()
g ()
foo.nonExistentMethod()
4/8/2009 Slide 23
Copyright (c) 2009 Chris Richardson. All rights reserved.
24. XML and GPath expressions
p
<RunInstancesResponse>
…
<instancesSet>
<item>
<instanceId>i-4ef21327</instanceId>
<imageId>ami-3795705e</imageId>
<instanceState>
<code>0</code>
def client = new HttpClient() <name>pending</name>
… </instanceState>
<dnsName/>
def responseStream =
…
getMethod.getResponseBodyAsStream()
getMethod getResponseBodyAsStream()
</RunInstancesResponse>
def parser = new XmlParser(false, false)
def response = parser.parseText(responseStream)
def newServers = response instancesSet.item collect {
response.instancesSet.item.collect
new EC2Server(this, awsProperties, ssh,
it.instanceId.text(),
it.instanceState.name.text())
}
4/8/2009 Slide 24
Copyright (c) 2009 Chris Richardson. All rights reserved.
25. Builders
def report(String path, hosts, cpuCount, threadCount) {
def builder = new groovy.xml.MarkupBuilder(new OutputStreamWriter(new FileOutputStream(path)))
builder.performanceReport {
cpus cpuCount
threads threadCount
hosts.entrySet().each { hostEntry ->
host {
name hostEntry.key <performanceReport>
cpuUtil hostEntry value getAverageBusy()
hostEntry.value.getAverageBusy() <cpus>1</cpus>
} <threads>10</threads>
} <host>
requests {
<name>database</name>
timings.entrySet().sort{ a, b-> a.key <=> b.key}.each{ pair ->
request { <cpuUtil>3.27</cpuUtil>
name pair key
pair.key </host>
art pair.value.average() <host>
errors pair.value.errorPercentage() <name>tomcat0</name>
}
<cpuUtil>94.32</cpuUtil>
}
} </host>
def durationValue = ((fl t)( dTi
d fd ti V l ((float)(endTime - startTime))/1000.0
t tTi ))/1000 0 …
duration durationValue <duration>557.943</duration>
def tpsValue = transactionCount/ durationValue <tps>10.753786677133686</tps>
tps tpsValue
<art>916.6578333333</art>
art averageResponseTime()
} </performanceReport>
}
4/8/2009 Slide 25
Copyright (c) 2009 Chris Richardson. All rights reserved.
26. Grails/GORM p
/ persistence methods
class Customer { Implemented using
String name
g metaclasses and method
} missing
Customer c = new Customer(quot;John Doequot;)
Ct Ct (quot;J h D quot;)
if (!c.save())
fail quot;validation failed: ${c.errors}quot;
Customer c2 = Customer.get(c.id)
c2.delete()
assertNull Customer.get(c.id)
def customers = Customer findAllByName(“Fred”)
Customer.findAllByName( Fred )
4/8/2009 Slide 26
Copyright (c) 2009 Chris Richardson. All rights reserved.
27. Agenda
g
The fall and rise of dynamic
languages
Favorite Groovy features
The frustration of using Groovy
Scala: expressiveness and compile-
p p
time checking
4/8/2009 Slide 27
Copyright (c) 2009 Chris Richardson. All rights reserved.
28. Getting Groovy code to work can
be frustrating
g
Dynamic language = less information
for IDE:
Limited compile-time checking
Limited refactorings
Limited completion
4/8/2009 Slide 28
Copyright (c) 2009 Chris Richardson. All rights reserved.
29. Groovy fans say quot;write unit tests“
BUT…
Groovy
When you have typos
versus
Java
4/8/2009 Slide 29
Copyright (c) 2009 Chris Richardson. All rights reserved.
30. Unit tests don't always catch errors
y
void testPollStatus_discoveringNewServer() {
mockEC2RequestExecutor.demand.executeRequest {params ->
….
}
def mockEC2Server = new MockFor(EC2Server.class)
….
mockEC2Server.use {
mockEC2RequestExecutor.use {
ec2 = new EC2(awsProperties)
ec2.pollStatus() public class EC2 {
assertEquals 1, ec2.servers.size()
} public pollStatus() {
} def params = ['Action':
} 'DescribeInstances']
def p =
requestor.executeRequest(params)
requestor executeRequest(params)
class EC2RequestExecutor { …
}
public Node executeEc2Request(Map …
parameters) { Method signature changes are
}
… often missed
ft i d
}
Slide 30
4/8/2009 Copyright (c) 2009 Chris Richardson. All rights reserved.
31. The trouble with duck typing
yp g
Interface between components not
defined in a single place
It is scattered throughout caller
Difficult to understand
Difficult to change
g
4/8/2009 Slide 31
Copyright (c) 2009 Chris Richardson. All rights reserved.
32. The outcome: fear of change
g
Did my tests
catch all
the obvious errors?
4/8/2009 Slide 32
Copyright (c) 2009 Chris Richardson. All rights reserved.
33. Writing Java becomes frustrating
g g
Importing the obvious, e.g. java.util
Tedious collection manipulation
Painful XML processing
p g
Repetitive type declarations
4/8/2009 Slide 33
Copyright (c) 2009 Chris Richardson. All rights reserved.
34. Agenda
g
The fall and rise of dynamic
languages
Favorite Groovy features
The frustration of using Groovy
Scala: expressiveness and
p
compile-time checking
4/8/2009 Slide 34
Copyright (c) 2009 Chris Richardson. All rights reserved.
35. Distilling a language
g gg
4/8/2009 Slide 35
Copyright (c) 2009 Chris Richardson. All rights reserved.
36. Scala – a modern (2003) static
language
gg
Object-oriented
Pure object-oriented language
All values are objects
Class-based
Traits support quot;multiple inheritancequot;
Functional
Functions are values
Higher-order functions
Currying
Statically typed
Expressive
Type inference
Extensible t support d
Et ibl to t domain specific languages
i ifi l
Methods as infix and postfix operators
Automatic closure construction
Fully interoperable with Java
4/8/2009 Slide 36
Copyright (c) 2009 Chris Richardson. All rights reserved.
37. Simple example
p p
object StringFunctions {
def reverseSentence(sentence : String) = sentence.split(quot; quot;).reverse.mkString(quot; quot;)
}
import org.junit._
import Assert._
@Test
class StringFunctionsTest {
@Test
def testReverseSentence() = {
val input = quot;Hello New Yorkquot;
val expected = quot;York New Helloquot;
assertEquals(expected, StringFunctions.reverseSentence(input))
}
}
4/8/2009 Slide 37
Copyright (c) 2009 Chris Richardson. All rights reserved.
38. Collection literals example
p
@Test
class ScalaCollectionExamplesTest {
@Test
def listExample() = {
val myList = List(1, 2, 3)
assertEquals(3, myList.length)
assertEquals(List(0, 1, 2, 3)
assertEquals(List(0 1 2 3), 0::myList)
assertEquals(List(2, 3), myList.tail)
assertEquals(1, myList.head)
}
@Test
def testMapExampleList() : Unit = {
val myMap = Map( quot;xquot; -> 1, quot;yquot; -> 2, quot;zquot; -> 3)
assertEquals(1, myMap(quot;xquot;))
}
}
4/8/2009 Slide 38
Copyright (c) 2009 Chris Richardson. All rights reserved.
39. Closure example
p
@Test
class ScalaCollectionExamplesTest {
@Test
def testMapList() = {
p ()
val myList = List(1, 2, 3)
assertEquals(List(2,4,6), myList.map ( x => x * 2))
assertEquals(List(2,4,6), myList.map ( _ * 2))
}
@Test
def testFilterList() = {
val myList = List(1, 2, 3)
assertEquals(List(1, 3), myList.filter( _ % 2 == 1));
}
}
4/8/2009 Slide 39
Copyright (c) 2009 Chris Richardson. All rights reserved.
40. Pattern matching
g
case class Organization(name: String,
industry: Industry.Value, revenue: Double, assets: Double, liabilities: Double) {
}
object Industry extends Enumeration {
val Banking, GreenEnergy, IT, Other = Value
}
class LoanApprovalPolicy {
def isLoanApproved(organization : Organization) = organization match {
case Organization(_, Industry.GreenEnergy, _, _, _) => true
case Organization(_, Industry.Banking, _, assets, liabilities)
if liabilities < assets * 1.5 => true
case O
Organization(_, I d t B ki
i ti ( Industry.Banking, _, _, _) => false
) fl
case Organization(_, _, _, assets, liabilities) if assets > liabilities => true
case _ => false
}
}
4/8/2009 Slide 40
Copyright (c) 2009 Chris Richardson. All rights reserved.
41. XML generation
g
@Test
class ScalaXmlExampleTest {
@Test
def xmlLiterals() {
val now = new Date()
val loanRequestor =
new Organization(quot;Community Bank, Incquot;, Industry.Banking, 10, 10, 5)
val doc = <loanRequest>
<time>{now.getTime()}</time>
<requester>{loanRequestor.name}</requester>
<industry>{loanRequestor.industry}</industry>
<revenue>{loanRequestor.revenue}</revenue>
<assets>{loanRequestor.assets}</assets>
<liabilities>{loanRequestor.liabilities}</liabilities>
</loanRequest>
</l R t>
val docAsString : String = doc.toString()
println(docAsString)
}
4/8/2009 Slide 41
Copyright (c) 2009 Chris Richardson. All rights reserved.
42. XML parsing
p g
class ScalaXmlExampleTest {
@Test
def xmlProcessing() {
val doc = xml.XML.loadString(docAsString)
assertEquals (quot;Community Bank, Incquot;, (doc quot;requesterquot;).text)
node match {
case <loanRequest>{children @ _* }</loanRequest> =>
for (x <- children if !x.isInstanceOf[scala.xml.Text]) {
processChildren(x)
}
}
}
def processChildren(node : scala.xml.Node ) = {
node match {
d th
case <time>{value}</time> => println(value.text)
case <requester>{value}</requester> => println(value.text)
…
}
}
4/8/2009 Slide 42
Copyright (c) 2009 Chris Richardson. All rights reserved.
43. DSL Example
p
class OrganizationDslTest {
val o : Organization = (Organization
called quot;Bernie Madoff & Associatesquot;
Bernie Associates
in Industry.Banking
withRevenuesOf (10 million)
withAssetsOf (10 billion)
withLiabilitiesOf (30 billion))
object Organization {
}
def called(name : String) = new OrganizationBuilder(name)
class OrganizationBuilder(name : String) {
g ( g)
var industry : Industry.Value = null
def in(industry : Industry.Value) = { this.industry = industry; this }
def withRevenuesOf(…) = …
…
def make()= new Organization(name industry revenue assets, liabilities)
Organization(name, industry, revenue, assets
}
implicit def organizationBuilderToOrganization(builder : OrganizationBuilder)
= builder.make
}
4/8/2009 Slide 43
Copyright (c) 2009 Chris Richardson. All rights reserved.
44. Constructing object hierarchies
g j
object ExampleSwingApp extends SimpleGUIApplication {
def top = new MainFrame {
title = quot;Example Swing Appquot;
val button = new Button {
text = quot;pressquot;
press
}
contents = button
var count = 0
t
listenTo(button)
reactions += {
case ButtonClicked(b) =>
count = count + 1
Console.println(count);
b.text = quot;press: quot; + count
}
}
}
4/8/2009 Slide 44
Copyright (c) 2009 Chris Richardson. All rights reserved.
45. Scala command line
4/8/2009 Slide 45
Copyright (c) 2009 Chris Richardson. All rights reserved.
46. Traits
Consist of members
methods
fields
types
The members can be abstract
Multiple traits can be mixed into a
class
Alternative to multiple inheritance
Class must define abstract members
4/8/2009 Slide 46
Copyright (c) 2009 Chris Richardson. All rights reserved.
47. Dependency injection in Scala
p yj
Dependency injection = component
definition and composition
Traditional approach
Metadata: XML, annotations
Framework: Spring, Guice, EJB3
Scala: use traits and other language
features
4/8/2009 Slide 47
Copyright (c) 2009 Chris Richardson. All rights reserved.
48. Dependency injection –
Spring/Java example
p g/ p
Names a
@Component(quot;organizationRepositoryquot;)
component and
p class OrganizationRepositoryImpl extends OrganizationRepository {
specifies it's …
implementation }
@Component(quot;loanProcessingServicequot;)
class LoanProcessingServiceImpl extends LoanProcessingService{
Expresses a @Autowired
dependency private OrganizationRepository organizationRepository;
void processLoan( ) {
processLoan(….)
}
…
}
4/8/2009 Slide 48
Copyright (c) 2009 Chris Richardson. All rights reserved.
49. Dependency injection - repository
p yj p y
trait OrganizationRepositoryComponent {
Names a
component
p val organizationRepository : OrganizationRepository
and defines
it's interface trait OrganizationRepository {
def findByName(name : String) : Organization
}
}
Specifies the
implementation
trait OrganizationRepositoryComponentImpl extends OrganizationRepositoryComponent {
val organizationRepository = new OrganizationRepositoryImpl()
class OrganizationRepositoryImpl extends OrganizationRepository {
def findByName(name : String) = {
d f fi dB N ( Si )
… Access the database here…
}
}
}
4/8/2009 Slide 49
Copyright (c) 2009 Chris Richardson. All rights reserved.
50. Dependency injection - service
p yj
trait LoanProcessingServiceComponent {
Expresses a
val loanProcessingService : LoanProcessingService
dependency
trait LoanProcessingService {
def processLoan(organizationName : String )
}
}
trait LoanProcessingServiceComponentImpl extends LoanProcessingServiceComponent
{ this : OrganizationRepositoryComponent =>
val loanProcessingService = new LoanProcessingServiceImpl()
val policy = new LoanApprovalPolicy()
class LoanProcessingServiceImpl extends LoanProcessingService {
def processLoan(organizationName : String ) = {
val organization = organizationRepository.findByName(organizationName)
if ( li i L
(policy.isLoanApproved(organization)) {
A d( i i ))
// process the loan
} else {
throw new LoanRequestRejectedException()
….
}
4/8/2009 Slide 50
Copyright (c) 2009 Chris Richardson. All rights reserved.
51. Dependency injection - application
p yj pp
object LoanProcessingApplication
extends LoanProcessingServiceComponentImpl
with OrganizationRepositoryComponentImpl {
}
LoanProcessingApplication.loanProcessingService.processLoan(quot;Green Coquot;)
4/8/2009 Slide 51
Copyright (c) 2009 Chris Richardson. All rights reserved.
52. Dependency injection – testing
p yj g
class LoanProcessingApplicationTest {
trait OrganizationRepositoryComponentStub extends OrganizationRepositoryComponent {
val organizationRepository = new OrganizationRepositoryStubImpl()
class OrganizationRepositoryStubImpl extends OrganizationRepository {
def findByName(name : String) = {
name match {
case quot;Bernie Madoff & Associatesquot; => new Organization(…)
…
}
}
}
}
object LoanProcessingApplicationWithStub extends
LoanProcessingServiceComponentImpl with OrganizationRepositoryComponentStub {
g p p g p y p
}
@Test
def testProcessLoanOk() = {
LoanProcessingApplicationWithStub.loanProcessingService.processLoan( Green Co )
LoanProcessingApplicationWithStub loanProcessingService processLoan(quot;Green Coquot;)
}
4/8/2009 Slide 52
Copyright (c) 2009 Chris Richardson. All rights reserved.
53. The bad news about Scala
IDEs are rough around the edges
Expressiveness comes from complex
language features
Generics are better than Java but still
complex
BUT
The investment in learning these
features is repaid with every
application you write
pp y
4/8/2009 Slide 53
Copyright (c) 2009 Chris Richardson. All rights reserved.
54. Summary
y
Today’s interest in dynamic
languages is natural reaction to Java
Not evolving sufficiently
Showing its age
But many benefits of those languages
are due to good language design
Scala = expressiveness + static
typing
4/8/2009 Slide 54
Copyright (c) 2009 Chris Richardson. All rights reserved.
55. Final thoughts
g
Download or contribute to Cloud
Tools today :
y
www.cloudtools.org
Checkout Cloud Foundry:
www.cloudfoundry.com
www cloudfoundry com
Buy my book ☺
Send email:
chris@chrisrichardson.net
Visit my website:
www.chrisrichardson.net
Talk to me about consulting and
training
Phone: 510 904 9832
4/8/2009 Slide 55
Copyright (c) 2009 Chris Richardson. All rights reserved.