CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an evolutionary dead end?

55
Dynamic Languages: the Dynamic Languages: the next big thing for the JVM or an evolutionary dead end? an evolutionary dead end? Chris Richardson Author of POJOs in Action Founder of Cloud Tools and Cloud Foundry Chris Richardson Consulting, Inc www.chrisrichardson.net www.chrisrichardson.net
  • date post

    22-Oct-2014
  • Category

    Technology

  • view

    3.464
  • download

    3

description

There is a good reason why dynamic languages such as Groovy and Ruby are getting a lot of attention. They are powerful, expressive languages that enable developers to easily write concise programs. However, not all of their benefits derive from being dynamic. Many important benefits are simply due to modern language design such as the support for closures. Moreover, dynamic languages have some inherent drawbacks. The extremely limited compile-time checking requires developers to write significantly more tests and severely limits how much help an IDE can provide to a developer. In this session, which is aimed at Java developers and architects, you will learn • What it means for a language to be dynamic • Which Groovy features we liked the most • The frustrating side of Groovy development • How Groovy compares to Scala, which is a modern statically typed language that provides many of benefits of Groovy

Transcript of CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an evolutionary dead end?

Dynamic Languages: the Dynamic Languages: the next big thing for the JVM or an evolutionary dead end?an evolutionary dead end?

Chris RichardsonAuthor of POJOs in Action

Founder of Cloud Tools and Cloud FoundryyChris Richardson Consulting, Inc

www.chrisrichardson.netwww.chrisrichardson.net

Overall presentation goalp g

Dynamic languages have many benefits But

Static languages which have the Static languages, which have the safety net of compile-time

checking can be just as expressive checking, can be just as expressive

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 24/8/2009

About ChrisAbout Chris• Grew up in England and live in Oakland, CA• Over 20+ years of software development

experience including 12 years of Javaexperience 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 • 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 a 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/cloudtoolshttp://code.google.com/p/cloudtools

• Founder of a startup that provides outsourced, automated, and Java-centric datacenter management on the cloud: www.cloudfoundry.comy

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 34/8/2009

Agendag

The fall and rise of dynamic languagesFavorite Groovy featuresThe frustration of using GroovyScala: expressiveness and compile-p ptime checking

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 44/8/2009

Dynamic vs. static languages

Dynamic (run-time) Static (compile-time)Dynamic (run-time)Types associated with values rather than

Static (compile-time)Types associated with variables

variablesAbility to define new program elements at

Compile-time checking of language elements and types program elements at

runtimeNot a new idea:

elements and types Not a new idea either:

Lisp – 1958!SmallTalk - 1980

Algol 60

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 5

anObject.someMethod(someArgs)

4/8/2009

LISP/CLOS – an early (late 1980s) dynamic languagey g g

(defclass Account ()((account-id :accessor account-id :initarg :account-id)(balance :accessor account-balance :initarg :balance))

)Develop by adding and changing program )

(defmethod debit ((Account account) amount) (decf (account-balance account) amount))

(defmethod credit ((Account account) amount)(incf (account balance account) amount))

g g p gelements in a running VM

(incf (account-balance account) amount))

CL-USER 5 > (setq a (make-instance 'account :account-id "abc123" :balance 10.0))#<ACCOUNT 200C05AF>

CL-USER 6 > (describe a)CL-USER 6 > (describe a)

#<ACCOUNT 200C05AF> is an ACCOUNTACCOUNT-ID "abc123"BALANCE 10.0

CL USER 7 > (debit a 5)CL-USER 7 > (debit a 5)5.0

CL-USER 8 > (describe a)

#<ACCOUNT 200C05AF> is an ACCOUNTACCOUNT ID " b 123"

4/8/2009 Copyright (c) 2009 Chris Richardson. All rights reserved. 6

ACCOUNT-ID "abc123"BALANCE 5.0

… a very dynamic languagey y g g

(defclass Account ()( ()((account-id :accessor account-id :initarg :account-id)(balance :accessor account-balance :initarg :balance)(description :accessor account-description :initarg :description))

)

Existing instances are updated when the class is redefined

CL-USER 9 > (describe a)

#<ACCOUNT 2168DCBF> is an ACCOUNTACCOUNT-ID "abc123"BALANCE 10.0DESCRIPTION #<unbound slot>DESCRIPTION #<unbound slot>

CL-USER 10 > (setf (account-description a) "checking account")"checking account"

CL-USER 11 > (describe a)

#<ACCOUNT 2168DCBF> is an ACCOUNTACCOUNT-ID "abc123"BALANCE 10.0DESCRIPTION "checking account"

4/8/2009 Copyright (c) 2009 Chris Richardson. All rights reserved. 7

Ruby on Rails woke up Javay p

Ruby on Rails:Significantly more productiveSimplicity of Convention over C fi tiConfiguration

Motivated the Java community to iimproveReopened the debate about

i lprogramming languages

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 84/8/2009

Dynamic languages on the JVMy g gJRuby

http://jruby.codehaus.orgp //j y gRuby on the JVM

Jythonhttp://www.jython.org/Projectp // jy g/ jPython on the JVM

Clojurehttp://clojure.org/p j gFunctional programming languageSoftware Transactional Memory…

Groovyhttp://groovy.codehaus.org/Java-compatible, dynamic language

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 94/8/2009

Small…

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 104/8/2009

… but growingg g

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 114/8/2009

Agendag

The fall and rise of dynamic languagesFavorite Groovy featuresThe frustration of using GroovyScala: expressiveness and compile-p ptime checking

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 124/8/2009

About Groovyy

Object-oriented, dynamic languageJava compatibleRuns on the JVMMade popular by the Grails framework:

Rails-like productivityUsing robust Java frameworks including g gSpring and Hibernate

Slide 13Copyright (c) 2009 Chris Richardson. All rights reserved.4/8/2009

Things I like: Java compatibleg p

import javax.crypto.Mac;import javax.crypto.spec.SecretKeySpec;

class EC2RequestExecutor {

Log logger = LogFactory.getLog(getClass())

Java-like syntaxUse Java libraries

public String calculateRFC2104HMAC(String data, String key) {try {SecretKeySpec signingKey = new SecretKeySpec(key.getBytes("UTF8"),

HMAC_SHA1_ALGORITHM)M M tI t (HMAC SHA1 ALGORITHM)Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM)mac.init(signingKey)byte[] rawHmac = mac.doFinal(data.getBytes())return new String(Base64.encodeBase64(rawHmac))

}}catch (Exception e) {throw new RuntimeException("Failed to generate HMAC : ", e)

}}

Slide 144/8/2009 Copyright (c) 2009 Chris Richardson. All rights reserved.

Groovy is concise and expressivey p

def configureAsMaster() {writeFile fileName: "/etc/my.cnf", templateName: "/templates/master.my.cnf"

restartService "mysqld"

exec command: "mysql -u root", templateName: "/templates/createSchema.sql", No parenstemplateName: /templates/createSchema.sql , templateArgs: [schemaSpec: schemaSpec]

executeSchemaScripts()}

No parensKeyword parameters

class TomcatServer { tomcatServer.contextsN t ()

{def getContexts() {

webApps.context}

}

No get…()

Slide 154/8/2009 Copyright (c) 2009 Chris Richardson. All rights reserved.

Literals for lists and mapsp

def myList = [“a”, “b”, “c”]

def params = ['Action': 'RunInstances','MinCount': n.toString(), 'MaxCount': n.toString(),' ImageId': awsProperties."imageId.${instanceType}", 'KeyName': awsProperties.keyName,' InstanceType': instanceType] + extraParams

def response = requestor executeRequest(params)def response = requestor.executeRequest(params)

Slide 164/8/2009 Copyright (c) 2009 Chris Richardson. All rights reserved.

GStringsg

def schemaScript = """DROP SCHEMA IF EXISTS ${schemaSpec.name};CREATE SCHEMA ${schemaSpec.name};

"""

Slide 174/8/2009 Copyright (c) 2009 Chris Richardson. All rights reserved.

Closures

public EC2Server findInstance(String instanceId) {d f fi d {i t Id it i t Id}def server = servers.find {instanceId == it.instanceId}if (server)return server

else throw new RuntimeException( )else throw new RuntimeException(….)}

Simplified collection processing

Slide 184/8/2009 Copyright (c) 2009 Chris Richardson. All rights reserved.

Closures – new control structurespublic class Ssh {

public Object withTunnel(String publicDnsName, int localPort, int remotePort, Closure closure) {p j ( g p , , , ) {SshConnection sshConnection = makeSshConnection(publicDnsName);try {

sshConnection.connect()…return closure.call()

} fi ll {} finally {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

}

}

Slide 194/8/2009 Copyright (c) 2009 Chris Richardson. All rights reserved.

}

An interactive shell

Great for experimentation and learning

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 204/8/2009

Simple reusable codep

interface Quackable {void quack();

Java: l it f

q ();}

class QuackableContainer<T extends Quackable>

complexity of generics

void add(T element) {element.quack();…

}}…}

class QuackableContainer { Groovy: just assume that c ass Quac ab eCo ta e {

void add(T element) {element.quack()…

Groovy: just assume that there is a quack() method

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 21

}

4/8/2009

Groovy metaclassesy

public class StringMetaclassExampleTest extends GroovyTestCase {

void testAddMethodToString() {String.metaClass.doubleString = { -> delegate + delegate }String.metaClass.static.makePowerString = { String s, int n ->

def result = sn.times { result = result.doubleString() }result

}assertEquals "CommunityOne EastCommunityOne East",

"CommunityOne East" doubleString()CommunityOne East .doubleString()assertEquals "NewYorkNewYorkNewYorkNewYork",

String.makePowerString("NewYork", 2)}

}

Runtime definition of program elements

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 224/8/2009

p g

Method Missingg

public class ClassWithMissingMethods {

Object methodMissing(String name, args) {Closure method = makeMethodImplementation(name)if (method) {

method(args)method(args)} else {

throw new MissingMethodException(name, getClass(), args)}

}

def makeMethodImplementation(String name) {….

}

}

def foo = new ClassWithMissingMethods()

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 234/8/2009

g ()foo.nonExistentMethod()

XML and GPath expressionsp<RunInstancesResponse>…<instancesSet>

<item><instanceId>i-4ef21327</instanceId><imageId>ami-3795705e</imageId><instanceState>

<code>0</code>def client = new HttpClient()…def responseStream =

getMethod getResponseBodyAsStream()

<code>0</code><name>pending</name>

</instanceState><dnsName/>

…getMethod.getResponseBodyAsStream()def parser = new XmlParser(false, false)def response = parser.parseText(responseStream)

def newServers = response instancesSet.item collect {

</RunInstancesResponse>

def newServers response.instancesSet.item.collect {new EC2Server(this, awsProperties, ssh,

it.instanceId.text(), it.instanceState.name.text())

}

Slide 24Copyright (c) 2009 Chris Richardson. All rights reserved.4/8/2009

}

Buildersdef report(String path, hosts, cpuCount, threadCount) {

def builder = new groovy.xml.MarkupBuilder(new OutputStreamWriter(new FileOutputStream(path))) builder.performanceReport {builder.performanceReport {cpus cpuCountthreads threadCounthosts.entrySet().each { hostEntry ->host {name hostEntry.keycpuUtil hostEntry value getAverageBusy()

<performanceReport><cpus>1</cpus>cpuUtil hostEntry.value.getAverageBusy()

}}requests {

timings.entrySet().sort{ a, b-> a.key <=> b.key}.each{ pair ->request {name pair key

<cpus>1</cpus><threads>10</threads><host>

<name>database</name><cpuUtil>3.27</cpuUtil>

</host>name pair.keyart pair.value.average()errors pair.value.errorPercentage()}

}}d f d ti V l ((fl t)( dTi t tTi ))/1000 0

</host><host>

<name>tomcat0</name><cpuUtil>94.32</cpuUtil>

</host>

def durationValue = ((float)(endTime - startTime))/1000.0duration durationValuedef tpsValue = transactionCount/ durationValuetps tpsValueart averageResponseTime()

}

…<duration>557.943</duration>

<tps>10.753786677133686</tps><art>916.6578333333</art>

</performanceReport>

}

Slide 254/8/2009 Copyright (c) 2009 Chris Richardson. All rights reserved.

Grails/GORM persistence methods/ p

class Customer {String name

Implemented using metaclasses and method g

}

C t C t ("J h D ")

missing

Customer c = new Customer("John Doe")

if (!c.save())fail "validation failed: ${c.errors}"

Customer c2 = Customer.get(c.id)

c2.delete()

assertNull Customer.get(c.id)

def customers = Customer findAllByName(“Fred”)

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 26

def customers = Customer.findAllByName( Fred )

4/8/2009

Agendag

The fall and rise of dynamic languagesFavorite Groovy featuresThe frustration of using GroovyScala: expressiveness and compile-p ptime checking

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 274/8/2009

Getting Groovy code to work can be frustratingg

Dynamic language = less information for IDE:

Limited compile-time checkingLimited refactoringsLimited completion

Slide 284/8/2009 Copyright (c) 2009 Chris Richardson. All rights reserved.

Groovy fans say "write unit tests“ BUT…

Groovy

versus

When you have typos

Java

Slide 294/8/2009 Copyright (c) 2009 Chris Richardson. All rights reserved.

Unit tests don't always catch errorsy

void testPollStatus_discoveringNewServer() {mockEC2RequestExecutor.demand.executeRequest {params ->….

}def mockEC2Server = new MockFor(EC2Server.class)….mockEC2Server.use {mockEC2Server.use {

mockEC2RequestExecutor.use {ec2 = new EC2(awsProperties)ec2.pollStatus()assertEquals 1, ec2.servers.size()

}

public class EC2 {

}}

}

public pollStatus() {def params = ['Action':

'DescribeInstances']def p = requestor executeRequest(params)

class EC2RequestExecutor {

public Node executeEc2Request(Map parameters) {

requestor.executeRequest(params)…

}…} Method signature changes are

ft i d…}

often missed

Slide 304/8/2009 Copyright (c) 2009 Chris Richardson. All rights reserved.

The trouble with duck typingyp g

Interface between components not defined in a single placeIt is scattered throughout callerDifficult to understandDifficult to changeg

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 314/8/2009

The outcome: fear of changeg

Did my tests Did my tests catch all the obvious errors?the obvious errors?

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 324/8/2009

Writing Java becomes frustratingg g

Importing the obvious, e.g. java.utilTedious collection manipulationPainful XML processingp gRepetitive type declarations

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 334/8/2009

Agendag

The fall and rise of dynamic languagesFavorite Groovy featuresThe frustration of using GroovyScala: expressiveness and pcompile-time checking

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 344/8/2009

Distilling a languageg g g

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 354/8/2009

Scala – a modern (2003) static languageg g

Object-oriented Pure object-oriented languageAll values are objectsClass-basedTraits support "multiple inheritance"

FunctionalFunctionalFunctions are valuesHigher-order functionsCurrying

Statically typedExpressiveType inference

E t ibl t t d i ifi lExtensible to support domain specific languagesMethods as infix and postfix operatorsAutomatic closure construction

Fully interoperable with JavaFully interoperable with Java

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 364/8/2009

Simple examplep p

object StringFunctions {

def reverseSentence(sentence : String) = sentence.split(" ").reverse.mkString(" ")

}

import org.junit._import Assert._

@Testclass StringFunctionsTest {

@Testdef testReverseSentence() = {def testReverseSentence() {val input = "Hello New York"val expected = "York New Hello"assertEquals(expected, StringFunctions.reverseSentence(input))

}}

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 37

}

4/8/2009

Collection literals examplep@Testclass ScalaCollectionExamplesTest {

@Testdef listExample() = {val myList = List(1, 2, 3)assertEquals(3, myList.length)assertEquals(List(0 1 2 3) 0::myList) assertEquals(List(0, 1, 2, 3), 0::myList) assertEquals(List(2, 3), myList.tail) assertEquals(1, myList.head)

}

@Testdef testMapExampleList() : Unit = {val myMap = Map( "x" -> 1, "y" -> 2, "z" -> 3) assertEquals(1, myMap("x"))

}}}

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 384/8/2009

Closure examplep

@Test@Testclass ScalaCollectionExamplesTest {

@Testdef 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))

}

@Testdef testFilterList() = {val myList = List(1, 2, 3) assertEquals(List(1, 3), myList.filter( _ % 2 == 1));

}

}

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 394/8/2009

Pattern matchinggcase 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, _, _, _) => truecase Organization(_, Industry.Banking, _, assets, liabilities)

if liabilities < assets * 1.5 => true O i ti ( I d t B ki ) f lcase Organization(_, Industry.Banking, _, _, _) => false

case Organization(_, _, _, assets, liabilities) if assets > liabilities => truecase _ => false

}

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 40

}

4/8/2009

XML generationg@Testclass ScalaXmlExampleTest {

@Testdef xmlLiterals() {val now = new Date()val loanRequestor =

new Organization("Community Bank, Inc", Industry.Banking, 10, 10, 5)

val doc = <loanRequest><time>{now.getTime()}</time><requester>{loanRequestor.name}</requester><requester>{loanRequestor.name}</requester><industry>{loanRequestor.industry}</industry><revenue>{loanRequestor.revenue}</revenue><assets>{loanRequestor.assets}</assets><liabilities>{loanRequestor.liabilities}</liabilities>

</l R t></loanRequest>

val docAsString : String = doc.toString()println(docAsString)

}

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 41

}

4/8/2009

XML parsingp gclass ScalaXmlExampleTest {

@Test@Testdef xmlProcessing() {val doc = xml.XML.loadString(docAsString)assertEquals ("Community Bank, Inc", (doc \ "requester").text)

node match { case <loanRequest>{children @ _* }</loanRequest> => for (x <- children if !x.isInstanceOf[scala.xml.Text]) {processChildren(x)

}}}

}

def processChildren(node : scala.xml.Node ) = {d t h { node match {

case <time>{value}</time> => println(value.text) case <requester>{value}</requester> => println(value.text) …

}

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 42

}}

4/8/2009

DSL Examplepclass OrganizationDslTest {

val o : Organization = (Organization called "Bernie Madoff & Associates" called Bernie Madoff & Associates in Industry.BankingwithRevenuesOf (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 = nulldef in(industry : Industry.Value) = { this.industry = industry; this }def withRevenuesOf(…) = … …def make()= new Organization(name industry revenue assets liabilities)def make()= new Organization(name, industry, revenue, assets, liabilities)

}

implicit def organizationBuilderToOrganization(builder : OrganizationBuilder) = builder.make

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 43

}

4/8/2009

Constructing object hierarchiesg j

object ExampleSwingApp extends SimpleGUIApplication {

def top = new MainFrame {title = "Example Swing App"

val button = new Button {text = "press"text press

}

contents = button

t 0 var count = 0 listenTo(button)reactions += {case ButtonClicked(b) =>count = count + 1Console.println(count);b.text = "press: " + count

}}

4/8/2009 Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 44

}

Scala command line

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 454/8/2009

Traits

Consist of membersmethodsfieldstypes

The members can be abstractMultiple traits can be mixed into a class

Alternative to multiple inheritanceClass must define abstract members

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 464/8/2009

Dependency injection in Scalap y j

Dependency injection = component definition and compositionTraditional approach

Metadata: XML, annotationsFramework: Spring, Guice, EJB3

Scala: use traits and other language features

4/8/2009 Slide 47Copyright (c) 2009 Chris Richardson. All rights reserved.

Dependency injection –Spring/Java examplep g/ p

@Component("organizationRepository")class OrganizationRepositoryImpl extends OrganizationRepository {

Names a component and class OrganizationRepositoryImpl extends OrganizationRepository {

…}

pspecifies it's implementation

@Component("loanProcessingService")class LoanProcessingServiceImpl extends LoanProcessingService{

@Autowiredprivate OrganizationRepository organizationRepository;

void processLoan( ) {

Expresses a dependency

void processLoan(….) {}

…}

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 484/8/2009

Dependency injection - repositoryp y j p y

trait OrganizationRepositoryComponent {

val organizationRepository : OrganizationRepository

Names a component val organizationRepository : OrganizationRepository

trait OrganizationRepository {def findByName(name : String) : Organization

}

pand defines it's interface

}

trait OrganizationRepositoryComponentImpl extends OrganizationRepositoryComponent {

Specifies the implementation

trait OrganizationRepositoryComponentImpl extends OrganizationRepositoryComponent {

val organizationRepository = new OrganizationRepositoryImpl()

class OrganizationRepositoryImpl extends OrganizationRepository {d f fi dB N ( S i ) {def findByName(name : String) = {… Access the database here…

}}

}

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 49

}

4/8/2009

Dependency injection - servicep y jtrait LoanProcessingServiceComponent { val loanProcessingService : LoanProcessingServicetrait LoanProcessingService {

Expresses a dependencytrait LoanProcessingService {

def processLoan(organizationName : String )}

}trait LoanProcessingServiceComponentImpl extends LoanProcessingServiceComponent

dependency

{ 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 A d( i i )) {if (policy.isLoanApproved(organization)) {// process the loan

} else {throw new LoanRequestRejectedException()

….

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 50

….}

4/8/2009

Dependency injection - applicationp y j pp

object LoanProcessingApplicationextends LoanProcessingServiceComponentImplwith OrganizationRepositoryComponentImpl {

}

LoanProcessingApplication.loanProcessingService.processLoan("Green Co")

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 514/8/2009

Dependency injection – testingp y j g

class LoanProcessingApplicationTest {

trait OrganizationRepositoryComponentStub extends OrganizationRepositoryComponent {val organizationRepository = new OrganizationRepositoryStubImpl() class OrganizationRepositoryStubImpl extends OrganizationRepository {

def findByName(name : String) = {name match {name match {case "Bernie Madoff & Associates" => new Organization(…)…

}}

}}}

object LoanProcessingApplicationWithStub extends LoanProcessingServiceComponentImpl with OrganizationRepositoryComponentStub {g p p g p y p {

}

@Testdef testProcessLoanOk() = {

LoanProcessingApplicationWithStub loanProcessingService processLoan("Green Co")

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 52

LoanProcessingApplicationWithStub.loanProcessingService.processLoan( Green Co )}

4/8/2009

The bad news about Scala

IDEs are rough around the edgesExpressiveness comes from complex language featuresGenerics are better than Java but still complex

BUTThe investment in learning these The investment in learning these features is repaid with every application you writepp y

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 534/8/2009

Summaryy

Today’s interest in dynamic languages is natural reaction to Java

Not evolving sufficientlyShowing its age

But many benefits of those languages are due to good language designScala = expressiveness + static typing

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 544/8/2009

Final thoughtsg

Download or contribute to Cloud Tools today :y

www.cloudtools.org

Checkout Cloud Foundry:

www cloudfoundry comwww.cloudfoundry.com

Buy my book ☺

Send email:

[email protected]

Visit my website:

www.chrisrichardson.net

Talk to me about consulting and training

Phone: 510 904 9832

Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 554/8/2009