By Michael Woloszynowicz

By Michael Woloszynowicz

Thursday, December 8, 2011

A Month With Scala

Although I’ve played around with Scala for the few months, these efforts largely involved simple scripts and casual reading. It wasn’t until last month that the opportunity to use Scala in a large scale project finally arose and I dove right in. The project was a typical REST based web service built on top of Amazon’s Elastic Beanstalk, SimpleDB, S3 and Redis*.

First off let’s talk about why I chose Scala in the first place. After spending a good deal of my last year entrenched in JavaScript and appreciating its functional nature, brevity and flexibility, writing Java code became a tremendous chore for me. At the same time, our developers have grown accustomed to, and appreciative of the wide array of quality frameworks and tools available for Java, so a drastic departure was out of the question. This left us with two viable options: Clojure, and Scala. Ultimately I decided on Scala as it provided an easier transition, was more mature, had greater community support, better interoperability with existing Java code, and a nicer syntax. That being said, the last month hasn’t been as painless as I expected and Scala’s use in a real project is a far cry from its use as a scripting language.

The Good

Functional
Simply put, this is the main reason for my departure from Java. I fell in love with having Functions as first class members in JavaScript and it pained me to work without them in Java. Coupled with other functional niceties like currying, partially applied functions, etc. it improves code re-use and drastically accelerates development. Although I’ve seen several people grumble that Scala isn’t a purely functional language as it contains a good deal of Object Oriented features, I see this as a strong point. It provides OO programmers with an easier transition and allows them to strike a balance between the two styles. That being said, if Scala is to be adopted across the whole team, it’s best to decide on a coding style and enforce some best practices as Scala’s laxity can lead to greatly differing code styles.

Lists and Iteration
Scala’s lists and maps are completely different from those provided by Java which is both good and bad (more on the bad later). For starters, in true functional fashion, they are immutable by default but mutable variants are available. Their strength comes from the broad array of iteration and filtration functions that make manipulation a joy. These include the usual suspects such as map, filter, foreach, etc which accept a predicate or translation function to produce a new List. Some examples of iterating lists include:

val cars = List("honda", "audi", "bmw")
//Upper case each entry (using _ notation)
val uppers = cars.map(_.toUpperCase) 
//New list for names less than 5 chars
val shorts = cars.filter(A => A.length < 5)
//Create a list by joining two lists 1..4 and 6..9
val nums = List.range(1,5) ::: List.range(6, 10)
//Make comma separated string "1,2,3,4,6,7,8,9"
val numsStr = nums.mkString(",")
var sum = 0 //Get a sum of all the values
nums.foreach(sum+=_)

Syntax
Compared to Java, Scala code is easier to digest but it’s certainly no Python. The language lacks the intuitiveness that Python brings and only becomes fully readable once a good degree of familiarity has been gained. That being said, I now prefer to read and debug it over Java any day. Scala does away with excessive return statements, semi-colons, and allows for much more natural and expressive function naming and invocation.

Sort-of Statically Typed
Although we can debate the merits of dynamic vs. statically typed languages for hours, I think Scala has struck a good balance with its use of type inference. Dynamic typing in JavaScript is often a blessing and a curse so Scala’s promise of brevity and type checking is appealing and well implemented.

Concise Methods and Classes
As time passes, the “v” in Java begins to stand more and more for verbose. From lengthy boilerplate to duplicate statements in object declarations, Java is hardly a model for brevity. Scala on the other hand does an excellent job of this in many regards. Its functional nature has a lot to do with, as do the syntactic enhancements. Additionally, Scala helps by automatically building accessor methods for private class variables, as well as declaring those variables and the object’s constructor all on one line. Other features such as Traits and pattern matching provide further brevity. Traits allow you to mix additional functionality into an object regardless of its hierarchy. For example, Scala provides an Ordered Trait, that when mixed into an object that implements a compare method, will provide functions for object comparison operations such as “>, <, >=, <=”. The best thing about Traits is that they can be mixed in at the point of instantiation as well as declaration which allows you to build full featured objects on the fly. Pattern matching is the Swiss Army knife of Scala. Despite its somewhat deceptive name, pattern matching goes beyond the functionality of a simple “if” statement as shown in the below examples.

val cars = List("audi", "honda", "bmw")
cars match {
  case List("audi", x, _*) => println("second is: "+x)
  case first :: rest => println("first is: "+first)
  case _ => println("something else")
}
//A general size function
def getSize(a: Any) = a match {
  case s: String => s.length
  case l: List[_] => l.length
  case m: Map[_,_] => m.size()
}

The Bad

Not a Beginners Language
By most measures, Scala is not a simple language to learn. While there are lots of languages that are large in scope and features, most can be learned over time. Scala fall short by requiring you to learn at least 75% before you can do anything meaningful. When I first started out with some basic scripting this didn’t appear to be the case, however; once I tackled a real project, I realized how limited my knowledge really was. For those that think you’ll coast by because you’re a Java expert, think again. My Java knowledge is extensive and the parallels between the language are few and far between.

Java and Scala
One of the major draws to Scala was that it interoperates with Java code, so years of utility functions and helper classes would not go to waste. While it’s simple in theory, it’s not the case in practice. Several Scala objects are cumbersome to use in Java as Scala has had to perform ugly syntactic transformations on itself to work with the JVM, resulting in some rather ugly Java code. Furthermore, Scala collections are largely incompatible with Java, so a good deal of conversion has to be done (Scala does provide utilities for this). Finally, the greatest frustrations occur at compile time when Java and Scala sources don’t always play well. Because Java and Scala compile independently, the order of compilation can matter when one languages references another, or worse, they both reference each other. While the Scala compiler invoked through a builder like Maven, or the command line provides workarounds for this, IDE’s such as Eclipse and NetBeans don’t fare as well. Although the Eclipse Scala plugin is supposed to support Joint Compilation out of the box, this has not been my experience thus far. As long as your not married to Eclipse, I’ve heard IntelliJ and Buildr are the best IDE’s for Scala development so you may want to opt for one those if going the Scala route. If you do choose to use Eclipse, be sure to discard the slow default Scala build manager and opt for the new SBT project builder which offers far better performance. If at all possible, I would also recommend constraining your Java and Scala to uni-directional calls as this keeps the code cleaner and reduces compilation issues. In my case, I use Java for Servlets and REST via Jersey with the service and data access layers provided by Scala. This way Scala never has to call Java.

Frameworks and Toolkits
Although the number of good quality toolkits for Scala is growing, Lift and ScalaTest being two of them, it still pales in comparison to what is offered through Java. RESTEasy is not nearly as nice to work with as Jersey, and Scalaxb doesn’t perform JSON marshaling and unmarshaling like JaxB does. The limitation of Scalaxb has forced me to use JaxB over my Scala objects, which works fairly well, with the exception of Lists. Scala’s native Lists don’t convert properly during serialization so the solution is to use a Scala Buffer and write a transformation function which converts them to Java lists for writing, and back to a Buffer after reading. This isn’t a huge pain but it's an inconvenience nonetheless.

Versioning
The real Achilles Heel for Scala is its compiled version fragility whereby third party tools and frameworks have to be versioned to a specific Scala compiler version. This is simply a function of Scala's continual and rapid evolution, so shy of extending release cycles I'm not sure how much can be done about it. The issue has been well detailed on the Lift blog so I won’t elaborate on it too much, other than to say that it’s real and it is a pain.

So Should You Use It?
Despite its shortcomings Scala is an expressive and enjoyable language to write in. It eliminates a lot of the pain points that Java Suffers from and provides a good deal of added functionality that will accelerate your development efforts. For those currently writing in Java, I encourage you to learn Scala as it will make for more enjoyable programming and make you a better developer overall. For others, if your already using a good language like Python then Scala is a tougher sell although still recommended. In the end, it’s a good language with a lot of great third party tools provided by Java. If you do decide to take the plunge, Programming in Scala by Martin Odersky (Scala’s creator) is a good introduction to the language.

* As a side note, if working with Redis in Scala, the scala-redis package works like a charm. 

If you liked this post please follow me on Twitter  and upvote it on Hacker News

No comments:

Post a Comment