At Belly we make heavy use of Napa for all things API. Napa is our in–house, open source framework that makes it easy to create REST APIs in Ruby, and it forms the backbone of our application services layer.
Why we love Napa:
- Productivity: Being a Ruby framework, Napa bundles Rubyland mainstays like ActiveRecord and RSpec with built–in code generators to quickly get a service up and running. It is easy to configure, and quick to learn for newcomers.
- Predictable: Napa is our de facto standard. We use it across our services layer, so it is easy to jump from one service to another without context switching.
Being built on Ruby, Napa is easy to learn and incredibly productive. Though like other Ruby–based projects, it does inherit some of Ruby’s warts: lackluster performance when parsing large objects or manipulating large data, and arguably more annoying, its reliance on run time exceptions instead of compiler errors for things like type errors, arity mismatches, or unwittingly referencing
nil values instead of objects.
In practical terms these equate to slow response times for service consumers and wasted developer time tracking down pesky bugs.
What if we could take the things we love about Napa and Ruby — speed of development, active community, project predictability and standardization — and supplement them with snappy run time performance and a type system that augments our automated testing to reduce bugs in production?
Under the tutelage of Belly’s Senior Data Engineer Ryan Briones I’ve been working on a hack–time project called Cork to do exactly this. Cork is a framework that exists with the intention of combining everything we at Belly love about Napa and Ruby with the typesafety of Scala and the performance of the JVM to make creating correct, performant REST APIs productive and predictable.
My hope is that Cork will match Napa for convenience and productivity in developing REST APIs. To this end, Cork provides conveniences that mirror Napa’s: a REST API code generator, high–level DB abstraction for both queries and schema migrations, a built–in testing framework, and sensible configuration out of the box. It should also mimic Napa’s uncluttered and easy–to–approach nature by focusing on the task at hand: building RESTful JSON APIs with a minimum of fuss.
Of course, Scala differs from Ruby, otherwise there would be little point in using it. The most notable feature not present in Ruby is Scala’s static type system that places emphasis on immutable values, making it easier to reason about (or even help to do away with) program state.
Type systems like Scala’s help prevent entire classes of errors at compile time that often manage to sneak their way past unit tests and into production in Ruby. A few examples are:
NoMethodErrorwhen a method call happens on a wrong object or a
nil.last) that you the programmer believed would be the correct object.
ArgumentErrorwhen a method calls another with the wrong numbers of arguments.
- A general inability to reason or know about glaring logical errors until they raise exceptions or cause erroneous behavior, like methods that unpredictably return different types depending on their arguments, or control flow branches that are unreachable due to syntactically correct errors in logic.
These kinds of productivity enhancements must come at an enormous cost, right? I’m not so sure. My experience with Scala so far has convinced me that it is not hard for Rubyists — even beginning/junior programmers like me — to pick up the language and quickly be productive.
Scala resembles Ruby in a number of ways: the class–based “everything is an object” model that we already know, the feeling that “there’s a library for that”, the expressive syntax and functional idioms, the try–it–in–the–REPL–and–see pattern, and the relentless focus on getting out of the developer’s way.
Ruby developers will spy language features we already know and love like
filter, and the idea of passing functions as values to other functions (like we do all the time with blocks and procs).
These reasons (among others) have convinced me that Scala is a great language in which to attempt to emulate Napa’s best qualities.
Is Cork ready for prime time?
No. I have only been working on Cork for a few weeks, so it is missing crucial features like tests for correctness of the generated code, solid documentation, logging, and easy deployment.
It is definitely pre–alpha software, but large parts of the project are functional today. Basics like one–step API generation, routing, async responses by default, schema migrations and database persistence are all usable.
You can check Cork out here, and a few preliminary benchmarks against a Napa service (for fun) here. A word of warning: the project is under heavy development, and breaking changes are guaranteed to occur frequently for the forseeable future.
Reach out, let’s chat. I would love to connect with you.