SlideShare a Scribd company logo
inPracticeScala
patric.fornasier@thoughtworks.com
marc.hofer@thoughtworks.com
2&/82..9+8$&+&"0+&/;0+2-3+0<10-*0+#7+
7=&"0=2>#50+2-3+;#(0?+
Optimising IT
Organisations
technology
Consulting
Testing
Build & Release
Management
Experience
Design
Offices
2
presentation Contains
code examples
Warning
Context
A bit of
about the project
Why Scala
What is
Scala
Scala
FunctionalObject
Oriented
Statically
Typed
Scriptable
JVM-
based
JVMByte CodeCompileScala
Benefits
“Functional
Programming”
List<String> features = Arrays.asList("noFeature", "featureC",
"featureB", "featureA");
for (String feature : features) {
System.out.println(feature);
}
List<String> javaFeatures = Arrays.asList("noFeature", "featureC",
"featureB", "featureA");
for (String feature : javaFeatures) {
System.out.println(feature);
}
	 	 val scalaFeatures = List( "noFeature", "featureC",
"featureB", "featureA")
	 	 scalaFeatures foreach { println _ }
val currentFeatures = List("noFeature", "featureC", "featureB", "featureA")
Result: "featureA_toggle, featureB_toggle"
currentFeatures.filter { _.startsWith("feature") }
.mkString(", ")
.map { _ + "_toggle" }
.sorted
.take(2)
String result = "";
List<String> currentFeatures = Arrays.asList("noFeature", "featureC",
	 	 	 	 "featureB", "featureA");
Collections.sort(currentFeatures);
int i = 0, j = 0, take = 2;
	 	
while(i < take && j < currentFeatures.size()) {
	 String feature = currentFeatures.get(j++);
	 if(feature.startsWith("feature")) {
	 	 result += feature + "_toggle" + ((i++ != take) ? ", " : "");
	 }
}
	 	
currentFeatures.filter { _.startsWith("feature") }
.mkString(", ")
.map { _ + "_toggle" }
.sorted
.take(2)
“Less
Boilerplate”
public class Property {}
class Property {}
public class Property {
private final String key;
private final String value;
private final String defaultValue;
public Property(String key, String value, String defaultValue) {
this.key = key;
this.value = value;
this.defaultValue = defaultValue;
}
}
class Property(key: String, value: String, default: String) {}
public class Property {
// ...
public String getKey() {
return key;
}
public String getValue() {
return value;
}
public String getDefaultValue() {
return defaultValue;
}
}
class Property(val key: String, val value: String, val default: String) {}
public class Property {
// ...
public Property changeTo(String newValue) {
return new Property(key, value, newValue);
}
public Property reset() {
return new Property(key, value);
}
@Override
public String toString() {
return String.format("%s=%s", key, value);
}
}
class Property(val key: String, val value: String, val default: String) {
def changeTo(newValue: String) = new Property(key, newValue, default)
def reset = new Property(key, default)
override def toString = "%s=%s" format(key, value)
}
public class Property {
// ...
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Property))
return false;
Property other = (Property) obj;
return other.key.equals(key) && other.value.equals(value)
&& other.defaultValue.equals(defaultValue)
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + key;
result = 31 * result + value;
result = 31 * result + defaultValue;
return result;
}
}
case class Property(key: String, value: String, default: String) {
def changeTo(newValue: String) = Property(key, newValue, default)
def reset = Property(key, default)
override def toString = "%s=%s" format(key, value)
}
public class Property {
private final String key;
private final String value;
private final String defaultValue;
public Property(String key, String value, String defaultValue) {
this.key = key;
this.value = value;
this.defaultValue = defaultValue;
}
public String getKey() {
return key;
}
public String getValue() {
return value;
}
public String getDefaultValue() {
return defaultValue;
}
public Property changeTo(String newValue) {
return new Property(key, value, newValue);
}
public Property reset() {
return new Property(key, value);
}
@Override
public String toString() {
return String.format("%s=%s", key, value);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Property))
return false;
Property other = (Property) obj;
return other.key.equals(key) && other.value.equals(value)
&& other.defaultValue.equals(defaultValue)
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + key;
result = 31 * result + value;
result = 31 * result + defaultValue;
return result;
}
}
case class Property(key: String, value: String, default: String) {
def changeTo(newValue: String) = Property(key, newValue, default)
def reset = Property(key, default)
override def toString = "%s=%s" format(key, value)
}
public class Property {
private final String key;
private final String value;
private final String defaultValue;
public Property(String key, String value, String defaultValue) {
this.key = key;
this.value = value;
this.defaultValue = defaultValue;
}
public String getKey() {
return key;
}
public String getValue() {
return value;
}
public String getDefaultValue() {
return defaultValue;
}
public Property changeTo(String newValue) {
return new Property(key, value, newValue);
}
public Property reset() {
return new Property(key, value);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Property))
return false;
Property other = (Property) obj;
return other.key.equals(key) && other.value.equals(value)
&& other.defaultValue.equals(defaultValue)
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + key;
result = 31 * result + value;
result = 31 * result + defaultValue;
return result;
}
@Override
public String toString() {
return String.format("%s=%s", key, value);
}
}
case class Property(key: String, value: String, default: String) {
def changeTo(newValue: String) = Property(key, newValue, default)
def reset = Property(key, default)
override def toString = "%s=%s" format(key, value)
}
45 vs 5
LOCs
* ignoring blank lines
Another Example:
{ Blocks }
“Less
Boilerplate”
val content = get("http://foo.com") { toString }
val statusCode = get("http://foo.com") { statusCode }
get("http://foo.com")
int statusCode = httpSupport.get("http://foo.com", new Block<Integer>() {
public Integer execute(HttpResponse response) {
return response.getStatusLine().getStatusCode());
}
});
String content = httpSupport.get("http://foo.com", new Block<String>() {
public Integer execute(HttpResponse response) {
return EntityUtils.toString(response.getEntity());
}
});
httpSupport.get("http://foo.com", new VoidBlock() {
public void execute(HttpResponse response) {}
});
“Java
Compatibility”
java -cp "lib/*" com.springer.core.app.Casper
Scala library goes in here!
val java = new java.util.ArrayList[String]
val scala: Seq[String] = foo filter { ... }
val log = Logger.getLogger("com.foo")
log.debug("Hello!")
“Gentle
Learning Curve”
“Java without ;”
Library
re-use JVM
<XML-Support/>
<PdfInfo hasAccess="false">
<DDSId>12345</DDSId>
<ContentType>Article</ContentType>
</PdfInfo>
	 	 	
val pdfInfo =
	 	 	
val contentType = (pdfInfo  "ContentType").text
val hasAccess = (pdfInfo  "@hasAccess").text.toBoolean
val pdfInfoList = <PdfInfoList>
	 	 	 	 	 	 <PdfInfo hasAccess="false">
	 	 	 	 	 	 <DDSId>12345</DDSId>
	 	 	 	 	 		 <ContentType>Article</ContentType>
	 	 	 	 </PdfInfo>
	 	 	 	 	 	 <PdfInfo hasAccess="true">
	 	 	 	 	 	 <DDSId>54321</DDSId>
	 	 	 	 	 		 <ContentType>Book</ContentType>
	 	 	 	 	 </PdfInfo>
	 	 	 	 	 	 </PdfInfoList>
case class PdfInfo(xml: NodeSeq) {
val ddsId = (xml  "DDSId").head.text
val hasAccess = (xml  "@hasAccess").head.text
val contentType = (xml  "ContentType").head.text
}
(pdfInfoList  "PdfInfo") map { PdfInfo(_) }
“DSL-
Friendly”
System
App2
App3
Functional
App1
Unit
DB
Integration
Levels of Testing
Unit Test DSL
class PropertyTest extends Spec with ShouldMatchers {
it("should render key and value separated with an equals sign") {
Property("shark", "fish").toString should equal ("shark=fish")
}
}
class ForgottenPasswordPageTests
extends FunctionalTestSpec with ForgottenPasswordSteps with Uris {
it("should validate user email") {
given(iNavigateTo(ForgottenPasswordPage))
when(iSubmitEmail("invalid@email.com"))
then(iShouldSeeInvalidEmailErrorMessage)
}
}
Functional Test DSL
Document Validation DSL
trait DDSValidationRules extends JournalXPaths with APlusPlusElements {
val journalRules = List(
No(JournalTitle) is Invalid,
MoreThanOneElementIn(JournalArticle) is Invalid,
BadLanguageIn(JournalArticleLanguage) is Invalid,
JournalIssue With No(JournalIssueCoverYear) is Invalid,
Bibliography With No(BibliographyHeading) is Invalid,
MarkupIn(JournalTitle) is Unsupported,
MarkupIn(JournalAuthor) is Unsupported
)
}
“Active
Community”
“Fun”
“Fun”
“Fun”
val foo = (7 to 21)
“Fun”
List<Integers> foo = new ArrayList<Integers>()
for (int i = 7; i <= 21; i++) {
foo.add(i);
}
“Fun”
def eat(food: String = "plankton")
“Fun”
public void eat(String food) {...}
public void eat() {
eat("plankton");
}
get("http://foo.com") { statusCode }
“Fun”
httpSupport.get("http://foo.com", new Block<Integer>() {
public Integer execute(HttpResponse response) {
return response.getStatusLine().getStatusCode());
}
});
“Fun”
Drawbacks
“Tool
Support”
!?
1:10
“More rope...”
def ++ [B >: A, That](that: TraversableOnce[B])(implicit bf: CanBuildFrom[List[A], B, That]):That
Scala Collection Library
class JournalPageTests extends Spec with FunctionalTestSpec
with JournalPageSteps
with SearchResultsPageSteps
with LanguageSteps
with LanguageSupport
with JavascriptSupport
with Uris
with IssuePageSteps
with VolumesAndIssuesPageSteps
with CoverImageUrlBuilders
with FakeEntitlementSteps
with FullTextPageSteps
with CommonAbstractSteps
with GoogleAnalyticsSteps
with ActionSectionSteps { ... }
Traits Galore in our codebase...
xsbt
scalaz
→Can Should
Risk
Mitigations
Would we
do it again
disclaimer
use scala
at your own risk
Thanksfor
Listening
@patforna | @mhoefi

More Related Content

What's hot

Advanced Php - Macq Electronique 2010
Advanced Php - Macq Electronique 2010Advanced Php - Macq Electronique 2010
Advanced Php - Macq Electronique 2010
Michelangelo van Dam
 
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptProgrammation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScript
Loïc Knuchel
 
Benefits of Kotlin
Benefits of KotlinBenefits of Kotlin
Benefits of Kotlin
Benjamin Waye
 
11. session 11 functions and objects
11. session 11   functions and objects11. session 11   functions and objects
11. session 11 functions and objectsPhúc Đỗ
 
Spring has got me under it’s SpEL
Spring has got me under it’s SpELSpring has got me under it’s SpEL
Spring has got me under it’s SpEL
Eldad Dor
 
JavaScript Fundamentals with Angular and Lodash
JavaScript Fundamentals with Angular and LodashJavaScript Fundamentals with Angular and Lodash
JavaScript Fundamentals with Angular and Lodash
Bret Little
 
Martin Fowler's Refactoring Techniques Quick Reference
Martin Fowler's Refactoring Techniques Quick ReferenceMartin Fowler's Refactoring Techniques Quick Reference
Martin Fowler's Refactoring Techniques Quick Reference
Seung-Bum Lee
 
An introduction to property-based testing
An introduction to property-based testingAn introduction to property-based testing
An introduction to property-based testing
Vincent Pradeilles
 
Say Hello To Ecmascript 5
Say Hello To Ecmascript 5Say Hello To Ecmascript 5
Say Hello To Ecmascript 5Juriy Zaytsev
 
Scala for Java programmers
Scala for Java programmersScala for Java programmers
Scala for Java programmers
輝 子安
 
Basic java, java collection Framework and Date Time API
Basic java, java collection Framework and Date Time APIBasic java, java collection Framework and Date Time API
Basic java, java collection Framework and Date Time API
jagriti srivastava
 
Lodash js
Lodash jsLodash js
Lodash js
LearningTech
 
How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF
Luc Bors
 
Powerful JavaScript Tips and Best Practices
Powerful JavaScript Tips and Best PracticesPowerful JavaScript Tips and Best Practices
Powerful JavaScript Tips and Best Practices
Dragos Ionita
 
Alternatives of JPA/Hibernate
Alternatives of JPA/HibernateAlternatives of JPA/Hibernate
Alternatives of JPA/Hibernate
Sunghyouk Bae
 
Chaining and function composition with lodash / underscore
Chaining and function composition with lodash / underscoreChaining and function composition with lodash / underscore
Chaining and function composition with lodash / underscore
Nicolas Carlo
 
Alternate JVM Languages
Alternate JVM LanguagesAlternate JVM Languages
Alternate JVM Languages
Saltmarch Media
 

What's hot (18)

Advanced Php - Macq Electronique 2010
Advanced Php - Macq Electronique 2010Advanced Php - Macq Electronique 2010
Advanced Php - Macq Electronique 2010
 
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptProgrammation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScript
 
Benefits of Kotlin
Benefits of KotlinBenefits of Kotlin
Benefits of Kotlin
 
11. session 11 functions and objects
11. session 11   functions and objects11. session 11   functions and objects
11. session 11 functions and objects
 
Spring has got me under it’s SpEL
Spring has got me under it’s SpELSpring has got me under it’s SpEL
Spring has got me under it’s SpEL
 
JavaScript Fundamentals with Angular and Lodash
JavaScript Fundamentals with Angular and LodashJavaScript Fundamentals with Angular and Lodash
JavaScript Fundamentals with Angular and Lodash
 
Martin Fowler's Refactoring Techniques Quick Reference
Martin Fowler's Refactoring Techniques Quick ReferenceMartin Fowler's Refactoring Techniques Quick Reference
Martin Fowler's Refactoring Techniques Quick Reference
 
Java day9n
Java day9nJava day9n
Java day9n
 
An introduction to property-based testing
An introduction to property-based testingAn introduction to property-based testing
An introduction to property-based testing
 
Say Hello To Ecmascript 5
Say Hello To Ecmascript 5Say Hello To Ecmascript 5
Say Hello To Ecmascript 5
 
Scala for Java programmers
Scala for Java programmersScala for Java programmers
Scala for Java programmers
 
Basic java, java collection Framework and Date Time API
Basic java, java collection Framework and Date Time APIBasic java, java collection Framework and Date Time API
Basic java, java collection Framework and Date Time API
 
Lodash js
Lodash jsLodash js
Lodash js
 
How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF
 
Powerful JavaScript Tips and Best Practices
Powerful JavaScript Tips and Best PracticesPowerful JavaScript Tips and Best Practices
Powerful JavaScript Tips and Best Practices
 
Alternatives of JPA/Hibernate
Alternatives of JPA/HibernateAlternatives of JPA/Hibernate
Alternatives of JPA/Hibernate
 
Chaining and function composition with lodash / underscore
Chaining and function composition with lodash / underscoreChaining and function composition with lodash / underscore
Chaining and function composition with lodash / underscore
 
Alternate JVM Languages
Alternate JVM LanguagesAlternate JVM Languages
Alternate JVM Languages
 

Viewers also liked

Scala in practice - 3 years later
Scala in practice - 3 years laterScala in practice - 3 years later
Scala in practice - 3 years later
patforna
 
Agile in practice
Agile in practiceAgile in practice
Agile in practice
patforna
 
Continuous Delivery in Practice
Continuous Delivery in PracticeContinuous Delivery in Practice
Continuous Delivery in Practice
patforna
 
Stackphp
StackphpStackphp
Plato gb learnandnetworkworkshop
Plato gb learnandnetworkworkshopPlato gb learnandnetworkworkshop
Plato gb learnandnetworkworkshop
LCM
 
Final social-media-day
Final social-media-dayFinal social-media-day
Final social-media-day
LCM
 
Maximising The Potential Of Social Media Marketing
Maximising The Potential Of Social Media MarketingMaximising The Potential Of Social Media Marketing
Maximising The Potential Of Social Media Marketing
LCM
 
Social Mediafor B2 B Marketing
Social Mediafor B2 B MarketingSocial Mediafor B2 B Marketing
Social Mediafor B2 B Marketing
LCM
 
All about LCM - ethos, approach and examples
All about LCM - ethos, approach and examplesAll about LCM - ethos, approach and examples
All about LCM - ethos, approach and examples
LCM
 
Beyond Continuous Delivery at DevOpsDays Rome 2012
Beyond Continuous Delivery at DevOpsDays Rome 2012Beyond Continuous Delivery at DevOpsDays Rome 2012
Beyond Continuous Delivery at DevOpsDays Rome 2012
Chris Hilton
 
How to build a brand and protect it
How to build a brand and protect itHow to build a brand and protect it
How to build a brand and protect it
LCM
 
Confer
ConferConfer
Perforce on Tour 2015 - Securing the Helix Platform at Citrix
Perforce on Tour 2015 - Securing the Helix Platform at CitrixPerforce on Tour 2015 - Securing the Helix Platform at Citrix
Perforce on Tour 2015 - Securing the Helix Platform at Citrix
Perforce
 
Is Trunk-based Development Easy in Game Development?
Is Trunk-based Development Easy in Game Development?Is Trunk-based Development Easy in Game Development?
Is Trunk-based Development Easy in Game Development?
Perforce
 
Paris Devops - Monitoring And Feature Toggle Pattern With JMX
Paris Devops - Monitoring And Feature Toggle Pattern With JMXParis Devops - Monitoring And Feature Toggle Pattern With JMX
Paris Devops - Monitoring And Feature Toggle Pattern With JMX
Cyrille Le Clerc
 
Continous Delivery in Action
Continous Delivery in ActionContinous Delivery in Action
Continous Delivery in Action
andyhu1007
 
Trunk Based Development
Trunk Based DevelopmentTrunk Based Development
Trunk Based DevelopmentCarlos Lopes
 
The Evolution of Agile - Continuous Delivery - Extending Agile out to Product...
The Evolution of Agile - Continuous Delivery - Extending Agile out to Product...The Evolution of Agile - Continuous Delivery - Extending Agile out to Product...
The Evolution of Agile - Continuous Delivery - Extending Agile out to Product...
Burns Sheehan
 
Feature Flags Are Flawed: Let's Make Them Better - DPC
Feature Flags Are Flawed: Let's Make Them Better - DPCFeature Flags Are Flawed: Let's Make Them Better - DPC
Feature Flags Are Flawed: Let's Make Them Better - DPC
Stephen Young
 
Trunk Based Development in the Enterprise - Its Relevance and Economics
Trunk Based Development in the Enterprise - Its Relevance and EconomicsTrunk Based Development in the Enterprise - Its Relevance and Economics
Trunk Based Development in the Enterprise - Its Relevance and Economics
Perforce
 

Viewers also liked (20)

Scala in practice - 3 years later
Scala in practice - 3 years laterScala in practice - 3 years later
Scala in practice - 3 years later
 
Agile in practice
Agile in practiceAgile in practice
Agile in practice
 
Continuous Delivery in Practice
Continuous Delivery in PracticeContinuous Delivery in Practice
Continuous Delivery in Practice
 
Stackphp
StackphpStackphp
Stackphp
 
Plato gb learnandnetworkworkshop
Plato gb learnandnetworkworkshopPlato gb learnandnetworkworkshop
Plato gb learnandnetworkworkshop
 
Final social-media-day
Final social-media-dayFinal social-media-day
Final social-media-day
 
Maximising The Potential Of Social Media Marketing
Maximising The Potential Of Social Media MarketingMaximising The Potential Of Social Media Marketing
Maximising The Potential Of Social Media Marketing
 
Social Mediafor B2 B Marketing
Social Mediafor B2 B MarketingSocial Mediafor B2 B Marketing
Social Mediafor B2 B Marketing
 
All about LCM - ethos, approach and examples
All about LCM - ethos, approach and examplesAll about LCM - ethos, approach and examples
All about LCM - ethos, approach and examples
 
Beyond Continuous Delivery at DevOpsDays Rome 2012
Beyond Continuous Delivery at DevOpsDays Rome 2012Beyond Continuous Delivery at DevOpsDays Rome 2012
Beyond Continuous Delivery at DevOpsDays Rome 2012
 
How to build a brand and protect it
How to build a brand and protect itHow to build a brand and protect it
How to build a brand and protect it
 
Confer
ConferConfer
Confer
 
Perforce on Tour 2015 - Securing the Helix Platform at Citrix
Perforce on Tour 2015 - Securing the Helix Platform at CitrixPerforce on Tour 2015 - Securing the Helix Platform at Citrix
Perforce on Tour 2015 - Securing the Helix Platform at Citrix
 
Is Trunk-based Development Easy in Game Development?
Is Trunk-based Development Easy in Game Development?Is Trunk-based Development Easy in Game Development?
Is Trunk-based Development Easy in Game Development?
 
Paris Devops - Monitoring And Feature Toggle Pattern With JMX
Paris Devops - Monitoring And Feature Toggle Pattern With JMXParis Devops - Monitoring And Feature Toggle Pattern With JMX
Paris Devops - Monitoring And Feature Toggle Pattern With JMX
 
Continous Delivery in Action
Continous Delivery in ActionContinous Delivery in Action
Continous Delivery in Action
 
Trunk Based Development
Trunk Based DevelopmentTrunk Based Development
Trunk Based Development
 
The Evolution of Agile - Continuous Delivery - Extending Agile out to Product...
The Evolution of Agile - Continuous Delivery - Extending Agile out to Product...The Evolution of Agile - Continuous Delivery - Extending Agile out to Product...
The Evolution of Agile - Continuous Delivery - Extending Agile out to Product...
 
Feature Flags Are Flawed: Let's Make Them Better - DPC
Feature Flags Are Flawed: Let's Make Them Better - DPCFeature Flags Are Flawed: Let's Make Them Better - DPC
Feature Flags Are Flawed: Let's Make Them Better - DPC
 
Trunk Based Development in the Enterprise - Its Relevance and Economics
Trunk Based Development in the Enterprise - Its Relevance and EconomicsTrunk Based Development in the Enterprise - Its Relevance and Economics
Trunk Based Development in the Enterprise - Its Relevance and Economics
 

Similar to Scala in practice

Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsTaming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsJarod Ferguson
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
Dmitry Sheiko
 
Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?
Jesper Kamstrup Linnet
 
The Future of JVM Languages
The Future of JVM Languages The Future of JVM Languages
The Future of JVM Languages
VictorSzoltysek
 
Persisting Data on SQLite using Room
Persisting Data on SQLite using RoomPersisting Data on SQLite using Room
Persisting Data on SQLite using Room
Nelson Glauber Leal
 
Specs2
Specs2Specs2
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6Dmitry Soshnikov
 
Ast transformations
Ast transformationsAst transformations
Ast transformations
HamletDRC
 
CS101- Introduction to Computing- Lecture 29
CS101- Introduction to Computing- Lecture 29CS101- Introduction to Computing- Lecture 29
CS101- Introduction to Computing- Lecture 29
Bilal Ahmed
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
2014-11-01 01 Денис Нелюбин. О сортах кофе
2014-11-01 01 Денис Нелюбин. О сортах кофе2014-11-01 01 Денис Нелюбин. О сортах кофе
2014-11-01 01 Денис Нелюбин. О сортах кофе
Омские ИТ-субботники
 
Working With JQuery Part1
Working With JQuery Part1Working With JQuery Part1
Working With JQuery Part1saydin_soft
 
Scala - en bedre Java?
Scala - en bedre Java?Scala - en bedre Java?
Scala - en bedre Java?
Jesper Kamstrup Linnet
 
can you add a delete button and a add button to the below program. j.pdf
can you add a delete button and a add button to the below program. j.pdfcan you add a delete button and a add button to the below program. j.pdf
can you add a delete button and a add button to the below program. j.pdf
sales88
 
つくってあそぼ Kotlin DSL ~拡張編~
つくってあそぼ Kotlin DSL ~拡張編~つくってあそぼ Kotlin DSL ~拡張編~
つくってあそぼ Kotlin DSL ~拡張編~
kamedon39
 
Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2
Kirill Rozov
 
jQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journeyjQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journey
Huiyi Yan
 

Similar to Scala in practice (20)

Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsTaming that client side mess with Backbone.js
Taming that client side mess with Backbone.js
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
 
Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?
 
The Future of JVM Languages
The Future of JVM Languages The Future of JVM Languages
The Future of JVM Languages
 
Persisting Data on SQLite using Room
Persisting Data on SQLite using RoomPersisting Data on SQLite using Room
Persisting Data on SQLite using Room
 
Specs2
Specs2Specs2
Specs2
 
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
 
Ast transformations
Ast transformationsAst transformations
Ast transformations
 
CS101- Introduction to Computing- Lecture 29
CS101- Introduction to Computing- Lecture 29CS101- Introduction to Computing- Lecture 29
CS101- Introduction to Computing- Lecture 29
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
2014-11-01 01 Денис Нелюбин. О сортах кофе
2014-11-01 01 Денис Нелюбин. О сортах кофе2014-11-01 01 Денис Нелюбин. О сортах кофе
2014-11-01 01 Денис Нелюбин. О сортах кофе
 
Working With JQuery Part1
Working With JQuery Part1Working With JQuery Part1
Working With JQuery Part1
 
Scala - en bedre Java?
Scala - en bedre Java?Scala - en bedre Java?
Scala - en bedre Java?
 
can you add a delete button and a add button to the below program. j.pdf
can you add a delete button and a add button to the below program. j.pdfcan you add a delete button and a add button to the below program. j.pdf
can you add a delete button and a add button to the below program. j.pdf
 
つくってあそぼ Kotlin DSL ~拡張編~
つくってあそぼ Kotlin DSL ~拡張編~つくってあそぼ Kotlin DSL ~拡張編~
つくってあそぼ Kotlin DSL ~拡張編~
 
Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2
 
jQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journeyjQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journey
 

Recently uploaded

Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke
 
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissancesAtelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Neo4j
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
Globus
 
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of CodeA Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
Aftab Hussain
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Crescat
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
wottaspaceseo
 
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdfAutomated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
timtebeek1
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
Donna Lenk
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
Globus
 
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
Alina Yurenko
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
Globus
 
GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote session
Globus
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
Juraj Vysvader
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Globus
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Adele Miller
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Globus
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus
 
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptxText-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
ShamsuddeenMuhammadA
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
Georgi Kodinov
 

Recently uploaded (20)

Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
 
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissancesAtelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissances
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
 
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of CodeA Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
 
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdfAutomated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
 
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
 
GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote session
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
 
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptxText-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
 

Scala in practice

  • 2.
  • 7.
  • 8.
  • 9.
  • 11.
  • 17. List<String> features = Arrays.asList("noFeature", "featureC", "featureB", "featureA"); for (String feature : features) { System.out.println(feature); }
  • 18. List<String> javaFeatures = Arrays.asList("noFeature", "featureC", "featureB", "featureA"); for (String feature : javaFeatures) { System.out.println(feature); } val scalaFeatures = List( "noFeature", "featureC", "featureB", "featureA") scalaFeatures foreach { println _ }
  • 19. val currentFeatures = List("noFeature", "featureC", "featureB", "featureA") Result: "featureA_toggle, featureB_toggle" currentFeatures.filter { _.startsWith("feature") } .mkString(", ") .map { _ + "_toggle" } .sorted .take(2)
  • 20. String result = ""; List<String> currentFeatures = Arrays.asList("noFeature", "featureC", "featureB", "featureA"); Collections.sort(currentFeatures); int i = 0, j = 0, take = 2; while(i < take && j < currentFeatures.size()) { String feature = currentFeatures.get(j++); if(feature.startsWith("feature")) { result += feature + "_toggle" + ((i++ != take) ? ", " : ""); } } currentFeatures.filter { _.startsWith("feature") } .mkString(", ") .map { _ + "_toggle" } .sorted .take(2)
  • 24. public class Property { private final String key; private final String value; private final String defaultValue; public Property(String key, String value, String defaultValue) { this.key = key; this.value = value; this.defaultValue = defaultValue; } }
  • 25. class Property(key: String, value: String, default: String) {}
  • 26. public class Property { // ... public String getKey() { return key; } public String getValue() { return value; } public String getDefaultValue() { return defaultValue; } }
  • 27. class Property(val key: String, val value: String, val default: String) {}
  • 28. public class Property { // ... public Property changeTo(String newValue) { return new Property(key, value, newValue); } public Property reset() { return new Property(key, value); } @Override public String toString() { return String.format("%s=%s", key, value); } }
  • 29. class Property(val key: String, val value: String, val default: String) { def changeTo(newValue: String) = new Property(key, newValue, default) def reset = new Property(key, default) override def toString = "%s=%s" format(key, value) }
  • 30. public class Property { // ... @Override public boolean equals(Object obj) { if (!(obj instanceof Property)) return false; Property other = (Property) obj; return other.key.equals(key) && other.value.equals(value) && other.defaultValue.equals(defaultValue) } @Override public int hashCode() { int result = 17; result = 31 * result + key; result = 31 * result + value; result = 31 * result + defaultValue; return result; } }
  • 31. case class Property(key: String, value: String, default: String) { def changeTo(newValue: String) = Property(key, newValue, default) def reset = Property(key, default) override def toString = "%s=%s" format(key, value) }
  • 32. public class Property { private final String key; private final String value; private final String defaultValue; public Property(String key, String value, String defaultValue) { this.key = key; this.value = value; this.defaultValue = defaultValue; } public String getKey() { return key; } public String getValue() { return value; } public String getDefaultValue() { return defaultValue; } public Property changeTo(String newValue) { return new Property(key, value, newValue); } public Property reset() { return new Property(key, value); } @Override public String toString() { return String.format("%s=%s", key, value); } @Override public boolean equals(Object obj) { if (!(obj instanceof Property)) return false; Property other = (Property) obj; return other.key.equals(key) && other.value.equals(value) && other.defaultValue.equals(defaultValue) } @Override public int hashCode() { int result = 17; result = 31 * result + key; result = 31 * result + value; result = 31 * result + defaultValue; return result; } }
  • 33. case class Property(key: String, value: String, default: String) { def changeTo(newValue: String) = Property(key, newValue, default) def reset = Property(key, default) override def toString = "%s=%s" format(key, value) }
  • 34. public class Property { private final String key; private final String value; private final String defaultValue; public Property(String key, String value, String defaultValue) { this.key = key; this.value = value; this.defaultValue = defaultValue; } public String getKey() { return key; } public String getValue() { return value; } public String getDefaultValue() { return defaultValue; } public Property changeTo(String newValue) { return new Property(key, value, newValue); } public Property reset() { return new Property(key, value); } @Override public boolean equals(Object obj) { if (!(obj instanceof Property)) return false; Property other = (Property) obj; return other.key.equals(key) && other.value.equals(value) && other.defaultValue.equals(defaultValue) } @Override public int hashCode() { int result = 17; result = 31 * result + key; result = 31 * result + value; result = 31 * result + defaultValue; return result; } @Override public String toString() { return String.format("%s=%s", key, value); } } case class Property(key: String, value: String, default: String) { def changeTo(newValue: String) = Property(key, newValue, default) def reset = Property(key, default) override def toString = "%s=%s" format(key, value) } 45 vs 5 LOCs * ignoring blank lines
  • 35. Another Example: { Blocks } “Less Boilerplate”
  • 36. val content = get("http://foo.com") { toString } val statusCode = get("http://foo.com") { statusCode } get("http://foo.com") int statusCode = httpSupport.get("http://foo.com", new Block<Integer>() { public Integer execute(HttpResponse response) { return response.getStatusLine().getStatusCode()); } }); String content = httpSupport.get("http://foo.com", new Block<String>() { public Integer execute(HttpResponse response) { return EntityUtils.toString(response.getEntity()); } }); httpSupport.get("http://foo.com", new VoidBlock() { public void execute(HttpResponse response) {} });
  • 38. java -cp "lib/*" com.springer.core.app.Casper Scala library goes in here!
  • 39. val java = new java.util.ArrayList[String] val scala: Seq[String] = foo filter { ... }
  • 40. val log = Logger.getLogger("com.foo") log.debug("Hello!")
  • 41.
  • 44. <PdfInfo hasAccess="false"> <DDSId>12345</DDSId> <ContentType>Article</ContentType> </PdfInfo> val pdfInfo = val contentType = (pdfInfo "ContentType").text val hasAccess = (pdfInfo "@hasAccess").text.toBoolean
  • 45. val pdfInfoList = <PdfInfoList> <PdfInfo hasAccess="false"> <DDSId>12345</DDSId> <ContentType>Article</ContentType> </PdfInfo> <PdfInfo hasAccess="true"> <DDSId>54321</DDSId> <ContentType>Book</ContentType> </PdfInfo> </PdfInfoList> case class PdfInfo(xml: NodeSeq) { val ddsId = (xml "DDSId").head.text val hasAccess = (xml "@hasAccess").head.text val contentType = (xml "ContentType").head.text } (pdfInfoList "PdfInfo") map { PdfInfo(_) }
  • 48. Unit Test DSL class PropertyTest extends Spec with ShouldMatchers { it("should render key and value separated with an equals sign") { Property("shark", "fish").toString should equal ("shark=fish") } }
  • 49. class ForgottenPasswordPageTests extends FunctionalTestSpec with ForgottenPasswordSteps with Uris { it("should validate user email") { given(iNavigateTo(ForgottenPasswordPage)) when(iSubmitEmail("invalid@email.com")) then(iShouldSeeInvalidEmailErrorMessage) } } Functional Test DSL
  • 50. Document Validation DSL trait DDSValidationRules extends JournalXPaths with APlusPlusElements { val journalRules = List( No(JournalTitle) is Invalid, MoreThanOneElementIn(JournalArticle) is Invalid, BadLanguageIn(JournalArticleLanguage) is Invalid, JournalIssue With No(JournalIssueCoverYear) is Invalid, Bibliography With No(BibliographyHeading) is Invalid, MarkupIn(JournalTitle) is Unsupported, MarkupIn(JournalAuthor) is Unsupported ) }
  • 54. “Fun” val foo = (7 to 21)
  • 55. “Fun” List<Integers> foo = new ArrayList<Integers>() for (int i = 7; i <= 21; i++) { foo.add(i); }
  • 57. “Fun” public void eat(String food) {...} public void eat() { eat("plankton"); }
  • 59. httpSupport.get("http://foo.com", new Block<Integer>() { public Integer execute(HttpResponse response) { return response.getStatusLine().getStatusCode()); } }); “Fun”
  • 62.
  • 63.
  • 64. !?
  • 65. 1:10
  • 67. def ++ [B >: A, That](that: TraversableOnce[B])(implicit bf: CanBuildFrom[List[A], B, That]):That Scala Collection Library
  • 68. class JournalPageTests extends Spec with FunctionalTestSpec with JournalPageSteps with SearchResultsPageSteps with LanguageSteps with LanguageSupport with JavascriptSupport with Uris with IssuePageSteps with VolumesAndIssuesPageSteps with CoverImageUrlBuilders with FakeEntitlementSteps with FullTextPageSteps with CommonAbstractSteps with GoogleAnalyticsSteps with ActionSectionSteps { ... } Traits Galore in our codebase...
  • 69. xsbt
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79. Would we do it again