• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
In pursuit of expressivity: Groovy and Scala compared
 

In pursuit of expressivity: Groovy and Scala compared

on

  • 9,327 views

Thirty years ago the famous computer scientist Tony Hoare said “I have regarded it as the highest goal of programming language design to enable good ideas to be elegantly expressed”. His comment ...

Thirty years ago the famous computer scientist Tony Hoare said “I have regarded it as the highest goal of programming language design to enable good ideas to be elegantly expressed”. His comment sums up what has been driving the evolution of programming languages: the desire to create increasingly expressive languages. In this talk you will learn about two modern JVM languages that strive to be expressive in very different ways. We will talk about Groovy, which is a dynamically-typed language, and Scala, which is a statically-typed language. You will learn about the key features of each language as well as their benefits and the drawbacks.

Statistics

Views

Total Views
9,327
Views on SlideShare
9,197
Embed Views
130

Actions

Likes
8
Downloads
0
Comments
1

10 Embeds 130

http://www.w2ee.com 73
http://www.scalazone.net 30
http://paper.li 15
https://twimg0-a.akamaihd.net 3
https://twitter.com 2
http://webcache.googleusercontent.com 2
http://www.techgig.com 2
http://www.slideshare.net 1
http://us-w1.rockmelt.com 1
https://si0.twimg.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

11 of 1 previous next

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • Slide 74: you don't need to define and annotate setters. Just use @(Autowired @beanSetter)
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    In pursuit of expressivity: Groovy and Scala compared In pursuit of expressivity: Groovy and Scala compared Presentation Transcript

    • In pursuit of expressivity:Groovy and Scala compared Chris Richardson Author of POJOs in Action Founder of CloudFoundry.com chris@chrisrichardson.net @crichardson
    • Overall presentation goal Examine the good, the bad and the ugly aspects of developing with Groovy and Scala 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 2
    • About Chris •  Grew up in England and live in Oakland, CA •  Over 25+ years of software development experience including 14 years of Java •  Speaker at JavaOne, SpringOne, NFJS, JavaPolis, Spring Experience, etc. •  Organize the Oakland JUG ( http://bit.ly/ebjava) and the Groovy Grails meetup (http://bit.ly/oakgrails) http://www.theregister.co.uk/2009/08/19/springsource_cloud_foundry/ 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 3
    • Agendao  Evolution of programming languageso  Favorite Groovy featureso  The frustration of using Groovyo  Scala: expressiveness and compile- time checkingo  The trouble with Scala 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 4
    • Lots of programming languages This site lists 8512 languages, complete with 17837 bibliographic records featuring 11064 extracts from those references. It is in effect a family tree of languages with 5445 links, making it not only the biggest programming language family tree around, but also one of the largest idea-genealogical projects undertaken. http://hopl.murdoch.edu.au/ 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 5
    • The Elite v. The MassesThe Elite Mainstreamo  Lisp o  Thought Lisp and n  Invented in the 1960s Smalltalk were: n  Dynamic functional n  Weird (Too different language from Algol) n  Dynamic object-oriented n  Too resource hungry language (mid-1980s) (probably were for theo  Smalltalk time) n  Invented in the 1970s o  So the mainstream used: n  Dynamic object-oriented Pascal, C, C++, …. language o  Not so safe, manualo  Safe, garbage collection, memory management, rich, … primitive, … 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 6
    • LISP/CLOS – an early (late 1980s)dynamic language (defclass Account () ((account-id :accessor account-id :initarg :account-id) (balance :accessor account-balance :initarg :balance)) Develop by adding and ) changing 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)) CL-USER 5 > (setq a (make-instance account :account-id "abc123" :balance 10.0)) #<ACCOUNT 200C05AF> CL-USER 6 > (describe a) #<ACCOUNT 200C05AF> is an ACCOUNT ACCOUNT-ID "abc123" BALANCE 10.0 CL-USER 7 > (debit a 5) 5.0 CL-USER 8 > (describe a) #<ACCOUNT 200C05AF> is an ACCOUNT ACCOUNT-ID "abc123" BALANCE 5.0 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. 7
    • … a very dynamic language (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 ) CL-USER 9 > (describe a) #<ACCOUNT 2168DCBF> is an ACCOUNT ACCOUNT-ID "abc123" BALANCE 10.0 DESCRIPTION #<unbound slot> CL-USER 10 > (setf (account-description a) "checking account") "checking account" CL-USER 11 > (describe a) #<ACCOUNT 2168DCBF> is an ACCOUNT ACCOUNT-ID "abc123" BALANCE 10.0 DESCRIPTION "checking account" 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. 8
    • Along came Javao  Provided the masses with: n  Garbage collection n  Safety, reliability and securityo  And 10+ years passed… 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 9
    • Ruby on Rails woke up the Javacommunityo  Ruby on Rails: n  Significantly more productive n  Simplicity of Convention over Configurationo  Motivated the Java community to improve: frameworks such as Spring improved considerablyo  And… 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 10
    • …Highlighted Problems with Javao  Tedious collection processingo  Painful object construction code n  No literals for collections n  Need to use Builders for creating hierarchieso  Tedious XML processingo  Types: n  Verbose declarations n  Generics are complicatedo  Fixed set of control constructso  Limited support for DSLs =>o  Reopened the debate about programming languageso  Dynamic languages became interesting again 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 11
    • Dynamic languages on the JVMo  JRuby n  http://jruby.codehaus.org n  Ruby on the JVMo  Jython n  http://www.jython.org/Project n  Python on the JVMo  Clojure n  http://clojure.org/ n  Functional programming language n  Software Transactional Memory n  …o  Groovy n  http://groovy.codehaus.org/ n  Java-compatible, dynamic language 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 12
    • Small but growing 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 13
    • Static languages on the JVM o  (Java) o  Fortress o  Gosu o  Scala o  …http://www.is-research.de/info/vmlanguages/?s=static 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 14
    • Scala and Gosu adoption – Smallerbut growing 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 15
    • Agendao  Evolution of programming languageso  Favorite Groovy featureso  The frustration of using Groovyo  Scala: expressiveness and compile- time checkingo  The trouble with Scala 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 16
    • About Groovyo  Object-oriented, dynamic languageo  Made popular by the Grails framework: n  Rails-like productivity n  Using robust Java frameworks including Spring and Hibernate 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 17
    • The good newso  Easy to learn n  Designed to be Java compatible n  Interactive Shello  Great support for DSLso  Closures: n  Easy collection processing n  New control constructso  Property/method missing mechanismo  Good XML handlingo  Meta-classes for dynamically defining new program elements => foundation for Grails 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 18
    • Intentionally compatible with Javao  Groovy objects are Java objectso  Groovy collections are Java collectionso  Groovy can call Java n  e.g. leverage all those Java librarieso  Java can call Groovy, e.g. Groovy objects can be: n  Spring beans n  Hibernate objectso  Easy to write a module of a project Groovy => Easy to incrementally adopt 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 19
    • Groovy can look like Javaimport javax.crypto.Mac;import javax.crypto.spec.SecretKeySpec;class EC2RequestExecutor { Java-like syntaxLog logger = LogFactory.getLog(getClass()) public String calculateRFC2104HMAC(String data, String key) { try { SecretKeySpec signingKey = new SecretKeySpec(key.getBytes("UTF8"), 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) }} 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 20
    • Groovy is concise and expressivedef configureAsMaster() { writeFile fileName: "/etc/my.cnf", templateName: "/templates/master.my.cnf" restartService "mysqld" exec command: "mysql -u root", templateName: "/templates/createSchema.sql", No parens templateArgs: [schemaSpec: schemaSpec] Keyword parameters executeSchemaScripts() } class TomcatServer { tomcatServer.contexts No get…() def getContexts() { webApps.context } } 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 21
    • An interactive shell Great for experimentation and learning 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 22
    • Literals for lists and mapsdef myList = ["a", "b", "c"]def params = [Action: RunInstances, MinCount: n.toString(), MaxCount: n.toString(), ImageId: awsProperties."imageId.${instanceType}", KeyName: awsProperties.keyName, InstanceType: instanceType] + extraParamsdef response = requestor.executeRequest(params) 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 23
    • GStringso  Templating mechanismo  Embedded Groovy expressionso  Multi-line stringsdef schemaScript = """ DROP SCHEMA IF EXISTS ${schemaSpec.name}; CREATE SCHEMA ${schemaSpec.name}; """ 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 24
    • Closures – collection processing public EC2Server findInstance(String instanceId) { def server = servers.find {instanceId == it.instanceId} if (server) return server else throw new RuntimeException(….) }assertEquals(["aa", "bb", "cc"], ["a", "b", "c"].collect { elem -> elem + elem }Simplified collection processingNo ugly anonymous inner classes 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 25
    • Closures – new control structurespublic class Ssh {def withTunnel(String publicDnsName, int localPort, int remotePort, Closure closure) { SshConnection sshConnection = makeSshConnection(publicDnsName); try { sshConnection.connect() … return closure.call() } 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 }} 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 26
    • Closures detailsgroovy:000> x = { println z }===> groovysh_evaluate$_run_closure1@658ba380groovy:000> x.delegate = [z: 99]===> Foo@564a5320groovy:000> x.call() Used to resolve99 unbound methods and properties===> null For example, Builders set the delegate 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 27
    • Simple reusable codeinterface Quackable { void quack(); Java:} complexity ofclass QuackableContainer<T extends Quackable> genericsvoid add(T element) { element.quack(); …}…}class QuackableContainer { Groovy: just assume thatvoid add(element) { there is a quack() method element.quack() …} 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 28
    • Method Missingpublic class ClassWithMissingMethods { def 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() foo.nonExistentMethod() 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 29
    • Groovy metaclassespublic 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 "JavaZoneJavaZone", "JavaZone".doubleString() assertEquals "OsloOsloOsloOslo", String.makePowerString("Oslo", 2) }} Runtime definition of program elements The foundation of many powerful features 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 30
    • XML and GPath expressions <RunInstancesResponse> … <instancesSet> <item> <instanceId>i-4ef21327</instanceId> <imageId>ami-3795705e</imageId> <instanceState> <code>0</code>def client = new HttpClient() <name>pending</name>… </instanceState>def responseStream = <dnsName/> … getMethod.getResponseBodyAsStream() </RunInstancesResponse>def parser = new XmlParser(false, false)def response = parser.parseText(responseStream)def newServers = response.instancesSet.item.collect { new EC2Server(this, awsProperties, ssh, it.instanceId.text(), it.instanceState.name.text())} 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 31
    • Metaclasses enhance JDK classesgroovy:000> new File("/Users/cer/.bashrc").text===> export PATH=/Users/cer/tools/apache-maven-3.0/bin:$PATHgroovy:000> l = [1,2,3]===> [1, 2, 3]groovy:000> l.getClass()===> class java.util.ArrayListgroovy:000> l.getClass().metaClass.foo = { delegate.size }===> groovysh_evaluate$_run_closure1@13a66c87groovy:000> l.foo()===> 3 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 32
    • Buildersdef 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 {hostName, metric -> host { name hostName <performanceReport> cpuUtil metric.getAverageBusy() <cpus>1</cpus> } <threads>10</threads> } <host> requests { timing.sort{ a, b-> a.key <=> b.key}.each{ requestName, metric-> <name>database</name> request { <cpuUtil>3.27</cpuUtil> name requestName </host> art metric.average() <host> errors metric.errorPercentage() <name>tomcat0</name> } } <cpuUtil>94.32</cpuUtil> } </host> def durationValue = (endTime – startTime)/1000.0 … duration durationValue <duration>557.943</duration> def tpsValue = transactionCount/ durationValue <tps>10.753786677133686</tps> tps tpsValue art averageResponseTime() <art>916.6578333333</art> } </performanceReport> } 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 33
    • Grails plugins use metaclasseso  Key part of the Grails pluginso  Plugins can dynamically add methods, e.g. GORM persistence methodso  Injected methods are closures that have access to the Spring application context n  Less need for traditional dependency injection n  Alternative to AOP static crosscutting or (non-POJO) inheritance 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 34
    • Grails/GORM persistence methods class Customer { Implemented using String name metaclasses and method } 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”) 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 35
    • Commentable plugin exampleclass CommentableGrailsPlugin { def doWithDynamicMethods = { ctx -> for(domainClass in application.domainClasses) { if(Commentable.class.isAssignableFrom(domainClass.clazz)) { domainClass.clazz.metaClass { static { getRecentComments {-> … } } addComment { poster, String text -> } getComments = {-> }…} 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 36
    • Grails DSL for ORM class Customer { static transients = ["networth"] static mapping = { id column: ‘customer_id’ Closures table ‘crc_customer’ columns { } name column: ‘customer_name’ Method } missing def getNetworth() { … } } ... 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 37
    • Grails Controllers -o  Accessing request/responseo  Databinding n  b.properties = params n  new B(params)o  … 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 38
    • Agendao  Evolution of programming languageso  Favorite Groovy featureso  The frustration of using Groovyo  Scala: expressiveness and compile- time checkingo  The trouble with Scala 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 39
    • Getting complex Groovy code towork can be frustratingo  Dynamic language = less information for IDE: n  Limited compile-time checking n  Limited refactorings n  Limited completion n  No todo list of errors 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 40
    • Groovy fans say "write unit tests“BUT… Groovy When you have typos versus Java 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 41
    • Unit tests dont always catch errors 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)class EC2RequestExecutor { … } public Node executeEc2Request(Map …parameters) { } Method signature changes are … often missed} Slide 42 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved.
    • The trouble with duck typingo  Interface between components not defined in a single placeo  It is scattered throughout callerso  Difficult to understando  Difficult to change 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 43
    • The outcome: fear of change Did my tests catch all the obvious errors? 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 44
    • Agendao  Evolution of programming languageso  Favorite Groovy featureso  The frustration of using Groovyo  Scala: expressiveness and compile-time checkingo  The trouble with Scala 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 45
    • Distilling a language Builders Dynamic methods and properties Gpath-based XML handling Dynamic features Static features Closures Groovy Literals for collections GStrings 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 46
    • Scala – a modern (2003) staticlanguageo  Object-oriented n  Pure object-oriented language n  All values are objects “I can honestly say if someone had n  Class-based shown me the Programming in Scala book by by Martin Odersky,o  Functional Lex Spoon & Bill Venners back in n  Functions are values 2003 Id probably have never created Groovy.” n  Higher-order functions n  Currying James Strachan, Creator of Groovy http://macstrac.blogspot.com/o  Statically typed 2009/04/scala-as-long-term- n  Expressive replacement-for.html n  Type inferenceo  Extensible to support domain specific languages n  Methods as infix and postfix operators n  Automatic closure construction 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 47
    • The good newso  Fully interoperable with Javao  Interactive shello  Rich, extensible languageo  Closureso  Good XML processingo  Named arguments and default parameter valueso  Option class avoids null referenceso  Traits provide “multiple inheritance” 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 48
    • Scala command line 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 49
    • Simple exampleobject StringFunctions { def reverseSentence(sentence : String) = sentence.split(" ").reverse.mkString(" ")}import org.junit._import Assert._@Testclass StringFunctionsTest { @Test def testReverseSentence() = { val input = "Hello New York" val expected = "York New Hello" assertEquals(expected, StringFunctions.reverseSentence(input)) }} 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 50
    • Collection literals example@Testclass ScalaCollectionExamplesTest {@Test def listExample() = { val myList = List(1, 2, 3) assertEquals(3, myList.length) 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( "x" -> 1, "y" -> 2, "z" -> 3) assertEquals(1, myMap("x")) }} 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 51
    • Closure example@Testclass ScalaCollectionExamplesTest { @Test def testMapList() = { 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/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 52
    • Defining new control constructs 1class ExampleControlConstructExampleTest {def withOutputStream[T](f : File)(body : InputStream => T) = { val fis = new FileInputStream(f) try { body(fis) } finally { fis.close } } @Test def withOpenFileExample { withOutputStream(new File("/Users/cer/.bashrc")) {fis => println(fis.available) } } 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 53
    • Defining new control constructs 2 By-name parameter var assertsEnabled = false def myAssert(message : String, assertion : => Boolean) { if (assertsEnabled) { if (!assertion) throw new RuntimeException(message) } } @Test def assertionsDisabled = { myAssert("never", { println("you will not see me") ; false }) } 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 54
    • Pattern matchingcase 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 Organization(_, Industry.Banking, _, _, _) => false case Organization(_, _, _, assets, liabilities) if assets > liabilities => true case _ => false }} 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 55
    • XML generation@Testclass ScalaXmlExampleTest { @Test def 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> <industry>{loanRequestor.industry}</industry> <revenue>{loanRequestor.revenue}</revenue> <assets>{loanRequestor.assets}</assets> <liabilities>{loanRequestor.liabilities}</liabilities> </loanRequest> val docAsString : String = doc.toString() println(docAsString) } 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 56
    • XML parsingclass ScalaXmlExampleTest { @Test def xmlProcessing() { val doc = xml.XML.loadString(docAsString) assertEquals ("Community Bank, Inc", (doc "requester").text) doc match { case <loanRequest>{children @ _* }</loanRequest> => for (x <- children if !x.isInstanceOf[scala.xml.Text]) { processChildren(x) } } } def processChildren(node : scala.xml.Node ) = { node match { case <time>{value}</time> => println(value.text) case <requester>{value}</requester> => println(value.text) … } } 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 57
    • DSL Exampleclass OrganizationDslTest { val o : Organization = (Organization called "Bernie Madoff & 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) { 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) } implicit def organizationBuilderToOrganization(builder : OrganizationBuilder) = builder.make } 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 58
    • Named arguments and default valueso  Arguments can be namedo  Parameters can have default valueso  Benefits: n  Clearer code – Booleans aren’t so evil n  Avoids confusing overloaded methods/ constructors n  Less need for the Builder patterndef foo(x: Int = 10, y: Int = 20) = x * yfoo() should be(200)foo(y = 30, x = 50) should be(1500)foo(x = 50) should be(1000) 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 59
    • Constructing object hierarchies object ExampleSwingApp extends SimpleGUIApplication { def top = new MainFrame { title = "Example Swing App" Defines method declared abstract in superclass val button = new Button { text = "press" } Sets property contents = button var count = 0 Statements/ listenTo(button) reactions += { expressions that case ButtonClicked(b) => are executed count = count + 1 Console.println(count); b.text = "press: " + count Nesting of new Class { } } } mirrors object hierarchy } 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 60
    • Pimping existing classesscala> 5.times { println("Hello") }<console>:6: error: value times is not a member of Int 5.times { println("Hello") } ^scala> class IntWithTimes(n: Int) { | def times(body: => Unit) = for (x <- 1 to n) body | }defined class IntWithTimesscala> implicit def toIntWithTimes(n: Int) = new IntWithTimes(n)toIntWithTimes: (n: Int)IntWithTimesscala> 5.times { println("Hello") }HelloHelloHello Implicit conversionHelloHello 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 61
    • Implicit parameters 1@Testdef implicitParamsImplicitVar { implicit val defaultValue = 8 def m(i : Int) (implicit j : Int) = i * j assertEquals(48, m(6)) assertEquals(42, m(6)(7))} 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 62
    • Implicit parameters 2scala> implicit def toInt : Int = 5toInt: Intscala> def m(i : Int) (implicit j : Int) = i * jm: (i: Int)(implicit j: Int)Intscala> m(6)res6: Int = 30scala> m(6)(7)res7: Int = 42 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 63
    • Null References My Billion Dollar mistake 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 64
    • Use Options instead of null…var x : Option[Int] = Some(5)var y : Option[Int] = Nonevar z : Option[Int] = Some(7)assertEquals(5, x.get)try { y.get fail } catch { case _ : NoSuchElementException => }assertEquals(5, x.getOrElse(10))assertEquals(10, y.getOrElse(10)) 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 65
    • … more optionsassertEquals(Some(7), x.map(_ + 2))assertEquals(None, y.map(_ + 2))assertEquals(None, x.filter(_ == 2))assertEquals(Some(5), x.filter(_ == 5))assertEquals(Some(35), for (a <- x ; b <- z) yield a * b) 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 66
    • Traitso  Consist of members n  methods n  fields n  typeso  The members can be abstracto  Multiple traits can be mixed into a class n  Alternative to multiple inheritance n  Class must define abstract memberso  Uses: n  Modularizing applications n  Enriching interfaces n  Decorating classes 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 67
    • RESTful WS using Spring MVC and Scalao  Handling HTTP request Photo management n  Extract values from URL n  Invoke appropriate handler application n  Generate response (XML)o  Sounds like a job for Scalas GET /album n  Pattern matching GET /album/<albumId> n  XML support POST /album … <album> <id>6699</id>GET /album/6699 <photos>…</photos> … </album> 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 68
    • Pattern matching HTTP Requests o  Match against n  URL – represented as a List n  Method n  … o  Returns XMLrequest match {case Request(List("album"), "GET", _, _) => listAlbumscase Request(List("album", albumId), "GET", _, _) => findAlbum(albumId)} def findAlbum(albumId : String) = { def album = albumService.findAlbum(albumId) <album> <id>{album.getId()}</id> <photos>…</photos> … </album> } 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 69
    • The Extractorobject Request { def unapply(request : HttpServletRequest) : Option[ (List[String], String, RequestBody, Binder)] ={ val path = List.fromArray(request.getPathInfo().split("/")).tail Some(path, request.getMethod, new RequestBody(request), new Binder(request)) }} 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 70
    • Package as WSEndpointstrait WsEndpoint extends PartialFunction[HttpServletRequest, Node] { def isDefinedAt(request : HttpServletRequest) = wsDispatchRules.isDefinedAt(request) def apply(request : HttpServletRequest) = wsDispatchRules(request) protected def wsDispatchRules : PartialFunction[HttpServletRequest, Node]} @Component class AlbumWsEndpoint extends WsEndpoint { @Autowired def setAlbumService(albumService : AlbumService) = … def wsDispatchRules = { case Request(List("album", albumId), "GET", _, _) => findAlbum(albumId) … } def findAlbum(albumId : String) = { def album = albumService.findAlbum(albumId) <album>…</album> } 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 71
    • Integrate with Spring MVC 1@Componentclass WsEndpointHandlerMapping extends HandlerMapping {@Autowireddef setApplicationContext(applicationContext : ApplicationContext) { this.applicationContext = applicationContext}def endpoints = …applicationContext.getBeansOfType(classOf[WsEndpoint])…override def getHandler(request : HttpServletRequest) : HandlerExecutionChain = { val endpointForRequest = endpoints.find( _.isDefinedAt(request)) endpointForRequest match { case Some(endpoint) => new HandlerExecutionChain(endpoint) case None => null } } Maps HTTP request to WSEndpoint 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 72
    • Integrate with Spring MVC 2@Componentclass WsEndpointHandlerAdapter extends HandlerAdapter { override def supports(handler : Object) = { handler.isInstanceOf[WsEndpoint] } override def handle(request : HttpServletRequest , response : HttpServletResponse , handler : Object ) : ModelAndView = { val endpoint = handler.asInstanceOf[WsEndpoint] val node = endpoint(request) response.setContentType("text/xml") response.getWriter.print(node.toString) null } Invokes WSEndpoint and generates HTTP response 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 73
    • Scala and Spring DIo  Scala and Spring DI play togethero  @Component on Scala classes workso  @Autowired fields: n  Annotation ends up on field and generated methods è fail n  Need to define and annotate setters 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 74
    • Agendao  Evolution of programming languageso  Favorite Groovy featureso  The frustration of using Groovyo  Scala: expressiveness and compile- time checkingo  The trouble with Scala 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 75
    • Really bad newso  Scala IDEs are ok and slowly improving BUT have a really really long way to go compared to Javao  Limited refactoring => painful to maintain code quality? 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 76
    • More bad news…o  Expressiveness comes from complex language featureso  Generics are better than Java but still complex BUTo  The investment in learning these features is repaid with every application you write 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 77
    • …more bad newso  Lift is not Grails (or Rails)o  A subset of the Scala community has a functional programming background => Obsessed with their Monadso  Implicit conversions make it possible to write “incomprehensible” codeo  Scala Collections != Java Collections n  BUT Implicit conversions simplify interoperability 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 78
    • Summaryo  The Java Language has stagnated and need to be replacedo  Dynamic languages are one optiono  But many benefits of those languages are due to good language designo  Scala = expressiveness + static typingo  But Grails derives much of its power from the dynamic features of Groovyo  Therefore, choose the right tool: n  Web application è Use Groovy and Grails n  Complex business logic/middleware è Consider Scala 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 79
    • Summary – Pessimistic viewo  Languages used by mainstream developers have improved substantiallyo  But are those languages that much better than the 25+ year old “ivory tower” languages: LISP, Smalltalk, ML, … ? 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 80
    • Final thoughtso  Learn some languages including Haskello  Watch the 50 in 50 presentation by Guy Steele and Dick Gabriel: http://blog.jaoo.dk/2008/11/21/art- and-code-obscure-or-beautiful-code/"Those who cannot remember the past are condemned to repeat it” http://en.wikipedia.org/wiki/George_Santayana 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 81
    • The end Twitter: @crichardson Send email: chris@chrisrichardson.net 4/3/11 Copyright (c) 2011 Chris Richardson. All rights reserved. Slide 82