Monday, June 9, 2008

Un lenguaje de dominio especifico para interfaces gráficas

Muchas veces me paso que al desarrollar una aplicación de escritorio no incluí una ventana más para evitar el tedio de tener que abrir el diseñador de ventanas del entorno y genera otro archivo y otra clase más con todo el código generado (que en general es terrible je). Por tanto, para evitarme esa complicación termine reutilizando otra ventana que ya tenía aunque no fuera lo más adecuado.

Por otro lado, si hemos tenido la oportunidad de programar interfaces gráficas en más de un lenguaje o en más de una API aún en el mismo lenguaje, sabremos que cada quién trabaja las interfaces como quiere. En definitiva una ventana con un textbox y un botón aceptar, es eso. Sin embargo, si lo programamos en C# es de una forma con Windows Form, con WPF es de otra manera, si usamos C++ lo podemos hacer con el API de Windows, con MFC, con GTK o cualquier otra librería, en Java lógicamente es distinto, en Javascript también por supuesto es diferente. En cada plataforma los eventos se enlazan de manera diferente, los contenedores trabajan distinto, entre otros problemas.

El problema que encara el ejemplo del post, es la complejidad del código y la poca legibilidad. Por ejemplo, si construimos una ventana con C# usando Windows forms debemos de hacer una clase que herede de System.Windows.Forms.Form, luego estableceremos las propiedades en el constructor o en algún otro método. Los controles internos también los deberemos de definir en general como campos, agregarlos al contenedor, setearle las propiedades, capturar los eventos, etc. Todo este código hace que al final tengamos una clase la cual, si no fuera por la ayuda de los IDEs nos sería complicado de manipular y entender.

En lugar de tener que escribir todo ese código no necesariamente intuitivo para quien no uso antes la librería, en LayerD podemos desarrollar una classfactory que nos permita declarar y utilizar interfaces graficas de la siguiente forma:

GUI::Window(MiVentana3){

    Text = "Una ventana en un DSL con LayerD";

    Controls{

        Button(CSalir){

            Text="Salir"; AutoSize=true;

            Click{

                MessageBox::Show("Saliendo de la aplicación");

                this.Close();

            };

        };

    };

};

El código superior casi no necesita explicación si se toma el trabajo de leerlo. Declara una ventana cuyo nombre será "MiVentana3", establece el título de la ventana con "Text = "Una ventana en un DSL con LayerD"". Luego se especifican los controles directamente dentro del bloque "Controls". El ejemplo muestra un botón "CSalir" al cual se capturo el evento "Click" simplemente escribiendo "Click{…}" y proporcionando la implementación del evento entre llaves, las propiedades del botón se establecieron como simples asignaciones "Text = "Salir";" y "AutoSize = true;".

El lenguaje de dominio específico está pensado de tal forma que es posible utilizar cualquier clase de Windows Forms directamente dentro de la colección de controles, setear propiedades y capturar eventos de forma directa usando sólo el nombre del evento y proporcionando la implementación en un bloque.

En el SDK de LayerD podrá encontrar un ejemplo de uso de este lenguaje de dominio específico "EjemploGUI.dpp" y la classfactory que implementa el lenguaje de dominio especifico en "Zoe.DotNET.UtilsTemplate.dpp". Puede insertar un ejemplo en su código usando el modo interactivo con la instrucción "Zoe::DotNET::Utils::iGUI::Help()" (o sólo "iGUI::Help()" si ya tiene un using "Zoe::DotNET::Utils").

Si comparamos el código superior con el código de una ventana en C# o Java es muy probable que le parezca mucho más claro, más fácil de leer y hasta se anime a escribirlo a mano sin la ayuda de un diseñador :-) .

Por cierto, la classfactory que implementa este lenguaje de dominio específico no tiene miles de líneas de código :-). El ejemplo, encara uno de los problemas de las GUI en muchos de los lenguajes actuales volviendo el código de GUIs fácil de escribir, leer y mantener (lo cual no es necesariamente poco), pero sólo sirve para ser utilizada para desarrollar GUIs para .NET usando Windows Forms. Una mejora de este DSL será agregar la capacidad multiplataforma y permitir que sirva para Windows Forms, WPF, ASP.NET y Java. Ello es perfectamente posible en LayerD, simplemente hay que trabajar un poquito más :-), con seguridad uno de los ejemplos futuros.

A modo de avance les paso un ejemplo de un GUI similar para hacer paginas ASP.NET en LayerD:

///Pagina ASP.NET 2.0 implementada con un DSL

ASPNET::Page(TestPage){

    Title = "La primera pagina ASPNET en un DSL con LayerD";

    Controls{

    "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">";

    "<html xmlns=\"http://www.w3.org/1999/xhtml\" >";

    "<head>";

    "<title>Pagina ASP.NET 2.0 implementada con un DSL usando Meta D++.</title>";

    "</head>";

    "<body>";

    "<h2>El título de mi primera pagina ASP.NET en LayerD</h2>";

    "<br/>";

    HtmlForm(form1){

    Controls{

        Label(l2){

            CssClass="miClaseCSS";

            Text="Label Inicio";            

        };

        "<br/>";

        Calendar(c1){

            ID="c1";            

        };

        "<br/>";

        Button(CSalir){

            Text="¡Hacer Algo!";            

            Click{

                l2.Text="Hola Mundo desde el Server";

            };

        };

        "<br/>";

        "<br/>";

        Button(CCambiar){

            Text="Cambiar página";

            Click{

                Response.Redirect("testajax.aspx");

            };

        };

    };

    };

    "</body>";

    "</html>";

    };

};

///Fin Pagina ASP.NET 2.0 implementada con un DSL

Hasta la próxima!!

No comments: