keenlabs/KeenClient-Scala — pull request #20 by ches (2014-12-13 12:04:54+00:00)
Title: Access levels - making missing keys a compile-time error

I actually started out with working to add [Typesafe Config] for config file support. It's already a transient dependency by way of Akka, and can use environment variables, so it will drop in quite smoothly.

But I started running into conundrums with the way the keys were handled, so this turned into something else first. I still have some WIP adding the config file support on top of this, but this seemed like a significant enough set of changes already that I should start discussion to see if there are any concerns.

So here's the story of this PR:

Throwing exceptions is not idiomatic in Scala land. `Try` is better, but if we wrapped every API call in a `Try` because of the possibility of a missing API key, then we’d be giving callers an awkward `Try[Future[Response]]` to unpack for every method, which is not much less onerous than forcing them to handle with `try/catch`.

This factors client functionality into a separate trait for every access level (read, write, master). You must mix one of these traits into a `Client` instance in order to be able to make calls requiring that level of access, and each level’s trait defines its key field as abstract so that failing to provide it *errors at compile time*. No more runtime checks.

If you want to read and write, for example, you initialize a client like this:

```scala
val keen = Client.new("projectID") with Reader with Writer {
val readKey = "myReadKey"
val writeKey = "myWriteKey"
}
```

As a next step, we'll have the keys default to values from a config file so that this will become simpler:

```scala
val keen = Client.new("projectID") with Reader with Writer
```

The `Master` trait allows reading, writing, and master operations with only one mixin and key configuration value required, which of course should be discouraged when master isn't needed, but it reflects semantically how the API handles master authorization.

This needs documentation updates and new unit tests, but since it's still an incremental step with a config file coming next, I wanted to see how well that works out before fully updating everything.

[Typesafe Config]: https://github.com/typesafehub/config