in PracticeScala
@patforna
patric.fornasier@springer.com
3 years later…
Context
Context
Pat
Springer
Software
Engineer
Technical
Principal
10+ years
Academic
Publisher
Pretty Large
Springer
Link
Strategic
95 % Online
Revenue
66 % Total
Revenue
9 Mio items
2TB XML
Re-built
3 years ago
Content
Delivery
Platform
52 Mio
PageViews / Month
99.9%
Availability
Scala NoSql
Co-Sourced
Team
TW
Ex-TW
Springer
Global
CD
SpringerLink
Timeline
Start
development
Cycling
Trip
Re-joined
Product -> platform
Paying back tech debt
Today
04/11 04/12 08/13 04/14
Inception
05/12 09/12
Bookfair
Release
RD
Live
User migration,
enhancements
Link
Live
Smart
Books
Live
Enhancements
Looking back: why scala?
• Increase productivity
• Be more attractive employer
• Team decision
Looking back: good vs bad
Good
• Functional programming
• Terse syntax
• JVM ecosystem
• Gentle learning curve
• DSL friendly syntax
• Motivated team
Bad
• Tool support
• Compilation times
• Language complexity #moreRope
Fast-forward
Fast-forward (Aug 2013)
• 2.5 years into project
• 1.5 years of weekly live releases
• 100k LOC
• >10k commits
• >90 committers
Fast-forward (Aug 2013)
• 2.5 years into project
• 1.5 years of weekly live releases
• 100k LOC
• >10k commits
• >90 committers
not all related to Scala - to be fair
• Poor feedback loops
• Lots of accidental complexity
Trend (2 years)
LOC
~ 100k
Trend (2 years)
build time
LOC
Trend (2 years)
build time
LOC
• 1:34 min src/main
• 6:44 min src/test
• 8:18 min total
What did we do?
What did we do
• Reduced build time
• Improved feedback loops
• Reduced accidental complexity
Build time
• Reduced size of codebase (broke off vertical slices, pulled out APIs, pulled out libraries,
removed unused features, removed low-value tests, etc.)
• Reduced usage of certain language features (esp. traits and implicits)
Trend (Dec 2013)
LOC
Trend (Dec 2013)
build time
# traits
LOC
unable to compile on	

13” macbook
Trend (Dec 2013)
build time
# traits
LOC
unable to compile on	

13” macbook
The problem with traits
• Will re-compile on every class the trait is mixed in
• Slows down dev-build cycle
• Will result in byte code bloat
• Will compile *a lot* slower
!
For faster compile times:
• Use pure traits
• Use old-school composition for code re-use
• Use pure functions via imports (e.g. import Foo._)
• If unavoidable, use inheritance for code re-use
Build time
Build time
• 1:34 min src/main
• 6:44 min src/test
• 8:18 min total
Build time
• 1:34 min src/main
• 6:44 min src/test
• 8:18 min total
• 0:24 min src/main
• 3:11 min src/test
• 3:35 min total
Build time (on CI server)
• Incremental compilation on CI
• Only one dedicated CI agent
• Physical build servers
• CPUs with higher clock speed
Build time (on CI server)
• Incremental compilation on CI
• Only one dedicated CI agent
• Physical build servers
• CPUs with higher clock speed
Complexity
Complexity
• There’s still a lot of code in our codebase that is hard to read
• It seems to be very easy to shoot yourself in the foot with Scala
• Scala *is* complex (and that’s why scalac will never be as fast as javac)
Complexity
• There’s still a lot of code in our codebase that is hard to read
• It seems to be very easy to shoot yourself in the foot with Scala
• Scala *is* complex (and that’s why scalac will never be as fast as javac)
Invariant/covariant/contravariant types (T, +T and -T)	
Refined types (new Foo {...})	
Structural types (x: {def y: Int})	
Path dependant types (a.B)	
Specialized types (@specialized)	
Self types (this =>)	
Projection types (A#B)	
Existential types (M[_])	
Type bounds (<:, >:) 	
Type constraints (=:=, <:< and <%<)	
Type members (type T)	
Type aliases (type T = Int)	
Type classes ( (implicit ...) )	
View bounds (<%)	
Higher kinded types (* => *)	
F-Bounded type polymorphism (M[T <: M[T]])
http://nurkiewicz.github.io/talks/2014/scalar/#/16
Not opinionated
For example: http://twitter.github.io/effectivescala/
• Many ways to do the same thing
• Coding conventions help, but only so much
Not opinionated
def foo() = "foo"	
def bar = "bar"	
!
foo	
foo()	
bar	
bar() // won't compile
For example: http://twitter.github.io/effectivescala/
• Many ways to do the same thing
• Coding conventions help, but only so much
Not opinionated
def foo() = "foo"	
def bar = "bar"	
!
foo	
foo()	
bar	
bar() // won't compile
For example: http://twitter.github.io/effectivescala/
• Many ways to do the same thing
• Coding conventions help, but only so much
def baz(x: String) = x	
“x”.charAt(0)	
“x” charAt(0) // won't compile	
“x”.charAt 0 // won't compile	
“x” charAt 0	
baz("x")	
baz “x" // won't compile
Not opinionated
def foo() = "foo"	
def bar = "bar"	
!
foo	
foo()	
bar	
bar() // won't compile
list.foreach { x => println(x) }	
list.foreach ( x => println(x) )	
list.foreach { println(_) }	
list.foreach ( println(_) )	
list foreach { x => println(x) }	
list foreach ( x => println(x) )	
list foreach { println(_) }	
list foreach ( println(_) )
For example: http://twitter.github.io/effectivescala/
• Many ways to do the same thing
• Coding conventions help, but only so much
def baz(x: String) = x	
“x”.charAt(0)	
“x” charAt(0) // won't compile	
“x”.charAt 0 // won't compile	
“x” charAt 0	
baz("x")	
baz “x" // won't compile
Not opinionated
def foo() = "foo"	
def bar = "bar"	
!
foo	
foo()	
bar	
bar() // won't compile
list.foreach { x => println(x) }	
list.foreach ( x => println(x) )	
list.foreach { println(_) }	
list.foreach ( println(_) )	
list foreach { x => println(x) }	
list foreach ( x => println(x) )	
list foreach { println(_) }	
list foreach ( println(_) )
if (foo) "x" else "y"	
	
foo match {	
case true => "x"	
case _ => "y"	
}
For example: http://twitter.github.io/effectivescala/
• Many ways to do the same thing
• Coding conventions help, but only so much
def baz(x: String) = x	
“x”.charAt(0)	
“x” charAt(0) // won't compile	
“x”.charAt 0 // won't compile	
“x” charAt 0	
baz("x")	
baz “x" // won't compile
Surprises
http://dan.bodar.com/2013/12/04/wat-scala/
Surprises
List(1, 2, 3).toSet
http://dan.bodar.com/2013/12/04/wat-scala/
Surprises
List(1, 2, 3).toSet
scala.collection.immutable.Set[Int] = Set(1, 2, 3)
http://dan.bodar.com/2013/12/04/wat-scala/
Surprises
List(1, 2, 3).toSet
scala.collection.immutable.Set[Int] = Set(1, 2, 3)
List(1, 2, 3).toSet()
http://dan.bodar.com/2013/12/04/wat-scala/
Surprises
List(1, 2, 3).toSet
scala.collection.immutable.Set[Int] = Set(1, 2, 3)
List(1, 2, 3).toSet()
Boolean = false
http://dan.bodar.com/2013/12/04/wat-scala/
Implicits
• Can make it very hard to read code
• Tool support is very bad
• Impacts compilation time
• Surprising behaviour (esp. when used with overloaded methods or optional params)
Tooling
def handle(response: HttpResponse, request: HttpRequest)
• Tool support is still very basic
• Makes it hard to continuously refactor (which means people are less likely to do it)
Tooling
def handle(response: HttpResponse, request: HttpRequest)
• Tool support is still very basic
• Makes it hard to continuously refactor (which means people are less likely to do it)
no luck with “change signature”
refactoring support
Trait entanglements
• Makes it difficult to reason about behaviour
Trait entanglements
• Makes it difficult to reason about behaviour
trait A {
def foo = "a"
}
Trait entanglements
• Makes it difficult to reason about behaviour
trait A {
def foo = "a"
}
trait B extends A {
override def foo = "b"
}
Trait entanglements
• Makes it difficult to reason about behaviour
trait A {
def foo = "a"
}
trait B extends A {
override def foo = "b"
}
class C extends A with B
new C().foo
Trait entanglements
• Makes it difficult to reason about behaviour
trait A {
def foo = "a"
}
trait B extends A {
override def foo = "b"
}
class C extends A with B
new C().foo
"b"
Trait entanglements
• Makes it difficult to reason about behaviour
trait A {
def foo = "a"
}
trait B extends A {
override def foo = "b"
}
class C extends A with B
new C().foo
"b"
class D extends B with A
new D().foo
Trait entanglements
• Makes it difficult to reason about behaviour
trait A {
def foo = "a"
}
trait B extends A {
override def foo = "b"
}
class C extends A with B
new C().foo
"b"
class D extends B with A
new D().foo
"b"
Trait entanglements (2)
ArticlePageSteps
WebDriverSupport
AuthorStepsCoverImageSteps
SummarySection
Waiter SectionPageSteps
CommonPageSteps
WebElementSupport
Assertions
Uris TripleEquals
OnHost TripleEqualsSupport
MachineNames
Trait entanglements (3)
ArticlePageSteps_0
WebDriverSupport_1 AuthorSteps_1 CoverImageSteps_1 SummarySection_1Waiter_1 SectionPageSteps_1 CommonPageSteps_1
CommonPageSteps_2 WebElementSupport_2Assertions_2 WebDriverSupport_2Uris_2
WebElementSupport_3 WebDriverSupport_3Uris_3 TripleEquals_3 OnHost_3
OnHost_4 TripleEqualsSupport_4 MachineNames_4
MachineNames_5
Trait entanglements (3)
ArticlePageSteps_0
WebDriverSupport_1 AuthorSteps_1 CoverImageSteps_1 SummarySection_1Waiter_1 SectionPageSteps_1 CommonPageSteps_1
CommonPageSteps_2 WebElementSupport_2Assertions_2 WebDriverSupport_2Uris_2
WebElementSupport_3 WebDriverSupport_3Uris_3 TripleEquals_3 OnHost_3
OnHost_4 TripleEqualsSupport_4 MachineNames_4
MachineNames_5
Trait entanglements (4)
ArticlePageTests_0
ArticlePageSteps_1 AboutSectionSteps_1 SearchResultsPageSteps_1 Uris_1 ArticleTestFixture_1 JavascriptSupport_1 IssuePageSteps_1 CommonAbstractSteps_1 GoogleAnalyticsSteps_1 FakeEntitlementSteps_1 ExportCitationPageSteps_1 FullTextPageSteps_1 OtherActionsSectionSteps_1
WebDriverSupport_2 AuthorSteps_2 CoverImageSteps_2 SummarySection_2Waiter_2 SectionPageSteps_2 CommonPageSteps_2
CommonPageSteps_3 WebElementSupport_3Assertions_3 WebDriverSupport_3Uris_3
WebElementSupport_4 WebDriverSupport_4Uris_4 TripleEquals_4 OnHost_4
OnHost_5 TripleEqualsSupport_5 MachineNames_5
MachineNames_6
Trait entanglements (4)
ArticlePageTests_0
ArticlePageSteps_1 AboutSectionSteps_1 SearchResultsPageSteps_1 Uris_1 ArticleTestFixture_1 JavascriptSupport_1 IssuePageSteps_1 CommonAbstractSteps_1 GoogleAnalyticsSteps_1 FakeEntitlementSteps_1 ExportCitationPageSteps_1 FullTextPageSteps_1 OtherActionsSectionSteps_1
WebDriverSupport_2 AuthorSteps_2 CoverImageSteps_2 SummarySection_2Waiter_2 SectionPageSteps_2 CommonPageSteps_2
CommonPageSteps_3 WebElementSupport_3Assertions_3 WebDriverSupport_3Uris_3
WebElementSupport_4 WebDriverSupport_4Uris_4 TripleEquals_4 OnHost_4
OnHost_5 TripleEqualsSupport_5 MachineNames_5
MachineNames_6
Imagine many more circle here
So, what’s next?
Today
• We’ve delivered successfully using Scala
• Don’t think we’re more productive (pure gut feeling, though)
• We try to stick to the good parts (conventions, functional programming, pattern matching, etc.)
• Complexity, slow compilation and lack of tool support are real problems
The future
• No urgency to move away from Scala or re-write existing systems
• Java 8 is an alternative
• Smaller teams and apps will probably lead to more polyglotism (and less Scala)
Thanks
@patforna
patric.fornasier@springer.com
http://joinit.springer.com

More Related Content

PPTX
Promise of a better future by Rahul Goma Phulore and Pooja Akshantal, Thought...
PDF
Quarterly Technology Briefing, Manchester, UK September 2013
PDF
Reactive All the Way Down the Stack
PDF
Greach 2018: Surviving Microservices
PDF
from ai.backend import python @ pycontw2018
PPTX
Why akka
PDF
Scaling Uber
PDF
Challenges of moving a java team to scala
Promise of a better future by Rahul Goma Phulore and Pooja Akshantal, Thought...
Quarterly Technology Briefing, Manchester, UK September 2013
Reactive All the Way Down the Stack
Greach 2018: Surviving Microservices
from ai.backend import python @ pycontw2018
Why akka
Scaling Uber
Challenges of moving a java team to scala

What's hot (20)

PDF
Building Efficient and Reliable Crawler System With Sidekiq Enterprise
PDF
Product Managers are from Pluto and UXers are from Uranus
PDF
Donald Ferguson - Old Programmers Can Learn New Tricks
PDF
Beyond The Rails Way
PDF
Performance and Abstractions
PDF
Evolving the Netflix API
PPTX
Extending Ansible - Ansible Benelux meetup - Amsterdam 11-02-2016
PDF
RubyConf China 2015 - Rails off assets pipeline
PPTX
Skype goes agile
PPTX
Why Enterprises Are Embracing the Cloud
PDF
Devops and Immutable infrastructure - Cloud Expo 2015 NYC
PDF
An Introduction to Reactive Application, Reactive Streams, and options for JVM
PDF
The Netflix API Platform for Server-Side Scripting
PPTX
EXPERTALKS: Jul 2012 - Build using Gradle
PDF
Test Automation for Packaged Systems: Yes, You Can!
PPTX
Ansible benelux meetup - Amsterdam 27-5-2015
KEY
Lessons from Branch's launch
PDF
Taking Gliffy to the Cloud – Moving to Atlassian Connect - Mike Cialowicz
PPTX
AWS Summit New York Recap 2016
PPTX
You don’t need DTAP + Backbase implementation - Amsterdam 17-12-2015
Building Efficient and Reliable Crawler System With Sidekiq Enterprise
Product Managers are from Pluto and UXers are from Uranus
Donald Ferguson - Old Programmers Can Learn New Tricks
Beyond The Rails Way
Performance and Abstractions
Evolving the Netflix API
Extending Ansible - Ansible Benelux meetup - Amsterdam 11-02-2016
RubyConf China 2015 - Rails off assets pipeline
Skype goes agile
Why Enterprises Are Embracing the Cloud
Devops and Immutable infrastructure - Cloud Expo 2015 NYC
An Introduction to Reactive Application, Reactive Streams, and options for JVM
The Netflix API Platform for Server-Side Scripting
EXPERTALKS: Jul 2012 - Build using Gradle
Test Automation for Packaged Systems: Yes, You Can!
Ansible benelux meetup - Amsterdam 27-5-2015
Lessons from Branch's launch
Taking Gliffy to the Cloud – Moving to Atlassian Connect - Mike Cialowicz
AWS Summit New York Recap 2016
You don’t need DTAP + Backbase implementation - Amsterdam 17-12-2015

Viewers also liked (20)

PPTX
Презентация 1.25 - Диспетчеризация инженерных систем
PDF
ABC ELP Program - Innovation in government
PDF
Living Wall - Arabic
PDF
E-acme E-tailer elettronica di consumo
PDF
Building Out Your Editorial Calendar 4.24.13
PDF
利用資訊擷取技術之適性化語言輔助學習系統
PDF
HackconEU: Hackathons are for Hackers
PPTX
Energy Matters Summit, Peel Region 6 May 2013
PDF
"Year of the Selfie" [INFOGRAPHIC]
PPTX
Video Encoding and HTML5 Playback With Native DRM
PDF
Piko Farms v. Hawaii Health Department
PDF
Guía de capacitación de sst 2-radiación solar
PPTX
Using eventbrite to manage your event registration
PDF
מתחת לקלמנטיה
PPT
欧赛斯品牌网络整合营销外包解决方案
PPTX
Čo nás môžu reštaurácie naučiť o online biznise?
DOC
Cuestionario De Convivencia Pais
PPT
The Future Of Social Networks
PDF
Report: Wearable Technology - Ready for Prime Time?
PPTX
Bolero Crowdfunding Inspiratiesessie Roeselare - 2 juni 2016
Презентация 1.25 - Диспетчеризация инженерных систем
ABC ELP Program - Innovation in government
Living Wall - Arabic
E-acme E-tailer elettronica di consumo
Building Out Your Editorial Calendar 4.24.13
利用資訊擷取技術之適性化語言輔助學習系統
HackconEU: Hackathons are for Hackers
Energy Matters Summit, Peel Region 6 May 2013
"Year of the Selfie" [INFOGRAPHIC]
Video Encoding and HTML5 Playback With Native DRM
Piko Farms v. Hawaii Health Department
Guía de capacitación de sst 2-radiación solar
Using eventbrite to manage your event registration
מתחת לקלמנטיה
欧赛斯品牌网络整合营销外包解决方案
Čo nás môžu reštaurácie naučiť o online biznise?
Cuestionario De Convivencia Pais
The Future Of Social Networks
Report: Wearable Technology - Ready for Prime Time?
Bolero Crowdfunding Inspiratiesessie Roeselare - 2 juni 2016

Similar to Scala in-practice-3-years by Patric Fornasier, Springr, presented at Pune Scala Symposium 2014, ThoughtWorks (20)

PDF
TypeScript와 Flow: 
자바스크립트 개발에 정적 타이핑 도입하기
PPTX
From Ruby to Scala
KEY
wwc start-launched
KEY
PTW Rails Bootcamp
PPTX
Go from a PHP Perspective
PPTX
Code for Startup MVP (Ruby on Rails) Session 2
PDF
Ingo Muschenetz: Titanium Studio Deep Dive
PDF
Effective Scala (JavaDay Riga 2013)
PPTX
Introduction to Kotlin Language and its application to Android platform
PPTX
The openCypher Project - An Open Graph Query Language
PDF
Unleash your inner console cowboy
PPTX
Strong typing : adoption, adaptation and organisation
PDF
4 JVM Web Frameworks
PPTX
Should i Go there
PDF
JAZOON'13 - Paul Brauner - A backend developer meets the web: my Dart experience
PDF
Elegant concurrency
PDF
Introduction to the rust programming language
PDF
Introduction to clojure
PPTX
What the C?
PDF
Torquebox OSCON Java 2011
TypeScript와 Flow: 
자바스크립트 개발에 정적 타이핑 도입하기
From Ruby to Scala
wwc start-launched
PTW Rails Bootcamp
Go from a PHP Perspective
Code for Startup MVP (Ruby on Rails) Session 2
Ingo Muschenetz: Titanium Studio Deep Dive
Effective Scala (JavaDay Riga 2013)
Introduction to Kotlin Language and its application to Android platform
The openCypher Project - An Open Graph Query Language
Unleash your inner console cowboy
Strong typing : adoption, adaptation and organisation
4 JVM Web Frameworks
Should i Go there
JAZOON'13 - Paul Brauner - A backend developer meets the web: my Dart experience
Elegant concurrency
Introduction to the rust programming language
Introduction to clojure
What the C?
Torquebox OSCON Java 2011

More from Thoughtworks (20)

PDF
Design System as a Product
PDF
Designers, Developers & Dogs
PDF
Cloud-first for fast innovation
PDF
More impact with flexible teams
PDF
Culture of Innovation
PDF
Dual-Track Agile
PDF
Developer Experience
PDF
When we design together
PDF
Hardware is hard(er)
PDF
Customer-centric innovation enabled by cloud
PDF
Amazon's Culture of Innovation
PDF
When in doubt, go live
PDF
Don't cross the Rubicon
PDF
Error handling
PDF
Your test coverage is a lie!
PDF
Docker container security
PDF
Redefining the unit
PPTX
Technology Radar Webinar UK - Vol. 22
PDF
A Tribute to Turing
PDF
Rsa maths worked out
Design System as a Product
Designers, Developers & Dogs
Cloud-first for fast innovation
More impact with flexible teams
Culture of Innovation
Dual-Track Agile
Developer Experience
When we design together
Hardware is hard(er)
Customer-centric innovation enabled by cloud
Amazon's Culture of Innovation
When in doubt, go live
Don't cross the Rubicon
Error handling
Your test coverage is a lie!
Docker container security
Redefining the unit
Technology Radar Webinar UK - Vol. 22
A Tribute to Turing
Rsa maths worked out

Recently uploaded (20)

PDF
Early detection and classification of bone marrow changes in lumbar vertebrae...
PDF
Human Computer Interaction Miterm Lesson
PDF
Lung cancer patients survival prediction using outlier detection and optimize...
PDF
CXOs-Are-you-still-doing-manual-DevOps-in-the-age-of-AI.pdf
PDF
SaaS reusability assessment using machine learning techniques
PDF
CCUS-as-the-Missing-Link-to-Net-Zero_AksCurious.pdf
PPTX
AQUEEL MUSHTAQUE FAKIH COMPUTER CENTER .
PDF
Examining Bias in AI Generated News Content.pdf
PDF
The-2025-Engineering-Revolution-AI-Quality-and-DevOps-Convergence.pdf
PDF
Altius execution marketplace concept.pdf
PDF
Co-training pseudo-labeling for text classification with support vector machi...
PDF
EIS-Webinar-Regulated-Industries-2025-08.pdf
PDF
Data Virtualization in Action: Scaling APIs and Apps with FME
PDF
Connector Corner: Transform Unstructured Documents with Agentic Automation
PDF
NewMind AI Journal Monthly Chronicles - August 2025
PDF
giants, standing on the shoulders of - by Daniel Stenberg
PDF
5-Ways-AI-is-Revolutionizing-Telecom-Quality-Engineering.pdf
PDF
Decision Optimization - From Theory to Practice
PDF
Transform-Your-Supply-Chain-with-AI-Driven-Quality-Engineering.pdf
PDF
Streamline Vulnerability Management From Minimal Images to SBOMs
Early detection and classification of bone marrow changes in lumbar vertebrae...
Human Computer Interaction Miterm Lesson
Lung cancer patients survival prediction using outlier detection and optimize...
CXOs-Are-you-still-doing-manual-DevOps-in-the-age-of-AI.pdf
SaaS reusability assessment using machine learning techniques
CCUS-as-the-Missing-Link-to-Net-Zero_AksCurious.pdf
AQUEEL MUSHTAQUE FAKIH COMPUTER CENTER .
Examining Bias in AI Generated News Content.pdf
The-2025-Engineering-Revolution-AI-Quality-and-DevOps-Convergence.pdf
Altius execution marketplace concept.pdf
Co-training pseudo-labeling for text classification with support vector machi...
EIS-Webinar-Regulated-Industries-2025-08.pdf
Data Virtualization in Action: Scaling APIs and Apps with FME
Connector Corner: Transform Unstructured Documents with Agentic Automation
NewMind AI Journal Monthly Chronicles - August 2025
giants, standing on the shoulders of - by Daniel Stenberg
5-Ways-AI-is-Revolutionizing-Telecom-Quality-Engineering.pdf
Decision Optimization - From Theory to Practice
Transform-Your-Supply-Chain-with-AI-Driven-Quality-Engineering.pdf
Streamline Vulnerability Management From Minimal Images to SBOMs

Scala in-practice-3-years by Patric Fornasier, Springr, presented at Pune Scala Symposium 2014, ThoughtWorks

  • 3. Context Pat Springer Software Engineer Technical Principal 10+ years Academic Publisher Pretty Large Springer Link Strategic 95 % Online Revenue 66 % Total Revenue 9 Mio items 2TB XML Re-built 3 years ago Content Delivery Platform 52 Mio PageViews / Month 99.9% Availability Scala NoSql Co-Sourced Team TW Ex-TW Springer Global CD
  • 5. Timeline Start development Cycling Trip Re-joined Product -> platform Paying back tech debt Today 04/11 04/12 08/13 04/14 Inception 05/12 09/12 Bookfair Release RD Live User migration, enhancements Link Live Smart Books Live Enhancements
  • 6. Looking back: why scala? • Increase productivity • Be more attractive employer • Team decision
  • 7. Looking back: good vs bad Good • Functional programming • Terse syntax • JVM ecosystem • Gentle learning curve • DSL friendly syntax • Motivated team Bad • Tool support • Compilation times • Language complexity #moreRope
  • 9. Fast-forward (Aug 2013) • 2.5 years into project • 1.5 years of weekly live releases • 100k LOC • >10k commits • >90 committers
  • 10. Fast-forward (Aug 2013) • 2.5 years into project • 1.5 years of weekly live releases • 100k LOC • >10k commits • >90 committers not all related to Scala - to be fair • Poor feedback loops • Lots of accidental complexity
  • 13. Trend (2 years) build time LOC • 1:34 min src/main • 6:44 min src/test • 8:18 min total
  • 14. What did we do?
  • 15. What did we do • Reduced build time • Improved feedback loops • Reduced accidental complexity
  • 16. Build time • Reduced size of codebase (broke off vertical slices, pulled out APIs, pulled out libraries, removed unused features, removed low-value tests, etc.) • Reduced usage of certain language features (esp. traits and implicits)
  • 18. Trend (Dec 2013) build time # traits LOC unable to compile on 13” macbook
  • 19. Trend (Dec 2013) build time # traits LOC unable to compile on 13” macbook
  • 20. The problem with traits • Will re-compile on every class the trait is mixed in • Slows down dev-build cycle • Will result in byte code bloat • Will compile *a lot* slower ! For faster compile times: • Use pure traits • Use old-school composition for code re-use • Use pure functions via imports (e.g. import Foo._) • If unavoidable, use inheritance for code re-use
  • 22. Build time • 1:34 min src/main • 6:44 min src/test • 8:18 min total
  • 23. Build time • 1:34 min src/main • 6:44 min src/test • 8:18 min total • 0:24 min src/main • 3:11 min src/test • 3:35 min total
  • 24. Build time (on CI server) • Incremental compilation on CI • Only one dedicated CI agent • Physical build servers • CPUs with higher clock speed
  • 25. Build time (on CI server) • Incremental compilation on CI • Only one dedicated CI agent • Physical build servers • CPUs with higher clock speed
  • 27. Complexity • There’s still a lot of code in our codebase that is hard to read • It seems to be very easy to shoot yourself in the foot with Scala • Scala *is* complex (and that’s why scalac will never be as fast as javac)
  • 28. Complexity • There’s still a lot of code in our codebase that is hard to read • It seems to be very easy to shoot yourself in the foot with Scala • Scala *is* complex (and that’s why scalac will never be as fast as javac) Invariant/covariant/contravariant types (T, +T and -T) Refined types (new Foo {...}) Structural types (x: {def y: Int}) Path dependant types (a.B) Specialized types (@specialized) Self types (this =>) Projection types (A#B) Existential types (M[_]) Type bounds (<:, >:) Type constraints (=:=, <:< and <%<) Type members (type T) Type aliases (type T = Int) Type classes ( (implicit ...) ) View bounds (<%) Higher kinded types (* => *) F-Bounded type polymorphism (M[T <: M[T]]) http://nurkiewicz.github.io/talks/2014/scalar/#/16
  • 29. Not opinionated For example: http://twitter.github.io/effectivescala/ • Many ways to do the same thing • Coding conventions help, but only so much
  • 30. Not opinionated def foo() = "foo" def bar = "bar" ! foo foo() bar bar() // won't compile For example: http://twitter.github.io/effectivescala/ • Many ways to do the same thing • Coding conventions help, but only so much
  • 31. Not opinionated def foo() = "foo" def bar = "bar" ! foo foo() bar bar() // won't compile For example: http://twitter.github.io/effectivescala/ • Many ways to do the same thing • Coding conventions help, but only so much def baz(x: String) = x “x”.charAt(0) “x” charAt(0) // won't compile “x”.charAt 0 // won't compile “x” charAt 0 baz("x") baz “x" // won't compile
  • 32. Not opinionated def foo() = "foo" def bar = "bar" ! foo foo() bar bar() // won't compile list.foreach { x => println(x) } list.foreach ( x => println(x) ) list.foreach { println(_) } list.foreach ( println(_) ) list foreach { x => println(x) } list foreach ( x => println(x) ) list foreach { println(_) } list foreach ( println(_) ) For example: http://twitter.github.io/effectivescala/ • Many ways to do the same thing • Coding conventions help, but only so much def baz(x: String) = x “x”.charAt(0) “x” charAt(0) // won't compile “x”.charAt 0 // won't compile “x” charAt 0 baz("x") baz “x" // won't compile
  • 33. Not opinionated def foo() = "foo" def bar = "bar" ! foo foo() bar bar() // won't compile list.foreach { x => println(x) } list.foreach ( x => println(x) ) list.foreach { println(_) } list.foreach ( println(_) ) list foreach { x => println(x) } list foreach ( x => println(x) ) list foreach { println(_) } list foreach ( println(_) ) if (foo) "x" else "y" foo match { case true => "x" case _ => "y" } For example: http://twitter.github.io/effectivescala/ • Many ways to do the same thing • Coding conventions help, but only so much def baz(x: String) = x “x”.charAt(0) “x” charAt(0) // won't compile “x”.charAt 0 // won't compile “x” charAt 0 baz("x") baz “x" // won't compile
  • 36. Surprises List(1, 2, 3).toSet scala.collection.immutable.Set[Int] = Set(1, 2, 3) http://dan.bodar.com/2013/12/04/wat-scala/
  • 37. Surprises List(1, 2, 3).toSet scala.collection.immutable.Set[Int] = Set(1, 2, 3) List(1, 2, 3).toSet() http://dan.bodar.com/2013/12/04/wat-scala/
  • 38. Surprises List(1, 2, 3).toSet scala.collection.immutable.Set[Int] = Set(1, 2, 3) List(1, 2, 3).toSet() Boolean = false http://dan.bodar.com/2013/12/04/wat-scala/
  • 39. Implicits • Can make it very hard to read code • Tool support is very bad • Impacts compilation time • Surprising behaviour (esp. when used with overloaded methods or optional params)
  • 40. Tooling def handle(response: HttpResponse, request: HttpRequest) • Tool support is still very basic • Makes it hard to continuously refactor (which means people are less likely to do it)
  • 41. Tooling def handle(response: HttpResponse, request: HttpRequest) • Tool support is still very basic • Makes it hard to continuously refactor (which means people are less likely to do it) no luck with “change signature” refactoring support
  • 42. Trait entanglements • Makes it difficult to reason about behaviour
  • 43. Trait entanglements • Makes it difficult to reason about behaviour trait A { def foo = "a" }
  • 44. Trait entanglements • Makes it difficult to reason about behaviour trait A { def foo = "a" } trait B extends A { override def foo = "b" }
  • 45. Trait entanglements • Makes it difficult to reason about behaviour trait A { def foo = "a" } trait B extends A { override def foo = "b" } class C extends A with B new C().foo
  • 46. Trait entanglements • Makes it difficult to reason about behaviour trait A { def foo = "a" } trait B extends A { override def foo = "b" } class C extends A with B new C().foo "b"
  • 47. Trait entanglements • Makes it difficult to reason about behaviour trait A { def foo = "a" } trait B extends A { override def foo = "b" } class C extends A with B new C().foo "b" class D extends B with A new D().foo
  • 48. Trait entanglements • Makes it difficult to reason about behaviour trait A { def foo = "a" } trait B extends A { override def foo = "b" } class C extends A with B new C().foo "b" class D extends B with A new D().foo "b"
  • 49. Trait entanglements (2) ArticlePageSteps WebDriverSupport AuthorStepsCoverImageSteps SummarySection Waiter SectionPageSteps CommonPageSteps WebElementSupport Assertions Uris TripleEquals OnHost TripleEqualsSupport MachineNames
  • 50. Trait entanglements (3) ArticlePageSteps_0 WebDriverSupport_1 AuthorSteps_1 CoverImageSteps_1 SummarySection_1Waiter_1 SectionPageSteps_1 CommonPageSteps_1 CommonPageSteps_2 WebElementSupport_2Assertions_2 WebDriverSupport_2Uris_2 WebElementSupport_3 WebDriverSupport_3Uris_3 TripleEquals_3 OnHost_3 OnHost_4 TripleEqualsSupport_4 MachineNames_4 MachineNames_5
  • 51. Trait entanglements (3) ArticlePageSteps_0 WebDriverSupport_1 AuthorSteps_1 CoverImageSteps_1 SummarySection_1Waiter_1 SectionPageSteps_1 CommonPageSteps_1 CommonPageSteps_2 WebElementSupport_2Assertions_2 WebDriverSupport_2Uris_2 WebElementSupport_3 WebDriverSupport_3Uris_3 TripleEquals_3 OnHost_3 OnHost_4 TripleEqualsSupport_4 MachineNames_4 MachineNames_5
  • 52. Trait entanglements (4) ArticlePageTests_0 ArticlePageSteps_1 AboutSectionSteps_1 SearchResultsPageSteps_1 Uris_1 ArticleTestFixture_1 JavascriptSupport_1 IssuePageSteps_1 CommonAbstractSteps_1 GoogleAnalyticsSteps_1 FakeEntitlementSteps_1 ExportCitationPageSteps_1 FullTextPageSteps_1 OtherActionsSectionSteps_1 WebDriverSupport_2 AuthorSteps_2 CoverImageSteps_2 SummarySection_2Waiter_2 SectionPageSteps_2 CommonPageSteps_2 CommonPageSteps_3 WebElementSupport_3Assertions_3 WebDriverSupport_3Uris_3 WebElementSupport_4 WebDriverSupport_4Uris_4 TripleEquals_4 OnHost_4 OnHost_5 TripleEqualsSupport_5 MachineNames_5 MachineNames_6
  • 53. Trait entanglements (4) ArticlePageTests_0 ArticlePageSteps_1 AboutSectionSteps_1 SearchResultsPageSteps_1 Uris_1 ArticleTestFixture_1 JavascriptSupport_1 IssuePageSteps_1 CommonAbstractSteps_1 GoogleAnalyticsSteps_1 FakeEntitlementSteps_1 ExportCitationPageSteps_1 FullTextPageSteps_1 OtherActionsSectionSteps_1 WebDriverSupport_2 AuthorSteps_2 CoverImageSteps_2 SummarySection_2Waiter_2 SectionPageSteps_2 CommonPageSteps_2 CommonPageSteps_3 WebElementSupport_3Assertions_3 WebDriverSupport_3Uris_3 WebElementSupport_4 WebDriverSupport_4Uris_4 TripleEquals_4 OnHost_4 OnHost_5 TripleEqualsSupport_5 MachineNames_5 MachineNames_6 Imagine many more circle here
  • 55. Today • We’ve delivered successfully using Scala • Don’t think we’re more productive (pure gut feeling, though) • We try to stick to the good parts (conventions, functional programming, pattern matching, etc.) • Complexity, slow compilation and lack of tool support are real problems
  • 56. The future • No urgency to move away from Scala or re-write existing systems • Java 8 is an alternative • Smaller teams and apps will probably lead to more polyglotism (and less Scala)