It all started with a desire to experiment a few things: Sinatra, Shoes, and the context testing framework. So I decided to write a simple application – the classic tic-tac-toe game. I ended up with 3 interfaces:
- command line interface (cli)
- web app (using Sinatra)
- GUI desktop app (using Shoes)
I thought it’d be nice to give a little feedback on my experience.
Ric-Rac-Roe: the App
I tried to write ‘nice Ruby code’, that is, readable/intuitive code along side tests (as a result of TDD, but complemented so that it serves as API doc). You can check the code out on github.
1 Grid model for the 9 squares of the tic-tac-toe as well as its rules (e.g. check for winning position, only play in an empty square, etc.). 1 Game model so that a gameplay can interact with the tic-tac-toe grid (via the Game#play method). The contract for the gameplay is to define 3 methods, which will be called at each turn (from the Game#play method):
- position(position) #reads the player’s move
- status_message=(msg) #sets the status message
- squares=(squares) #sets the grid’s squares
There currently exists 3 gameplays: CLI, web and desktop.
The classes diagram could look like this:
- (non-tests, non-views) LOC: 345
- tests LOC: 308
- C0 code coverage: 98%
I must say it was a joy to write Sinatra code. Quick, easy and fun. I’m aware my app is quite simple, but the light nature and the hands-off approach of Sinatra fit my tic-tac-toe project perfectly.
Support from the Sinatra Community
Sinatra’s Rdoc got me started real quick. No waste of time. On their #sinatra IRC channel, Ryan Tomayko, one of Sinatra lead developers, as well as some others, were there to assist on a few occasions. Lots of nice people in there, good vibe.
Booting up my first Shoes app was also easy, but it took me more time.
The development is intuitive because the layout management for your components is done web-style, with margin, padding, colors, etc. for components that you toss into either stacks (akin to usual block div’s) or flows (akin to inline div’s). You define your callbacks (like a click handler on a button) with a Ruby block appended to the button’s click method. So you get the drift. It starts to feel natural, after a little getting used to.
Support from the Shoes Community
The IRC channel #shoes is as quiet as a cemetery when it’s -35 C. Seth Thomas Rasmussen seems to be the only one active in there, and he is the one who helped me out (and some others) with my newbe questions. I thought I’d see _why hanging in there, but according to Seth, he hasn’t hanged in there for months. No doubt, busy elsewhere. But he’s actively working on Shoes (and has been for a long time), when you look at the github’s project history. As for the Shoes mailing-list, there’s medium activity (circa 1 mail per day).
The neat built-in manual (which comes with the Shoes installer) is your best way to find your answers; you don’t need much else. Finally, perusing through a few sample apps is a great way to get some source code inspiration.
I read a few interesting posts on testing frameworks, with a focus on context. I wanted to try it, and enjoyed it. All it requires is test/unit and you can have contexts in your tests, and play it a la BDD, RSpec-style (describe/it), shoulda-style (context/should), or context-style (context/test) it doesn’t matter. With context, you can mix all that, and have the context/it flavor if you will, without even including RSpec.
I ended up using pure test/unit in some places (e.g. testing simple input parsing, or my Array’s monkeypatch), RSpec in some others (e.g. testing Sinatra’s routes). And in either situations sometimes I found I needed contexts on top of test/unit. So it all depends on what you want to do, it just felt good to use the most appropriate tool of my tools belt, depending on the context (no pun intended).
Overall, I had a good time, and now I’m happy to know a bit more about quality tools. Any feedback on the code is welcome (design-wise, Ruby-wise, testing-wise, etc.).