Domain Specific Adventures in Real Life
There is a lot of buzz about Domain Specific Languages and about ten thousand pages describing what they are, so I’m just going to demonstrate a Domain Specific language that I am personally using. It’s for testing our chess engine, pawnzilla.
Probably the simplest thing one can do in chess is move a piece. Here is a sample unit test from earlier in the project:
1 2 3 4 5 6 7 8 9 | def test_should_move_piece state = GameState.new state.clear state.place_piece(Coord.new(0, 0), Chess::Piece.new(Chess::Colour::WHITE, Chess::Piece::PAWN)) state.move_piece(Coord.new(0, 0), Coord.new(0, 1)) assert_nil(state.sq_at(Coord.new(0, 0).piece) assert_not_nil(state.sq_at(Coord.new(0, 1).piece) assert_equal(Chess::Piece.new(Chess::Colour::WHITE, Chess::Piece::PAWN) end |
Right now you’re probably thinking “DAMN, that’s a lot of code, and I can barely read it!” And you’d be right. Here’s what the exact same test looks like after some massive rethinking:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | def test_should_move_piece state = GameState.new state.place_pieces(" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - p - - - - - - - ") state.move_piece(A1, A2) assert_position(state, " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - p - - - - - - - - - - - - - - - ") end |
Now, dear reader, assuming you know even the tiniest little bit about chess, is there any way you can’t understand this test? This relies on two primitives, each very important in their own way. First, the chessboard itself. Chess players will be familiar with FEN, or Forsythe Edwards Notation, which is used to describe chess positions. Now, FEN is less verbose than our chess board object, but we take the idea of piece representation – white pieces are lower case, black pieces are upper case. This makes it trivial to present any conceivable chess position in the same amount of space, and anybody looking at a test knows exactly what it’s trying to accomplish. The second important thing to note is that in the move_piece method, we’re using simple constants that represent the coordinates of all 64 squares in the corresponding algebraic notation. While (0, 0) (0, 1) is convenient for the engine, it’s very tough for a chess playing human – you end up spending several seconds mentally transposing the cartesian coordinates into algebraic notation. Why not just remove the barriers?
Tests that may have previously been a nightmare to read and figure out become dead simple:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | def test_should_detect_blockable_back_rank_checkmate state = GameState.new state.place_pieces(" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - b - - - - - - - - - - - - - - - - - - - p p p R - - - - - k - ") assert(!state.checkmate?(BLACK)) end |
This idea can extend to other tests as well. For example, let’s define a square under attack using an asterisk(*). Then testing attack vector calculations also becomes an easy visual test:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | def test_should_calcluate_queen_attack state = GameState.new state.place_pieces(" - - - - - - - - - - - - - P - - - - - - - - - - - - - Q - - - - - - - - - - - - - - - - - p - - - - - - - - - - - - - - - - - - ") state.calculate_queen_attack(BLACK) assert_attack_state(state, " * - - * - - - - - * - * - P - - - - * * * - - - * * * Q * * * * - - * * * - - - - * - * - p - - * - - * - - - - - - - * - - - - ") end |
Now you can really see the power! Can you imagine trying to make sense of a test that had to check all of that board real estate using coordinates?
This demonstration is the quickest way I know how to define a domain specific language. We take concepts directly from our domain, the game of chess, and create primitives that translate directly to real world concepts. Because of its lovely meta-programming facilities, it’s very easy to make Ruby use our DAL by adding our code to the Unit test module. It is important to note that we are not extending the unit test module, but adding behavior to it, as if our domain concepts are native. It’s quite simple:
1 2 3 4 5 6 7 8 9 10 11 12 13 | require "geometry" module Test::Unit class TestCase A1 = Coord.new(0, 0) # etc. H8 = Coord.new(7, 7) def assert_position(state, position) # code end # and so on end |
Now all of our tests can call upon an incredibly rich toolset that brings us to a holy grail that I previously thought was unattainable: Code that is actually easier to read than it is to write. That it’s not hard to write either is just icing on the cake. You just create a macro that drops an empty grid into the code, place your pieces, and away you go.
One of the most interesting things about this is that from a technical standpoint, this was a very easy thing to implement – Ron did the translation stuff and converted several test in only a few hours. The important breakthrough here, like when Google unveiled their map website, is NOT that it requires crazy voodoo programming, but that it requires a different way of applying what’s right in front of us.









Some auteur directors find a muse and form long lasting relationships. Think Martin Scorcese and Leonardo DiCaprio. Think John Waters and Divine. Think Kenneth Branagh and Kenneth Branagh. But you’d be hard-pressed to find a more fruitful pairing than Tim Burton and Johnny Depp, the team that brought us such masterpieces as Edward Scissorhands and Ed Wood. Add to that list Sweeney Todd, a surreal and captivating musical so far removed from the usual fare as to be almost subversive. Like Moulin Rouge, not Hairspray.
The cinematography is unmistakably Burton – view any frame from the film and you could identify its maker. Other signatures are there: Todd has hair that seems to be a mix between Edward Scissorhands and Robert Smith, while Ms. Lovett has the pallid complexion of a corpse (but a hot corpse.) The sets are simultaneously part of and beyond the theater tradition, with stage like intimacy in some scenes and expansive vistas in others. There is a nice flash-forward that changes the locations, but proves Todd to be a most morose madman. The murders themselves are lurid, fetishistic, and unsettling in a way that few films attain. It would seems that they would become mundane through sheer repetition, but they’re rough, gory, and plausible — I flinched just about every time a razor came onscreen.