Web Applications

Good magic, bad magic

Philip Potter pinged me his post on Sinatra magic during the week. Mark Needham’s comment and code on solving the mocking problem is good advice to the problem as posed.

At Wazoku where we use the often equally magical Bottle framework we don’t use top-down TDD but instead outside-in functional tests (with no funky runners as we don’t need CI). This solves the whole magic issue by shifting the attention to what the public interactions of the application are. This is one of the massive benefits of using a microapp HTTP/JSON/REST-like architecture. I could flip the API from Bottle to Django or Compojure or Sinatra and my test suite can keep on rocking and telling me whether the behaviour my consumers are relying on is correct.

The major thing I felt when reading through Philip’s post was the massive amount of effort that was going into testing relatively simple behaviour. This is a bit of anti-pattern with Agile developers (or perhaps it is part of the mastery thing where rote “correct” behaviour is modified by experience and judgement). One of the massive advantages of using something like Sinatra is that you can get a whole web app with rich behaviour into less than 200 lines. If you then create thousands of lines of test code and battle with the magic for hours on end you’ve completely destroyed your productivity.

If you have a code base that you expect to be large and highly contested by a large development team you need good, layered testing and to use frameworks that support that. If you have an app that is small and when its done it is done then there is no need to agonise as to whether it was done “right”.

The idea that top-down TDD is the only correct way to write software is corrosive. When faced with a generally poorly skilled and educated workforce it is good to have rules. I have imposed a certain style of TDD on a group myself because it gives a good framework for work and achieves very consistent output.

However with skilled people on small scale projects you can kill yourself by imposing arbitrary rules. I love Sinatra and while I might be equivocal about magic I think it is ridiculous to moan about it if you are using something as unicorn-packed as Ruby. For example Philip was trying to use RSpec mocks and stubs to do his TDD. The result is kind of saying that you’re disappointed that your “good” magic for testing didn’t work with the “bad” magic of a DSL for web applications. Even if your RSpec code passed its tests you still haven’t said anything particularly deep about the production behaviour of your application as your unit testing environment was severely compromised by the manipulations of your mocking framework.

So my rule of thumb is: if its simple, do it; if it was simple, functionally test it; if it was never really simple then test-drive it with suitable tools.

Ruby, Web Applications

Haml, Sinatra and template variables

Haml advertises itself as offering a haiku for HTML; that might mean it is short, beautiful and expressive or it could mean it is enigmatic, unsatisfying and cryptic. After a period away I have forgotten how Ruby-centric Haml is. If you want to include parameters in a Haml template within Sinatra you need to bind a map to the parameter locals.

haml :index, :locals => {:hello => “World”}

The easiest way to then include the data within a tag seems to be to use Ruby string interpolation

%p= “Hello #{locals[:hello]}”

There may be more elegant ways to do this but it seems relatively idiomatic. It is just hard to adjust to after months working on very restrictive templating systems.

Programming, Ruby, Scripting, Web Applications

Sinatra example

Since the Sinatra Project website currently seems to have been hijacked and directed to spam (the RubyForge page seems to be fine and is still a good introduction in its own right) I wanted to post an example of how to get going with Sinatra and also to highlight what makes it such a different approach to web frameworks. Here’s the example code on CodeDumper.

I wrote this with JRuby (for the cross-platform win). You’ll need to install the Sinatra, Haml and Mongrel Gems to get it to run.

It uses two styles, first there is the REST-ful extraction of parameters from the url and then there is the form POST submission. In both cases the code is pretty much the same as Sinatra extracts all parameters into the params hash.

I’ve inlined the Haml to make the example simple but normally the view templates would be extracted out of the code into separate files.

Sinatra is sometimes described as being as a web DSL rather than a web framework, it seems apt as it eschews MVC separation but instead by attaching code to routes directly it allows Controller code to be tiny and to delegate appropriately rather than putting in a heavyweight structure that might result in more frameworking code than actual “doing” code.

However one of the things I really like is something you can’t show in a code fragment and that is the ability to dynamically interact with your web application on the fly. Start up Sinatra, change the code of the file you’re running and your changes are reflected immediately. End the compile, deploy, view cycle! It kind of makes web programming fun again.

Programming, Ruby, Scripting, Web Applications

Sinatra and Haml

On Monday I was meant to be learning how to use the Grails framework (following up the impressive Grails site that Sky has launched) but I instead got distracted into scratching another itch, using Sinatra with JRuby. Since I was doing a little REST application I thought I would also give Haml a go as it promised a far easier way of generating HTML responses.

Installing both Gems was easy as ever and Sinatra was really easy to understand conceptually. Put the HTTP method name, the URI pattern you want to match and then the return value of the block is what goes back to the client in the response.

So for example to map “/hello” to the plain text response “Hello World” you simply have.

get "/hello" do
  "Hello World"

Fire up the script (with necessary requires) and a HTTP server is set up and running. It really couldn’t be simpler. You can use a :symbol in the URI matcher and then access it through the params hash. Within half an hour I was starting to add resources into my served HTML and I felt like master of the REST UNIVERSE.

Sinatra is a really smart piece of code that makes it simple to write a basic web application. I have loads of ideas of how it could be useful but one of my first thoughts was that it actually does a good job of solving the issue of GUI platforms.

My next project is to see how it works with posting data back to the app but on the face of it it all seems straight-forward.

Haml is another story. It is undoubtedly a good idea and on the right track. A DSL for creating HTML the method html for example creates a block html tag  while p “Hello World” creates a paragraph tag with the parameter as the content. Hash parameters sent to the method become attributes of the class.

It is much quicker than generating the HTML by hand but often not by much. That is because Haml has not found the same easy metaphor for code and content that Sinatra has. It is very picky, constantly harping about two-space indentation (no more, no less, don’t dare use tabs you bastardo!) for example, it sometimes throws a stack trace that failed to make it to Sinatra leading to a blank screen on the browser and hunt into the console for a clue as to what has gone wrong.

The documentation is to poor to figure out why the library doesn’t accept what you are doing and I am still baffled as to whether the module handles inline tags or whether you are meant to devolve all of that to Textile. Passing parameters to Haml templates seems unnecessarily complex (the only way I could get it to work is with normal string interpolation, it’s a solution but it seems to break the DSL concept) and mixing inline formatting with parameters baffles me still.

Haml makes more sense to me than RHTML style templating but its claim to simplicity and enjoyment seems to come only with a deep understanding and long experience with using it. It took me 20 minutes to fall in love with Sinatra but it took 20 minutes for me to get a working Haml page. And I didn’t enjoy myself doing it.