16/8/2010 16:08 Lucas Ontivero

Escalando DSL internos

En mi entrada Fluent Interfaces y TDD presentaba una prueba de concepto sobre un DSL interno que estaba desarrollando para encapsular varios detalles de la manipulación de documentos en el proyecto en el que trabajo actualmente. Luego de avanzar un tanto me doy con un problema muy común en la mayoría de las interfaces fluidas que he visto, a este patrón lo llamo sentencia única. Esto significa que una sentencia de un dsl interno no interactúa con otras del mismo. Veamos un ejemplo:

Dh.Using.AnimalControl
    .Where(
        ac => ac["Created"].LessThan(createdOn),
        ac => ac["Sex"].Not.EqualTo("Unknown"))
    .Perform(ac => ac.Document.ArchivedDate = DateTime.Now)
    .Archive();

¿Qué sucede si quisiera que los documentos fuesen accedidos por un orden dado? ¿Qué sucede si solo quiero que los documentos se archiven cuando se cumple una condición particular? ¿Qué sucede si quisiera imprimir estos documentos?. Bien, para hacer alguna de estas cosas podría extender la sintaxis así:

Dh.Using.AnimalControl
    .Where(
        ac => ac["Created"].LessThan(createdOn),
        ac => ac["Sex"].Not.EqualTo("Unknown"))
    .OrderBy(
        ac => ac["Created"].Ascendent)
    .Print();

Uhmm… el order by y el print son ahora soportados pero al costo de haber extendido la sintaxis, esto no puede estar bien. El servicio de indexado de documentos que se consulta nos permite traer páginas y definir el tamaño de las mismas para no traer un xml con 1.000.000 de resultados. ¿Cómo hago si quiero tener control de esto? ¿Debería renunciar a esta posibilidad en pos de la legibilidad y mantenibilidad?. No, lo que hay que hacer es salir del esquema totalmente declarativo. Veamos:

var ids = Dh.Query
    .Page(size: 40)
    .Where(
        ac => ac["Created"].LessThan(createdOn),
        ac => ac["Sex"].Not.EqualTo("Unknown"))
    .OrderBy(
        ac => ac["Age"].Ascendent
    );
 
Dh.Using.Documents.WithId(ids)
    .Perform(ac => { ac.Document.ArchivedDate = DateTime.Now; ac.Save(); })
        .If(ac => ac.IsMaster)
    .Perform(ac => ac.Print())
        .If(ac => !ac.IsMaster);

Esta separación nos da un fino manejo de la consulta y de las acciones a ejecutar sobre cada uno de los documentos sin complicar la sintnxis de la sentencia Using, por el contrario, ahora las expresiones soportadas son menos por lo que el lenguaje es más sencillo.

Archivado en: ,,,,,,,,,,
Comparte este post: