six years of scala and counting
TRANSCRIPT
7 years of Scalaand countingScala Days Vienna 2017
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
6 years of Scalaand countingScala Vienna User Group May 2016
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Agenda1. Quick introduction to Scala
2. Learning Scala
3. Using Scala
4. Learnings, reflection, observations, impressions
5. Questions
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Manuel Bernhardt
• I help companies getting started with using reactive applications in their distributed systems infrastructure
• http://manuel.bernhardt.io
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Manuel Bernhardt
• I help companies getting started with using reactive applications in their distributed systems infrastructure
• http://manuel.bernhardt.io
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Scala: an introduction
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Scala introduction
• first version released in 2003
• Martin Oderksy, EPFL
• an estimated more than half a million Scala developers 1
1 http://www.scala-lang.org/blog/2016/03/14/announcing-the-scala-center.html
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Scala Center
• non-for-profit foundation for Scala education and community guidance
• established at EPFL
• founding members: IBM, verizon, Goldman Sachs, nitro, Lightbend
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Favourite Feature tour
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
case classespublic class User {
private final String name; private final String surname; private final Integer age;
public User(String name, String surname, Integer age) { this.name = name; this.surname = surname; this.age = age; }
public String getName() { return this.name; }
public String getSurname() { return this.surname; }
public String getAge() { return this.age; }
@Override public int hashCode() { // ... }
@Override public boolean equals(Object that) { // ... }}
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
case classescase class User(name: String, surname: String, age: Int)
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
case classescase class User(name: String, surname: String, age: Int)
val bob = User("Bob", "Marley", 42)
val namedBob = User(name = "Bob", surname = "Marley", age = 22)
val john = bob.copy(name = "John")
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
case class• perfect example of the terseness Scala provides
• hashcode, equals, toString for free
• serializable by default
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
type inferenceval foo = "Bar" // foo: String = Bar
val answer = 42 // answer: Int = 42
val price = 9.99 // price: Double = 9.99
val nums = List(1, 2, 3) // nums: List[Int] = List(1, 2, 3)
val map = Map("abc" -> List(1, 2, 3))// map: scala.collection.immutable.Map[String,List[Int]] = Map(abc -> List(1, 2, 3))
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
functions and higher-order functionsdef isMajor(user: User): Boolean = user.age > 18
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
functions and higher-order functionsdef isMajor(user: User): Boolean = user.age > 18
class UserGroup { def filter(predicate: User ⇒ Boolean): List[User] = ...}
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
functions and higher-order functionsdef isMajor(user: User): Boolean = user.age > 18
class UserGroup { def filter(predicate: User ⇒ Boolean): List[User] = ...}
userGroup.filter(isMajor) // returns only majors
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Learning Scala
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
How "learnable" is Scala?
• Shadaj Laddad
• http://shadaj.me
• learned Scala at age 11-12
• talks at Scala Days, OSCON since 2012
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
How "learnable" is Scala?
• Coursera courses, 400.000+ participants - highest completation rate in the industry (10%, which is high for a MOOC 2)
• Scala as beginner programming language at Lund University of Technology 3
3 https://www.lth.se/english/about-lth/news/news/article/scala-will-be-the-beginner-programming-language-of/
2 Massive Open Online Course
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
My learning path
• 2010: started dabbling with Scala (books, using it in tests, small projects)
• 2011: discovering Functional Programming through Javascript. Using Play Framework 1 with the Scala module in my 2nd startup
• 2012: first large codebase to migration from Play 1 to Play 2.0.0 (based entirely on Scala)
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
My learning path• 2013: several client projects using Scala
• 2014-2016: architecture, prototyping, design, implementation, review of various production systems with Scala, Akka, Play Framework; writing Reactive Web Applications
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
My learning path• estimated 6 months to "click"
• imperative ⇒ declarative
• mutable, global state ⇒ immutable, expression-oriented
• longer to grasp or use more advanced concepts
• and how not to shoot myself in the foot with them
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Your learning path?• new Coursera courses by the Scala Center
• https://scala.epfl.ch
• try to use Scala for something "real"
• and even if it is just tests in a real project
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Using ScalaScala Vienna May 2016 - manuel.bernhardt.io - @elmanu
6 years without one of those pesky NullPointerException-s
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Significantly less problems at runtime
• Scala compiler spots a whole plethora of problems at compile-time
• leveraged by e.g. Play Framework, high emphasis on "compiling everything"
• URLs
• Javascript (Google Clojure Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Less code yieldshigher maintainbility
(Less is more)
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
IDE / Editors• IntelliJ IDEA
• Scala IDE for Eclipse
• ENSIME 5
• emacs, Atom, Sublime Text, vim
5 Enhanced Scala and java Interaction Mode for text Editors
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Compiler• slower than the Java compiler
• but not a problem (anymore) on modern hardware
• especially with incremental compilation
• unless you deep dive into type-level and generic programming (e.g. shapeless library)
• much more precise than the Java compiler (type-safe ++)
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Jobs & Developers
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
http://appliedscala.com/blog/2016/scala-popularity/Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
What I've learnedReflection, Impressions, (Advice)
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
The Dreyfus model of skill acquisition
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Learning #1Spend a little time understanding
the language design
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Understand Scala's essenceand your life will be easier
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Learning #2Understand the purpose of the
language features
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Scala has quite a few language featuresbecause it was designed to be extensible
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Don't be that kid
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Scala language levels 4
• Level A1: Beginning application programmer
• Level A2: Intermediate application programmer
• Level A3: Expert application programmer
4 http://www.scala-lang.org/old/node/8610
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Scala language levels 4
• Level L1: Junior library designer
• Level L2: Senior library designer
• Level L3: Expert library designer
4 http://www.scala-lang.org/old/node/8610
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
The features you need to build
applicationsare not the sameas the ones you need to build
librariesScala Vienna May 2016 - manuel.bernhardt.io - @elmanu
SIP 18: Modularizing language featuresimport scala.language.implicitConversionsimport scala.language.dynamicsimport scala.language.postfixOpsimport scala.language.reflectiveCallsimport scala.language.higherKindsimport scala.language.existentialsimport scala.language.macros
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Incidental complexityIs this really a problemspecific to Scala?Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
@SuppressWarnings({"unchecked", "rawtypes"})@Deprecated@OneToMany(@HowManyDBADoYouNeedToChangeALightBulb)@OneToManyMore @AnyOne @AnyBody@YouDoNotTalkAboutOneToMany // Fightclub, LOL@TweakThisWithThat( tweak = { @TweakID(name = "id", preferredValue = 1839), @TweakID(name = "test", preferredValue = 839), @TweakID(name = "test.old", preferredValue = 34), }, inCaseOf = { @ConditionalXMLFiltering(run = 5), })@ManyToMany @Many @AnnotationsTotallyRock @DeclarativeProgrammingRules @NoMoreExplicitAlgorithms@Fetch @FetchMany @FetchWithDiscriminator(name = "no_name")@SeveralAndThenNothing @MaybeThisDoesSomething@JoinTable(joinColumns = { @JoinColumn(name = "customer_id", referencedColumnName = "id")})@DoesThisEvenMeanAnything @DoesAnyoneEvenReadThis@PrefetchJoinWithDiscriminator @JustTrollingYouKnow @LOL@IfJoiningAvoidHashJoins @ButUseHashJoinsWhenMoreThan(records = 1000)@XmlDataTransformable @SpringPrefechAdapterprivate Collection employees; // http://annotatiomania.com
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Learning #3Don't forget all about Object
Oriented Programming
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
class SynchronizationService {
private[services] def synchronizeTeeTimes( suite: Suite, dataType: SuiteDataType, eventuallyByteStream: Future[Enumerator[Array[Byte]]], removeDocsWithOlderTimestamps: Boolean): Future[Int] = ...
private[services] def synchronizeTournaments( suite: Suite, dataType: SuiteDataType, eventuallyByteStream: Future[Enumerator[Array[Byte]]], removeDocsWithOlderTimestamps: Boolean): Future[Int] = ...
}
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
class SynchronizationService {
private def synchronizeGolf[T, S](suite: Suite, dataType: SuiteDataType, eventuallyByteStream: Future[Enumerator[Array[Byte]]], toIndexDocuments: (Suite, Issuer, GolfClub) => Seq[T] => Iterable[S], // function! indexDocuments: Iterable[S] => Future[Boolean], // function! countDocuments: CountRequest => Future[Long], // function! verify: (Int, Long) => Unit, // function! removeDocsWithOlderTimestamps: Boolean)(implicit format: Format[T]): Future[Int] = ...
}
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Learning #4Don't use every feature as a
hammer
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
for comprehensionval bobUser: Option[User] = ...val carlUser: Option[User] = ...
val bobCarlAge: Option[Int] = for { bob <- bobUser carl <- carlUser } yield bob.age + carl.age
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
for comprehension from hellfor { stopWatch <- Future.successful(startedStopWatch) startTimestampOfSync = DateTime.now() byteStream <- eventuallyByteStream suiteDocStream = toDocumentStream[T](byteStream) chunkedStream = suiteDocStream &> ExtraEnumeratees.chunker(ChunkSize) indexerSuccessStream = chunkedStream &> indexer indexerSuccess <- indexerSuccessStream.run(Iteratee.fold(true)(_ && _)) _ <- if (removedDocsWithOlderTimestamps) waitForElasticSearchToFinishIndexing().map(_ => removeDocsUpsertedBefore(issuer, dataType, startTimestampOfSync)) else Future.successful(()) count <- waitForElasticSearchToFinishIndexing().flatMap { _ => verifyCount(issuer, counter.get(), countDocuments, verify) }} yield { if (!indexerSuccess) error(s"Failed to index $dataType for ${suite.url}") val duration = scala.concurrent.duration.Duration(stopWatch.getNanoTime, TimeUnit.NANOSECONDS).toSeconds info(s"Done synchronizing ${counter.get()} $dataType for ${suite.url}, it took $duration s") count}
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Learning #5Transitioning to Scala
(for teams)
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Don't start a Scala projectwith a team comprised
of novice and advanced beginners
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Don't start a <XYZ> projectwith a team comprised
of novice and advanced beginners
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
It's all about peopleThe biggest challenges of transitioning to Scala — or anything new — are rarely technical. Talented programmers can learn a new syntax, new concepts, and a new IDE. Rather, change often brings out the weaknesses in other areas like process and culture. 6— Kevin Webber
6 https://medium.com/@kvnwbbr/transitioning-to-scala-d1818f25b2b7#.x1tcfcs58
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Building up Scala knowledge in your team• culture that emphasizes learning, create time for learning
• code reviews, discussions
• try to get one "Competent" on your team
• even if it's a "hired gun" helping to bootstrap & ensure best practices (& avoiding pitfalls)
• invest in training (Fast track to Scala, etc.)Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Conclusion
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Conclusioncase class User(name: String, surname: String, age: Int)
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Conclusioncase class User(name: String, surname: String, age: Int)
embrace Scala's terseness
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Conclusioncase class User(name: String, surname: String, age: Int)
embrace Scala's terseness
don't forget about the language levels
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu
Thank you!Questions & Comments ?
• http://manuel.bernhardt.io
• @elmanu
Scala Vienna May 2016 - manuel.bernhardt.io - @elmanu