Ruby on Rails
Ta-da List


October 24, 7:12 | Comments (77)

Discourage the improper with syntactic vinegar

Syntactic sugar has long hogged the spotlight in discussions of framework and language design. It holds the power to turn idioms into conventions, to promote a common style through beauty, brevity, and ease of use. We all love syntactic sugar — and we want it all: the terrifying lows, the dizzying highs, the creamy middles. It's what makes languages such as Ruby taste ever so sweet in comparison to the plain alternatives.

But sugar is not all we need. Good design lies not only in emphasizing the proper, but de-emphasizing the improper too. Just as we can sprinkle syntactic sugar across a certain style or approach to promote its use, we can add syntactic vinegar to discourage it as well. It's more sparingly used, but that makes it no less important.

Allow me to demonstrate. Earlier today, I finally got around to giving the FormTagHelper#form_tag method in Rails a delicious lick of block-inducing magic. In The Old Days ("TOD" defined as time before the feature), we used to do something like this:

<%= start_form_tag :action => "create" %> My pretty form! <%= end_form_tag %>

Yes, as a block-loving programmer of Ruby stature, the mere sight of such a pre-historic notion of manually controlling start and end points in a coherent unit of execution seems almost... revolting. What's next? Starting and stopping your transactions by hand? Manually dealing with exception rollbacks?

No, no. Of course not. This start/end transgression is merely a relic from a time of lesser Ruby foo (mine in particular). We've long since uncovered the technology to deal with the intricate mix of ERb templates, blocks, and that pesky output buffer. That discovery was bundled up in the CaptureHelper, but somehow never made its obvious way to the form_tag.

But I digress, we're talking about syntactic vinegar, not days of yore. With the new form_tag in place, we can do this:

<% form_tag :action => "create" do %> My pretty form! <% end %>

Yes, yes, it's awfully pretty. So where's the vinegar? Added to the edge case. See, form_tag still works without a block, as it's former stand-alone self. In other words, you can still do:

<%= form_tag :action => "create" %> My pretty form! </form>

But what's that? The closing form-tag is now happening in pure HTML, highlighting the teeth-scratching lack of symmetry between opening a tag in Ruby and finishing it in vanilla HTML. This is because we've gone ahead and deprecated end_form_tag. Even though this method could potentially still be useful in combination with a form_tag called without a block.

And here comes the punch line. While we're still allowing non-block usage of form_tag, we're marginalizing it and discouraging it by forcing you to suffer a lack of symmetry to use it. The perfect tarmac of preferred approach is traded in for the rocky gravel of the possible approach. There may well be a case for using form_tag without blocks (think opening a form in one partial and needing it to close it in another, making it impossible to keep one block scope). So we want to allow for the edge, but highlight that you're balancing on it.

I know this is a trivial example. Perhaps carrying a larger design discussion than it can bear, but I none the less saw it as another drum to beat for baseline in the battle between those who seek to allow and forbid and those who seek to encourage and discourage. In the Rails camp, we're big believers of the latter approach.

Never assume that you as a language or framework designer is an eternal oracle of insight who can see foresee all possible use cases. The programmer working on a real application using your work for their assistance will almost always know more about her application-specific issues than you possibly can. It's rarely your role to outright deny certain behaviors. Your role is to guide, to inform, and to highlight the trade-offs.

The best way to do that is to appeal to a programmer's sense of aesthetics (at least in communities where that is a treasured attribute). Make that which is common, that which is preferred, into a beautiful structure. Sprinkle syntactic sugar to encourage. Then, make that which is uncommon, that which is suspicious, into an ugly structure. If the programmer truly needs it, the bitter taste of the vinegar will not be a deterrent. But if she doesn't, you did your best to reel her back from an unnecessary off-road excursion.