Using functional style in a Ruby webapp
Motivation
Consider a Ruby backend that communicates with its frontend via JSON. It sends (and perhaps receives) strings like this:
Let’s suppose it also communicates with a relational database. A simple translation of query results into Ruby looks like this:
(I’m using the Sequel gem to talk to Postgres.)
On the face of it, it seems odd for our code to receive dumb hashes and arrays, laboriously turn them into model objects with rich behavior, fling some messages at them to transform their state, and then convert the resulting object graph back into dumb hashes and arrays. There are strong historical reasons for that choice—see Fowler’s Patterns of Enterprise Application Architecture—but I’m starting to wonder if it’s as clear a default choice as it used to be. Perhaps a functional approach could work well:
-
Functional programs focus on the flow of data through code, rather than on objects with changing state. The former seems more of a match for a typical webapp.
-
It’s common in functional languages to lean toward a few core datatypes—like hashes and arrays—that are operated on by a wealth of functions. We could skip the conversion step into objects. Rather than having to deal with the leaky abstraction of an object-relational mapping layer, we’d embrace the nature of our data.
Seems plausible, I’ve been thinking. However, I’ve never been wildly good at understanding the problems of an approach just by thinking about it. It’s more efficient for me to learn by doing. So I’ve decided to strangle an application whose communication with its database is, um, labored.
I’m going to concentrate on two things:
-
Structuring the code. More than a year of work on Midje has left me still unhappy about the organization of its code, despite my using Kevin Lawrence’s guideline: if you have trouble finding a piece of code, move it to where you first looked. I have some hope that Ruby’s structuring tools (classes, modules,
include
, etc.) will be useful. -
Dependencies. As you’ll see, I’ll be writing code with a lot of temporal coupling. Is that and other kinds of coupling dooming me to a deeply intertwingled mess that I can’t change safely or quickly?
This blog post is about where I stand so far, after adding just one new feature.
(more…)