One of the interesting things about Scala is how well it composes. This is the primary "Scalable" in Scalable Language. I'm writing this up to share my experience and track my progression in a partially contrived but interesting example.
So I'm playing around with Plivo, which is a telecoms IaaS web service (similar to Twilio), and the Play! Framework. It uses a RESTful API, and we want to make sure the API callbacks are authentic. HMAC as usual.
This is your brain on Functional Programming
Scala makes it very easy to break up your problems into functions. Rather than loops with counters, mutable variables, and such, Scala encourages (but doesn't mandate) a functional style with immutable variables, first class functions, nested functions, etc. It generally leads to code that is both more concise and contains less bugs.
Nested functions
Play! provides an HMAC implementation (play.api.libs.Crypto.sign), but it converts the signature into a Hex ASCII string. Plivo Base64 encodes the HMAC byte (non-ASCII) signature. We have a few options to get the keys into equivalent formats. I chose to make some nested helper functions and encode my signature in their format. Since the functions are unlikely to be used elsewhere, the nesting keeps the namespace clean and locally reenforces that we have a specific format.
for comprehension (syntactic sugar around map)
One of the interesting things here is the use of Scala's for comprehension as a control structure, a technique I learned on the Play! mailing list. In the body, we have two variables that return Option type. If both are defined, the yield block fires with the params defined directly. Otherwise, the getOrElse block fires and handles errors.
List fun[ctions]
Play! returns the url-encoded POST data as a Map[String, Seq[String]] (because forms keys can have multiple values, i.e. check boxes). Plivo's signature is based on the full URL of the callback, and all the POST parameters, sorted by key, concatenated together.
I convert the parameter Map into a List[String, Seq[String]] (List of Tuples) because Maps don't have a sort operation. We'll soon be flattening it anyway, so the List is a pretty good structure (aside.. another approach superior in more general circumstances would be to convert the Map to a TreeMap which is always sorted)
The _ is an interesting character in Scala and is used in a few different ways. Programming in Scala calls it, in passing, "filling in the blank" which generally holds true. Ultimately, we are "filling in" the sortBy with the key of our List. Finally, we flatten the list, providing a flatten with a means of combining the key and the Seq of values. mkString works perfectly here since it just concatenates everything. x => indicates x as a placeholder for each of the List items and is analogous to _, which won't work here since we need to reference it twice.
OO Design tradeoffs
So I'm using Action Composition to take a Request, validate the HMAC key, and first class functions to pass on Response responsibility or otherwise respond with BadRequest if there is a problem with the signature or params.
A more Java-influenced design might throw Exceptions on error and in the delegated chain of command. This has the benefit of being more abstract.. if this function isn't called in response to an HTTP request, the invoking Exception handler could do something other than responding BadRequest as we do here. The cool thing about Scala is that I could just as well do that, but I make a more opinionated choice since I know how my class will be used in all cases.
Scala keeps OO, but turns the use on it's head and makes it always possible to ask: "gee, does this REALLY need to be abstracted?" More often than not, a more elegant and concise answer is to reach in the functional bag of tricks.
Comments
comments powered by Disqus