torsdag 24 februari 2011

Building a DSL with groovy

I am currently working an a small 2-d game, where there're supposed to be some organisms spread out over the "world". I soon realized that I will have to test different setups of the world with organisms spread out.
I wrote some tests for different locations of organisms, and added some comments to explain it visually.

The original test contained something like this:

/**
* This creates a world with two organisms, located:
* ---------------
* |______________|
* |_____1________|
* |__________2___|
* |______________|
*
*/
def world = new World(organisms: [new Organism(id:1, x:10,y:10), new Organism(id:2, x:20, y:20)])

This was an obvious candidate for a DSL; I beleive that any time you feel the need to explain your code (visually) with a comment, you should consider building a DSL instead.


This is my first draft:

class Organism {
def id, x, y, radius
}
class World {
def width, height
def organisms = []
}
class WorldBuilder {
def yIndex = 0
def organisms = []
def radius = 1
def xIndex = 0
def getProperty(String name) {
def metaProperty = metaClass.getMetaProperty(name)
if (!metaProperty) {
if(name.length() > xIndex){
xIndex = name.length()
}
name.eachWithIndex {character, index ->
if (character != '_') {
println "create an organism with: x:$index, y:${yIndex}, radius: 1"
organisms << new Organism(id:character, x:index, y:yIndex, radius: radius )
}
}
yIndex++
println "get the property with name: $name"
return this
}else{
return metaProperty.getProperty(this)
}
}

def build() {
new World(organisms: organisms, width: xIndex, height: yIndex)
}
}

class WorldBuilderTests extends GroovyTestCase {
void test_build() {
World world = new WorldBuilder().with {
_________1_____2
__3__4_____a___6
________________
}.build()
assertEquals(6, world.organisms.size())

def org1 = world?.organisms.find { it.id == "1" }
assertEquals(1, org1.radius)
assertEquals(9, org1.x)
assertEquals(0, org1.y)

assertEquals(16, world.width)
assertEquals(3, world.height)

}
}

Inga kommentarer:

Skicka en kommentar