Kata de api fluida del Coding dojo de Huesca en Scala.
El viernes estuvimos en Huesca en el coding dojo organizado por frogtek con carlos ble. Fue bastante entretenido y muy interesante el programar por parejas. A pesar de que allí tiré de Java, me ha picado el gusanillo y he hecho la kata en Scala. Ahí va el código:
import FluidApi._
case class User(val name: String, val surname: String, val age: Int, val location: String)
object FluidApi {
def select(field: String): SelectClause = new SelectClause(field)
def exec(clause: Executable) = clause.execute
def getAttrib(user: User, field: String): Any = {
val method = user.getClass.getDeclaredMethod(field)
method.invoke(user).asInstanceOf[Object]
}
}
trait Executable {
def execute(): List[Any];
}
class FromClause(fromObjs: List[User], select: SelectClause) extends Executable {
def execute() : List[Any] = fromObjs.map(getAttr(_, select.field))
def where(field: String) = new WhereClause(field, this)
def executeFiltered(filterfunc: (List[User]) => List[User]): List[Any] = {
filterfunc(fromObjs).map(getAttrib(_, select.field))
}
private def getAttr(user: User, field: String): Any = {
val method = user.getClass.getDeclaredMethod(field)
method.invoke(user).asInstanceOf[Object]
}
}
class SelectClause(val field: String) {
def from(fromObjs: List[User]) = new FromClause(fromObjs, this)
}
class WhereClause(val field: String, from: FromClause) {
def greater_than(value: Int) = new ConditionValueClause(this, from, {
_.filter(getAttrib(_, field) match {
case v: Int => v > value
})
})
def less_than(value: Int) = new ConditionValueClause(this, from, {
_.filter(getAttrib(_, field) match {
case v: Int => v < value
})
})
}
class ConditionValueClause(where: WhereClause, from: FromClause,
filterfunc: (List[User]) => List[User]) extends Executable {
def filter = filterfunc
def execute() : List[Any] = from.executeFiltered(filterfunc)
}
class FluidApiTest extends FunSuite {
val users = List(User("pablito", "perez", 20, "Moscow"),
User("pedrin", "rodriguez", 54, "Alcorcón"))
User("pepito", "lopez", 40, "San Francisco")
test("select name should return the name of all users") {
val names = exec(select("name").from(users));
assert(names.size === 2)
assert(names.contains("pablito") && names.contains("pedrin"))
}
test("select age should return the age of all users") {
val ages = exec(select("age").from(users));
assert(ages.size === 2)
assert(ages.contains(20) && ages.contains(54))
}
test("select name where age > 45 should return pedrin)") {
val names = exec(select("name").from(users).where("age").greater_than(20));
assert(names.size === 1)
assert(names.contains("pedrin"))
}
test("select name where age < 21 should return pablito)") {
val names = exec(select("name").from(users).where("age").less_than(21));
assert(names.size === 1)
assert(names.contains("pablito"))
}
}
0 comentarios