Professional Documents
Culture Documents
Dynamic Languages: The Dynamic Languages: The Next Big Thing For The JVM or An Evolutionary Dead End? 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?
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
y
Founder of Cloud Tools and Cloud Foundry
Chris Richardson Consulting, Inc
www.chrisrichardson.net
Overall p
presentation g
goal
CL-USER
CL USER 7 > (debit a 5)
5.0
((defclass Account ()
((account-id :accessor account-id :initarg :account-id) Existing instances
(balance :accessor account-balance :initarg :balance) are updated when
(description :accessor account-description :initarg :description)) the class is redefined
)
restartService "mysqld"
executeSchemaScripts()
}
public Object
p j withTunnel(String
( gppublicDnsName,, int localPort,, int remotePort,, Closure closure)) {
SshConnection sshConnection = makeSshConnection(publicDnsName);
try {
sshConnection.connect()
…
return closure.call()
} finally
fi ll {
sshConnection.close()
}
}
}
class EC2 {
class
c ass Quac
QuackableContainer
ab eCo ta e { Groovy: just assume that
void add(T element) { there is a quack()
element.quack()
…
method
}
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 "CommunityOne EastCommunityOne East",
"CommunityOne
CommunityOne East
East".doubleString()
doubleString()
assertEquals "NewYorkNewYorkNewYorkNewYork",
String.makePowerString("NewYork", 2)
}
}
Runtime definition of p
program
g elements
4/8/2009 Copyright (c) 2009 Chris Richardson. All rights reserved. Slide 25
Grails/GORM
/ p
persistence methods
class Customer { Implemented using
String
g name metaclasses and method
} missing
C t
Customer c = new Customer("John
C t ("J h Doe")
D ")
if (!c.save())
fail "validation failed: ${c.errors}"
Customer c2 = Customer.get(c.id)
c2.delete()
assertNull Customer.get(c.id)
Groovy
Java
Slide 30
4/8/2009 Copyright (c) 2009 Chris Richardson. All rights reserved.
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
Did my tests
catch all
the obvious errors?
import org.junit._
import Assert._
@Test
class StringFunctionsTest {
@Test
def testReverseSentence() = {
val input = "Hello New York"
val expected = "York New Hello"
assertEquals(expected, StringFunctions.reverseSentence(input))
}
}
@Test
def listExample() = {
val myList = List(1, 2, 3)
assertEquals(3, myList.length)
assertEquals(List(0 1
assertEquals(List(0, 1, 2
2, 3),
3) 0::myList)
assertEquals(List(2, 3), myList.tail)
assertEquals(1, myList.head)
}
@Test
def testMapExampleList() : Unit = {
val myMap = Map( "x" -> 1, "y" -> 2, "z" -> 3)
assertEquals(1, myMap("x"))
}
}
@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));
}
class LoanApprovalPolicy {
@Test
def xmlLiterals() {
val now = new Date()
val loanRequestor =
new Organization("Community Bank, Inc", Industry.Banking, 10, 10, 5)
@Test
def 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)
}
}
}
} object Organization {
def called(name : String) = new OrganizationBuilder(name)
class OrganizationBuilder(name
g ( : String)
g) {
var industry : Industry.Value = null
def in(industry : Industry.Value) = { this.industry = industry; this }
def withRevenuesOf(…) = …
…
def make()= new Organization(name
Organization(name, industry
industry, revenue
revenue, assets,
assets liabilities)
}
contents = button
var countt = 0
listenTo(button)
reactions += {
case ButtonClicked(b) =>
count = count + 1
Console.println(count);
b.text = "press: " + count
}
}
@Component("loanProcessingService")
class LoanProcessingServiceImpl extends LoanProcessingService{
Expresses a @Autowired
dependency private OrganizationRepository organizationRepository;
void processLoan(….)
processLoan( ) {
}
…
}
object LoanProcessingApplication
extends LoanProcessingServiceComponentImpl
with OrganizationRepositoryComponentImpl {
LoanProcessingApplication.loanProcessingService.processLoan("Green Co")
@Test
def testProcessLoanOk() = {
LoanProcessingApplicationWithStub loanProcessingService processLoan("Green
LoanProcessingApplicationWithStub.loanProcessingService.processLoan( Green Co")
Co )
}