3. Introduction
• A short essay that provides a set of best
practices
• Libraries from Twitter - Finagle, Ostrich,
Util, Gizzard, Scalding and more...
• Program in Scala, you’re not writing Java,
nor Haskell, nor Python
• Assumes the reader is familiar with Scala
4. Formatting 1
• Consistent application of the same
formatting rules will enhance readability
• Particular importance to Scala because its
grammar has a high degree of overwrap
• Scala Style Guide and some additional rules
5. Formatting 2
• Indent: 2spaces, Straight-line length: 100
• External APIs should have longer and
explanatory names
• Use val (= don’t rebind names)
• Avoid using ` to overload reserved names
• Active names for ops with side effects
6. Formatting 3
• Getters without `get` prefix
• Don’t repeat names that are already
encapsulated - e.g. User.getUser(123)
• Wildcard import for more than 6 names
• Don’t use relative imports
• Put imports at the top (in one place)
7. Formatting 4
• Avoid using braces for simple expressions
• Use PartialFunction if possible
• Comments to explain the behavior of your
code are bad sign
• Prefer “Obviously it works” to “it works,
obviously” and restructure so
8. Types and Generics 1
• Fascinating but avoid type level
programming in production code
• Use explicit return type annotations for
public methods
• Immutable collections should be covariant
• Mutable collections should be invariant
9. Types and Generics 2
• Use type alias for convenient naming or
clarify purpose
• Don’t subclassing when an alias will do
• Using implicits sparingly
• Ask yourself if there is a way to achieve the
same thing without implicits
• “Pimp my library” pattern - e.g. RichInt
10. Collections 1
• Should read “collections design document”
• Prefer using immutable collections
• Use “mutable” namespace explicitly
• Receive the most generic collection type
appropriate in methods/constructors
(Iterable, Seq, Set, Map ...)
11. Collections 2
• Pipelining transformations leads to very
succinct solutions but can also be confusing
to the reader
• “val votesByLang = votes groupBy { case
(lang, _) => lang }” instead of just
“groupBy(_._1) “
• If you worry about namespace pollution,
group expressions with {}
12. Collections 3
• Read “Performance Characterisitics”
• Use profiler (e.g.YourKit Java Profiler)
• Use arrays instead of lists for large
sequences
• Use buffers when performance matters
• Not JavaConversions but JavaConverters
13. Concurrency
• Use Futures to manage concurrency
• Futures are declarative, composable and
have principled handling of failures
• Prefer Future combinators
(com.twitter.util.Future.join/collect)
• Reach for a concurrent collection after
trying with a synchronized collection
14. Control structures 1
• Declarative style, more expression-oriented
• Recursion makes your programs simple
• Starts with a well-defined clean slate, no
reference cells and invariants abound
• Check the tail call optimization application
by the @tailrec annotation
15. Control structures 2
• Use returns to cut down branching and
establish invariants
• Avoid using returns as you would do in
imperative languages
• Avoid using returns inside of a closure
because of hidden costs
16. Control structures 3
• for-comprehensions provides succinct and
natural expressions
• Demerit: hidden costs to allocate and
dispatch closures and unexpected
semantics
• require/assert are useful when the type
system cannot express the required
invariants
17. Functional programming 1
• Value oriented programming (emphasizes
the transformation of values over stateful
mutation)
• Referentially transparent, stronger invaliants
• case classes as ADT(Algebraic Data Type)s
18. Functional programming 2
• Option type is a container which provides a
safe alternative to the use of null
• Use “opt foreach { v => }” or pattern
matching or getOrElse instead of
“if(opt.isDefined) opt.get”
• Use Option(v) instead of Some(v)
19. Functional programming 3
• Might be more composability with a
PartialFunction than returning an Option
• Destructuring bindings are particularly
useful for tuples and case classes
• Lazy fields compute and memorizes a result
• Should make the cost model explicit and
precisely control side-effects
20. Functional programming 4
• Use call-by-name only to construct natural
DSLs (control constructs)
• Use call-by-name only in the last position of
the last argument list
• Use explicit functions for multiple times
execution or side-effecting
21. Object oriented programming 1
• Dependency Injection by typically defining
trait and subclassing
• Injecting factories by using simple functions
• Keep traits short and orthogonal - e.g.
Reader/Writer instead of IOer
22. Object oriented programming 2
• private[this] can aid performance
optimizations
• Constrain visibility of singleton class types -
e.g. def foo(): Foo = new Foo with Bar {}
• Don’t use structural types in normal use
23. Garbage collection
• Functional Scala code tends to generate
more short-lived garbage than Java
• Don’t act without data, use profiling tools -
e.g. heapster, gcprof
24. Java compatibility
• Sometimes your Scala code is not directly
usable from Java (traits that contain
implementation, collections, functions...)
• Sometimes need to separate Java APIs
• Write unit tests in Java
25. Twitter’s standard libraries 1
• Util: an extension to the Scala and Java
standard libraries
• Finagle: RPC system - the kernel distributed
systems components
26. Twitter’s standard libraries 2
• Future - a simple container(a type of
collection) which hold the promise for the
result of a computation which is not yet
complete
• 3 states: pending, failed or completed
• Future#flatMap is useful to define
composite operations
27. Twitter’s standard libraries 3
• Use callbacks(onSuccess) instead of foreach
• Future.value(), exception() creates pre-
satisfied Futures
• Future.collect(), join() provide combinators
that turn futures into one
• Future#cancel from consumers is
propagated to its producer