Archive for October, 2011

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…)

Top-down design in “functional classic” programming

While waiting for my product owner to get back to me, I was going through open browser tabs. I read this from Swizec Teller:

The problem is one of turning a list of values, say, [A, B, C, D] into a list of pairs with itself, like so [[A,B], [A,C], [A,D], [B, C], [B,D], [C,D]].

He had problems coming up with a good solution. “I can do that!” I said, launched a Clojure REPL, and started typing the whole function out. I quickly got bogged down.

This, I think, is a problem with a common functional approach. Even with this kind of problem—the sort of list manipulation that functional programming lives for—there’s a temptation to build a single function bottom up. “I need to create the tails of the sequence,” I thought, “because I know roughly how I’ll use them.”

For me (and let’s not get into all that again), it usually works better to go top down, mainly because it lets me think of discrete, meaningful functions, give them names, and write facts about how they relate to one another. So that’s what I did.

First, what am I trying to do? Not create all the pairs, but only ones in which an element is combined with another element further down the list. Like this:

As I often do when doing list-manipulation problems, I lay things out to visually emphasize the “shape” of the solution. That helps me see more clearly what has to be done to create that solution. There’s one set of pairs, each headed by the first element of the list, then another set, each headed by the second element. That is, I can say the above fact is true provided two other facts are true:

It’s easy to see how I get the heads—just map down the list (maybe I have to worry about the last element, maybe not—I’ll worry about it if it comes up). What are those heads combined with? Just the successive tails of the original list: [2 3], [3]. I’ll assume there’s a function that does that for me. That gives me this entire fact-about-the-world-of-this-program:

Given all that, downward-pairs is easy enough to write:

It’s important to me that I have reached a stable point here. When building up a complicated function from snippets in a REPL, I more often create the wrong snippets than when I define what those snippets need to do via a function that uses them. (I’m not saying that I never backtrack: I might find a subfunction too hard to write, or I may have carved up the world in a way that leads to gross inefficiency, etc. I’m saying that I seem to end up with correct answers faster this way.)

Now I just have to solve two simpler problems. Tails I’ve done before, and here’s a solution I like:

For those who don’t know Clojure well, this produces this sequence of calls to drop:

This does roughly the same work as an iteration would do because of how laziness is implemented.

That leaves me headed-pairs, which is a pretty straightforward map:

This seems like a reasonable solution, doesn’t strike me as being terribly inefficient (given laziness), has a readability that I like, doubtless took me less time than developing it bottom-up would have, and comes with tests (including an end-to-end test that I won’t bother showing).

The whole solution is here.

UPDATE: Yes, I could have used do or even gotten explicit with the sequence-m monad, but that wouldn’t have addressed the original poster’s point, which I took to be how to think about functional problems.

How mocks can cut down on test maintenance

After around 11 months of not working on it, I needed to make a change to Critter4us, an app I wrote for the University of Illinois vet school. The change was simple. When I tried to push it to Heroku, though, I discovered that my Ruby gems were too out of date. So, I ended up upgrading from Ruby 1.8 to 1.9, to Sinatra 1.3 from a Sinatra less than 1.0, to a modern version of Rack, etc. etc. In essence, I replaced all the turtles upon which my code-world was resting. There were some backwards-compatibility problems.

One incompatibility was that I was sending an incorrectly formatted URI to fetch some JSON data. The old version of Rack accepted it, but the new one rejected it. The easy fix was to split what had been a single `timeslice` parameter up into multiple parameters. [Update: I later did something more sensible, but it doesn’t affect the point of this post.] “Crap!”, I thought. “I’m going to have to convert who knows how much test data.” But I was pleased when I looked at the first test and saw this:

The key point here is that neither the format of the URI parameters nor the resulting timeslice object is given in its real form. Instead, they’re represented by strings that basically name their type. (In my Clojure testing framework, Midje, I refer to these things as “metaconstants“.)

The only responsibility this code has toward timeslices is to pass them to another object. That object, the `internalizer`, has the responsibility for understanding formats. The test (and code) change is trivial:

The test is even (and appropriately) less specific than before. It says only that the GET parameters (a hash) will contain some key/value pairs of use to the internalizer. It’s up to the internalizer to know which those are and do the right thing.

The point here is that the size of the test change is in keeping with the size of the code change. It is unaffected by the nature of the change to the data—which is as it should be.

This application is the one where I finally made the important decision to use mocks heavily in the Freeman and Pryce “London” style and—most importantly—to not fall into the trap of thinking “Mocks are stupid!” when I ran into problems. Instead, I said “I’m stupid!” and, working on that assumption, figured out what I was doing wrong.

I made that decision halfway through writing the app. One of the happy results of the mocking that followed was that a vast amount of test setup code devoted to constructing complete data structures went away. No more “fixtures” or “object mothers” or “test factories.”


  • Buy Cheapest buy viagra meds online Now Special Prices For buy viagra meds online! Best Online.
  • Buy Cheap natural alternative to viagra Online Low Prices. Cheap Prescription Drugs.
  • Buy Cheap cheap viagra soft Online Online Prices For cheap viagra soft! Best Prices.
  • Buy Cheap natural alternative to cialis Now Free Viagra Pills! Online Prices For natural alternative to cialis!
  • Buy Cheap cialis prescriptions Now No Prescription Needed For Drugs. Best Prices.
  • Buy Cheap viagra female Now WorldWide Shipping. Cheap Pharmacy Online.
  • Buy Cheap cheap online viagra Online The Largest Internet Pharmacy. Best Online.
  • buy cialis cheap Online Without Prescription Low Prices. Pharmacy Store.
  • Buy Cheapest cialis 30mg Now Best Online. The Largest Internet Pharmacy.
  • cheep daily cialis Online Without Prescription No Prescription Online Pharmacy.
  • Buy Cheap blockers and alpha levitra Now WorldWide Shipping. Discount Online Pharmacy.
  • Buy Cheapest levitra on sale Now WorldWide Shipping. No Prescription Needed.
  • Buy Cheap free sample pack of viagra Now Cheap Pharmacy Online. Online Medical Shop.
  • cialis dosage rate Online Without Prescription Low Prices. Best Drugstore.
  • Buy Cheap levitra sales uk Now All Medications Are Certificated! Best Prices.
  • Buy Cheap soft cialis with mastercard Now Pharmacy Store. Drugs, Health And Beauty.
  • Buy Cheap cialis online Online Best Prices. Online Prices For cialis online!
  • Buy Cheapest levitra and alchol Now Pharmacy Store. Pharmacy At The Best Price!
  • Buy viagra side effect Without Prescription Doctor. Best Internet. Best Prices.
  • Buy Cheapest cialis and levitra viagra online brand Now Low Prices. Internet Prices For cialis and levitra viagra online brand!
  • Buy Cheapest cialis 10 20 mg Online Best Internet. Discount Online Pharmacy.
  • Buy Cheapest levitra for sale Now Cheap Pharmacy Online. WorldWide Shipping.
  • generica cialis Online Without Prescription Best Prices. Best Drugstore.
  • Buy Cheap sildenafil viagra Online Online Medical Shop. 24/Online Pharmacy.
  • Buy Cheap levitra without a prescription Now Cheap Online Pharmacy. Free Viagra Pills!
  • levitra cheapest Online Without Prescription Best Prices. Free Viagra Pills!
  • Buy buy sublingual viagra online Without Prescription Doctor. Low Prices. Best Online.
  • Buy Cheap viagra paypal Now No Prescription Needed. WorldWide Shipping.
  • Buy Cheap viagra propecia propecia xenical xenical celebrex Now Discount Pharmacy Online. Pharmacy Store.
  • Buy Cheap pharmacy viagra Now Online Medical Shop. Cheap Pharmacy Online.
  • Buy Cheapest cialis levitra pharmacy viagra Online Guaranteed Shipping. Best Online.
  • Buy Cheap buy viagra cialis levitra Now Best Online. Top Online Pharmacy Supplier.
  • Buy Cheap mexican generic cialis Now Buy Medications Online. Cheap Pharmacy Online.
  • Buy Cheap who should take cialis 5mg Now Safe And Secure Payment System. Low Prices.
  • Buy Cheapest how viagra works Now 24/Internet)(safe Pharmacy. Best Prices.
  • Buy Cheapest cialis and diazepam overnight delivery possible Online Best Online. Cheap Prescription Drugs.
  • Buy Cheapest viagra levitra cialis apcalis regalis zenegra Now Best Drugstore. Online Medical Shop.
  • Buy Cheapest viagra switzerland Online Best Prices. Cheap Prescription Drugs.
  • Buy Cheapest lowest cialis Now Discount Pharmacy Online. Best Online.
  • Buy Cheap mail order cialis Now Best Online. Order Cheap Meds Without Rx.
  • Buy Cheap buy cheap cialis generic levitra viagra Now Drugs, Health And Beauty. Free Viagra Pills!
  • Buy Cheapest prices cialis 120 Now Low Prices. 100% Satisfaction Guaranteed.
  • Buy Cheap cialis erectile disfunction Now Top Online Pharmacy. 24/Online Pharmacy.
  • Buy Cheap cialis online fda Online Low Prices. Pharmacy At The Best Price!
  • Buy Cheap does levitra allow for good experience Now Buy Medications Online. WorldWide Shipping.
  • Buy Cheap viagra for sex Online Low Prices. Safe And Secure Payment System.
  • Buy Cheapest discount brand viagra by pfizer Now Best Drugstore. Internet Prices For discount brand viagra by pfizer!
  • Buy Cheap buy cheap generic cialis Now Best Prices. All Medications Are Certificated!
  • Buy Cheap buy viagra in england Now Top Online Pharmacy Supplier. Best Prices.
  • Buy Cheapest viagra and cialis cheap Online Best Drugstore. Buy Medications Online.
  • Buy Cheap discount generic viagra Now Low Prices. 100% Satisfaction Guaranteed.
  • Buy Cheapest mail order for viagra tablets Online Best Online. Guaranteed Shipping.
  • Buy Cheapest original cialis Online Top Online Pharmacy. Free Viagra Pills!
  • Buy Cheapest viagra manufacturer Online Best Prices. Drugs, Health And Beauty.
  • Buy Cheapest cialis used for Now Top Online Pharmacy. Free Viagra Pills!
  • Buy Cheapest india generic cialis Now Safe And Secure Payment System. Low Prices.
  • Buy Cheapest cialis buy it online huge discount Online Best Internet. Cheap Pharmacy Online.
  • Buy Cheapest viagra from uk Now Drugs, Health And Beauty. Best Prices.
  • Buy Cheapest risperodol interactions with cialis viagra levitra Now Special Prices For risperodol interactions with cialis viagra levitra! Best Prices.
  • Buy Cheap purchase viagra in australia Now Low Prices. 24/Internet)(safe Pharmacy.
  • Buy Cheapest levitra coupon Online Best Drugstore. Top Online Pharmacy.
  • Buy Cheap cialis cheaply Online WorldWide Shipping. Cheap Pharmacy Online.
  • Buy Cheap what does cialis do Now Order Cheap Meds Without Rx. Best Prices.
  • Buy viagra wholesale Without Prescription Doctor. Best Internet. Low Prices.
  • Buy Cheap what is levitra Now No Prescription Online Pharmacy. Low Prices.
  • Buy Cheap buy cialis online Online Special Prices For buy cialis online! Best Internet.
  • Buy Cheapest cialis softtabs Online Buy Medications Online. Best Online.
  • Buy Cheapest canadian pharmacy levitra Online Pharmacy Store. Free Viagra Pills!
  • Buy Cheap taking half a 20mg cialis Online Guaranteed Shipping. Best Drugstore.
  • Buy Cheapest levitra experiences Online Buy Medications Online. Best Drugstore.
  • Buy Cheap drinking and viagra Online Best Online. Discount Online Pharmacy.
  • Buy Cheap viagra orgasm Online Online Prices For viagra orgasm! Best Drugstore.
  • Buy chinese viagra Online Without Prescription. Best Drugstore. Low Prices.
  • buy canada levitra Online Without Prescription Cheap Meds Without Prescription.
  • Buy Cheapest us pharmacy cialis Now WorldWide Shipping. Cheap Pharmacy Online.
  • Buy Cheap cialis buy on line Online WorldWide Shipping. Online Medical Shop.
  • Buy Cheapest women viagra Now Best Internet. Order Cheap Meds Without Rx.
  • Buy Cheapest viagra cost Now Safe And Secure Payment System. Low Prices.
  • Buy Cheap viagra for sale without a prescription Now 24/Online Pharmacy. Cheap Online Pharmacy.
  • Buy Cheapest viagra sales mexico Online No Prescription Needed. Best Online.
  • Buy Cheapest levitra faq Now Low Prices. Pharmacy At The Best Price!
  • Buy Cheapest cialis us Online Drugs, Health And Beauty. Low Prices.
  • Buy Cheap cialis compare viagra Now Low Prices. Top Online Pharmacy Supplier.
  • Buy Cheapest blood pressure and viagra Now Pharmacy At The Best Price! Low Prices.
  • Buy Cheapest bayer levitra cheapest price online pharmacy Now Best Online. No Prescription Needed.
  • Buy Cheapest pfizer viagra patent Now Best Prices. No Prescription Needed.
  • Buy Cheapest uk cialis supplier Now Low Prices. Pharmacy At The Best Price!
  • Buy Cheap viagra pay by e-check Now Best Prices. 24/Internet)(safe Pharmacy.
  • legal viagra Online Without Prescription Best Prices. Pharmacy Store.
  • Buy Cheap viagra purchase uk Now Guaranteed Shipping. No Prescription Needed.
  • Buy Cheap viagra mail order Online Pharmacy Store. Guaranteed Shipping.
  • Buy Cheap buying viagra online uk Now No Prescription Needed. Cheap Online Pharmacy.
  • Buy Cheap free levitra sample Now Pharmacy At The Best Price! Free Viagra Pills!
  • Buy viagra cheap prescription Online Without Prescription. Best Prices. Best Online.
  • Buy Cheap levitra or viagra Now Cheap Online Pharmacy. Guaranteed Shipping.
  • Buy Cheapest levitra prescription drugs Now Pharmacy Store. Online Prices For levitra prescription drugs!
  • Buy Cheap cialis dosage and uses Now 100% Satisfaction Guaranteed. Low Prices.
  • Buy Cheapest viagra half price pharmacy Online Low Prices. Drugs, Health And Beauty.
  • Buy Cheap viagra levitra Now The Largest Internet Pharmacy. Best Prices.
  • Buy substitute for viagra Without Prescription Doctor. Low Prices. Best Drugstore.