Estimación de Líneas de Código Orientada a Plantillas de Código Fuente Mario R. MORENO SABIDO Depto. de Sistemas y Computación, Instituto Tecnológico de Mérida Mérida, Yucatán 97118, México y Jorge BAROUDI PEREZMILICUA Depto. de Sistemas y Computación, Instituto Tecnológico de Mérida Mérida, Yucatán 97118, México RESUMEN En este artículo se describe el proceso de estimación para entornos de desarrollo ágiles, el cual se basa en características funcionales pequeñas de los sistemas a implementar. Para las estimaciones iniciales se puede utilizar la generación de código fuente a partir de plantillas de código ligadas a meta-datos, como por ejemplo, estructuras de tablas de bases de datos. El resultante en líneas de código puede complementarse con la estimación de las líneas de código que se tendrán que modificar para que el código generado se adapte a las variantes que se presentan en las diversas características funcionales del sistema. Si se realiza una retroalimentación de las plantillas de código en cada iteración del proceso, se puede lograr un desarrollo aún más ágil por cada una de las características funcionales comunes entre proyectos. Palabras Claves: Estimación de Proyectos de Software, XML, XSLT, Generación de Código, Refactorización de Código. 1. INTRODUCCIÓN La estimación del tamaño de un proyecto de desarrollo de software es una de las actividades más retadoras e importantes, y a menudo una tarea difícil. A medida que los requerimientos son más complejos, la estimación del tamaño tiene que incluir nuevos factores de estimación propios del proyecto, y por ello resulta muy difícil realizar modelos adecuados para la mayoría de los casos. Por otro lado, la experiencia en la metodología de desarrollo y en la tecnología en la que se desarrolla, difiere de persona a persona, por lo tanto, tomar datos de manera general puede llegar a ser inútil para calcular una estimación aproximada del tamaño sino se cuenta con una madurez en el equipo de desarrollo, esto es, que se integren estándares para todas las actividades de la programación. Para realizar una estimación de un proyecto, muchos equipos y organizaciones buscan definir un único proceso que generalice todo el desarrollo de software, pensando que si pudiera desarrollar software usando los mismos procesos, recursos, y produciendo los mismos documentos, sería mucho más fácil la administración y el aseguramiento de la calidad [1]. El problema es que en los sistemas de software, la tecnología y las organizaciones difieren tanto, que cualquiera de los modelos que realmente definan el desarrollo de software con su amplia gama de variaciones se vuelve de poco uso práctico, a menos que se describa cada posible rol, actividad, salida y paso en detalle, lo que en la práctica no resulta nada fácil. La única forma con la que se cuenta hasta ahora para lidiar con dicho problema es descomponerlo en partes más pequeñas, las cuales, en caso de requerirse, se manejarían en porciones aún más pequeñas, hasta que se llegue a un punto en el que se determine su solución práctica, y en que tiempo y con que capacidad de esfuerzo horas-hombre se hará dicha solución [2]. 2. ESTIMACIÓN DEL ESFUERZO DE DESARROLLO La estimación generalmente es una aproximación o un cálculo especulativo de un resultado futuro basado en aproximaciones, especulaciones y otros datos inciertos e incompletos [3]. La aplicación de una métrica para determinar el tamaño de un programa de software o componente se puede representar por medio del número de líneas de código. Una vez que se realiza el desarrollo se pueden hacer comparaciones para determinar lo acertado de la estimación y calificar los criterios de estimación utilizados. Los diferentes factores que forman parte de la estimación pueden ser ajustados conforme se obtenga mayor experiencia en circunstancias similares, reduciendo la diferencia entre la estimación del esfuerzo y el tiempo real de desarrollo. Con el uso de patrones de diseño [4] y la estimación basada en módulos análogos [5], un equipo comandado por Hugo Troche, originario de Asunción Paraguay, realizó estimación para proyectos en la universidad de Auburn, Alabama durante los años 2002 al 2004 mediante el número de líneas de código que se integran por cada patrón de diseño de la aplicación que cumplen funciones específicas previamente identificadas en cualquier contexto, como es el caso de los componentes de acceso a datos (DAO’s, Data Access Objects), los cuales están encargados de las conexiones con los servidores a base de datos y la ejecución de las consultas SQL. En este caso se identifican cuantas líneas de código pueden resultar en el DAO a partir de una sola columna, para luego multiplicar su valor por el número de columna y el número de tablas, obteniendo un total de líneas de código estimadas para dichos componentes o patrón de diseño. El número de líneas de código por columna está basado en datos históricos por patrón o componente. 3. XML Y XSLT XML (eXtensible Markup Language, Lenguaje de Marcado Extensible) viene a ser una versión reducida de SGML, y está especialmente diseñado para la definición de estructuras de documentos y el almacenamiento de datos. Se puede decir que XML puede utilizarse para el desarrollo de dos tipos de aplicaciones: Aplicaciones de Datos: los documentos XML por definición son “unidades de almacenamiento de datos” y el principal objetivo de este lenguaje consiste en definir una estructura lógica en forma de árbol de dichos datos. Aplicaciones de Documento: Permite la publicación de documentos XML utilizando técnicas de creación de estilos (CSS, XSL: FO) y técnicas para aplicar formatos (XSL, XSLT) a los contenidos XML. Las aplicaciones de documento posibilitan la publicación a cualquier formato conocido: HTML, PDF, entre otros [6]. XSLT (eXtensible Stylesheet Language Transformations, Lenguaje de Hojas Extensibles de Transformación) permite convertir documentos XML de una sintaxis a otra (por ejemplo, de XML a un documento HTML). XSL: FO (Lenguaje de Hojas Extensibles de Formateo de Objetos) es un lenguaje que permite especificar el formato visual con el cual se quiere presentar un documento XML; es usado principalmente para generar documentos PDF. XPath, o XML Path Language es una sintaxis (no basada en XML) para acceder o referirse a porciones de un documento XML. La conjunción de XML con XSLT, que es un lenguaje estándar de estilo para archivos XML, permite realizar transformaciones de los datos en el archivo XML a cualquier formato de archivo [3] (ver Figura 1). Figura 2. Representación XML de las Tablas de la Base de Datos. A continuación se presenta como ejemplo el código XML para la representación de una tabla de productos (ver Figura 3). <?xml version="1.0" encoding="ISO-8859-1"?> <tabla nombre="Productos"> <campos> <campo nombre="codigo" tipo="varchar" tamaño="10" llave_primaria="true" /> <campo nombre="descripcion" tipo="varchar" tamaño="100" /> <campo nombre="clasificacion" tipo="char" tamaño="3" /> <campo nombre="status" tipo="char" tamaño="1" valor_predefinido="A" /> </campos> </tabla> Figura 3. Representación en XML de la Tabla de Productos. Un ejemplo de generación de código con la estructura de la tabla Productos en un archivo XML y una serie de plantillas XSL se presenta en la Figura 4. En esta fase también se realiza la estimación de un porcentaje de líneas a refactorizar en la siguiente etapa. La generación del código puede realizarse en diferentes herramientas, tal es el caso de los navegadores de Internet como Mozilla FireFox e Internet Explorer. Una forma práctica y sencilla para realizar la generación del código es agregar una línea al archivo XML con la directiva xml-stylesheet y abriéndolo en el navegador (ver Figura 5). Figura 1. Transformación XML/XSL a otro Formato. 4. GENERACIÓN DE CÓDIGO CON PLANTILLAS XSL A continuación se presenta una representación en archivos XML de las tablas de una base de datos y plantillas de código fuente creadas a partir de archivos XSL y un procesador XSLT. Un ejemplo de la generación de código se puede observar en la Figura 2. Sin embargo, a pesar de que XSL tiene funciones para manejo de cadenas, números y otras funciones, puede llegar a ser muy difícil obtener un resultado al cien por ciento fiable de código que cumpla con los estándares de nombres de un lenguaje o del equipo de desarrollo. En la Figura 6 se muestra una clase generada con una plantilla XSL en lenguaje Java donde los métodos get y set no cumplen con la especificación de JavaBeans de Sun Microsystems, la cual indica que hay que capitalizar la primera letra de cada palabra a partir del prefijo get o set [7]. La plantilla XSL para generar el código de la Figura 6 consta del encabezado y una plantilla (xsl-template) interna que genera cada una de las propiedades de la clase conforme a los datos de los campos. Esta plantilla recibe como parámetro el tipo de dato y el nombre del campo para generar el atributo private de la clase y sus métodos public de acceso (ver Figura 7). <xsl:template name="createProperty"> <xsl:param name="tipoDato" /> <xsl:param name="nombreCampo" /> private <xsl:value-of select="$tipoDato" /><xsl:text> </xsl:text><xsl:value-of select="$nombreCampo" />; public <xsl:value-of select="$tipoDato" /> get<xsl:value-of select="$nombreCampo" />(){ return this.<xsl:value-of select="$nombreCampo" />; } public void set<xsl:value-of select="$nombreCampo" />(<xsl:value-of select="$tipoDato" /> valor){ this.<xsl:value-of select="$nombreCampo" /> = valor; } </xsl:template> Figura 4. Generación de Código con Plantillas XSL. <?xml version="1.0" encoding= "ISO-8859-1" ?> <?xml-stylesheet href="plantilla_entidades.xsl" type="text/xsl" ?> <tabla nombre="Productos">… Figura 5. Preparación de un Archivo XML para la Generación de Código a Partir de una Plantilla XSL. public class Productos { private String codigo; public String getcodigo(){ return this.codigo; } public void setcodigo(String valor){ this.codigo = valor; } private String descripcion; public String getdescripcion(){ return this.descripcion; } public void setdescripcion(String valor){ this.descripcion = valor; } private String clasificacion; public String getclasificacion(){ return this.clasificacion; } public void setclasificacion(String valor){ this.clasificacion = valor; } private String status; public String getstatus(){ return this.status; } public void setstatus(String valor){ this.status = valor; } } Figura 6. Código Generado de la Tabla Productos a Partir de la Estructura XML y una Plantilla XSL. Figura 7. Extracto de la Plantilla XSL para la Generación de Código Fuente con base en un Archivo XML de la Estructura de la Tabla Productos. 5. REFACTORIZACIÓN DE CÓDIGO La refactorización (del inglés Refactoring) es una técnica de la ingeniería de software para reestructurar un código fuente, alterando su estructura interna sin cambiar su comportamiento externo. Al final de la refactorización, cualquier cambio en el comportamiento es claramente un error y puede ser arreglado de manera separada a la depuración de la nueva funcionalidad. Un ejemplo de una refactorización trivial es cambiar el nombre de una variable para que sea más significativo, como una sola letra 't' a 'tiempo'. Una refactorización más compleja es transformar una parte de código dentro de un bloque en una subrutina. Una refactorización todavía aún más compleja es remplazar una sentencia condicional if por polimorfismo [3]. Existen herramientas de refactorización integradas a los entornos visuales de programación que facilitan este trabajo. Para el ejemplo de código generado de la Figura 6, y de acuerdo con el convencionalismo señalado por la especificación JavaBeans, se requiere refactorizar los nombres de los métodos, capitalizando la primera letra después del prefijo get y el prefijo set (modificaciones resaltadas en negritas y subrayado) (ver Figura 8). También en esta etapa se cambió en nombre de la clase a Producto (antes Productos). Sin la refactorización, estos cambios afectarían directamente a otros archivos de la aplicación que utilicen la clase Producto. public class Producto { private String codigo; public String getCodigo(){ return this.codigo; } public void setCodigo(String valor){ this.codigo = valor; } private String descripcion; public String getDescripcion(){ return this.descripcion; } public void setDescripcion(String valor){ this.descripcion = valor; } private String clasificacion; public String getClasificacion(){ return this.clasificacion; } public void setClasificacion(String valor){ this.clasificacion = valor; } private String status; public String getStatus(){ return this.status; } public void setStatus(String valor){ this.status = valor; } } Figura 8. Código Refactorizado de la Clase Producto. 6. COMPARACIÓN DE LÍNEAS DE CÓDIGO GENERADO Y CÓDIGO REFACTORIZADO En la Figura 9 se presenta un fragmento de código mejorado después de la retroalimentación sobre la plantilla XSL original de la Figura 7. En este caso se cambió el método de salida de la plantilla a HTML en vez de texto plano con la finalidad de manipular letras capitales con el atributo style. <xsl:template name="createProperty"> <xsl:param name="tipoDato" /> <xsl:param name="nombreCampo" /> private <xsl:value-of select="$tipoDato" /><xsl:text> </xsl:text><xsl:value-of select= "$nombreCampo" />;<br /> public <xsl:value-of select="$tipoDato" /> get<span style="text-transform:uppercase"><xsl:valueof select="substring($nombreCampo,1,1)" /></span><xsl:value-of select="substring($nombreCampo,2,stringlength($nombreCampo)-1)" />() { return this.<xsl:value-of select="$nombreCampo" />; }<br /> public void set<span style="texttransform:uppercase"><xsl:value-of select="substring($nombreCampo,1,1)" /></span><xsl:value-of select="substring($nombreCampo,2,stringlength($nombreCampo)-1)" />(<xsl:value-of select="$tipoDato" /> valor){ this.<xsl:value-of select="$nombreCampo" /> = valor; }<br /> </xsl:template> En esta fase se realiza una comparación de los archivos de forma manual o utilizando una herramienta de comparación línea a línea del código refactorizado contra el código generado. Figura 9. Retroalimentación de la plantilla XSL con Código Generado de Acuerdo al Estándar de JavaBeans. En el caso del archivo generado que se presenta en la Figura 6, se realizaron 9 cambios en la etapa de refactorización: 8 cambios para adaptarlo al convencionalismo de nombres de la especificación de JavaBeans y 1 más para cambiar el nombre de la clase (ver Figura 8). Este dato se registrará como el esfuerzo realizado. 8. PROCESO DE MEJORA CONTINUA DE LAS PLANTILLAS Cada archivo de clase o de un componente específico sería comparado con su archivo origen que fue generado por una plantilla XSL. Esta relación sirve para comparaciones futuras con la finalidad de establecer un historial de los cambios que ha tenido una clase o componente. La comparación implica también un esfuerzo pero sirve como indicador para determinar que plantillas se deben mejorar y así minimizar el esfuerzo durante refactorizaciones futuras a código generado. Una vez retroalimentada la plantilla, ésta se utiliza de nuevo para generar código en proyectos alternos o incluso dentro del mismo proyecto de desarrollo aplicando siempre el proceso cíclico de generación, refactorización, comparación y retroalimentación de las diferentes tablas de la base de datos. Este proceso conlleva a una mejora continua de las plantillas XSL y por ende a la adaptación de estándares definidos por el equipo de trabajo. 9. RESULTADOS Como resultado de este trabajo se obtuvo un proceso de estimación para entornos de desarrollo ágiles. Para probar este proceso fue necesario aplicarlo en proyectos reales, la mayoría de estos enfocados al desarrollo web. 7. RETROALIMENTACIÓN DE PLANTILLAS XSL Una vez que se han comparado los archivos de código generado y código refactorizado, se busca mejorar las plantillas en una fase de retroalimentación conforme a las experiencias obtenidas por los programadores durante la refactorización. En el ejemplo del código refactorizado de la Figura 8 se puede observar que ciertos detalles pueden ser mejorados para alcanzar apegarse al estándar. En la Figura 10 se presentan los datos de 2 proyectos reales a los cuales se les aplicó el proceso descrito en este documento. El proyecto 1 utilizó plantillas comerciales sin modificaciones por parte de los programadores. Las plantillas están separadas por capas: Modelo, Vista, Controlador. Durante el proceso se eligió una tabla que tuvo cambios en la presentación principalmente durante la vida del proyecto para reflejar modificaciones en capas de vista. En el proyecto 2 se realizaron adaptaciones a las plantillas después de la generación, principalmente a las plantillas de Controlador (para adaptar un método de paginación en listados) y a una plantilla de vista para Listados, mismo que era utilizado en el proyecto anterior. Se puede ver que existen menos cambios (si se compara el 168% de cambios entre revisiones del primer proyecto contra el 78.8% del segundo), lo cual le permitió al programador minimizar el número de líneas a modificar en los listados, aún cuando los formularios respectivos sufrieron cambios mucho más fuertes (debido a sugerencias del usuario). (Empleado.java) se puede observar que el grado de inclinación es menor. Es posible que no se pueda eliminar con las plantillas XSL la intervención de un programador para adaptar el archivo generado al contexto de la aplicación, principalmente en los casos de código de interfaces gráficas, sin embargo, el objetivo principal es que cada vez se logre una menor diferencia en las estimaciones de código que se necesitará refactorizar (en la fase de refactorización) y el resultado final que se obtuvo. 10. CONCLUSIONES Figura 10. Resultados de Aplicar el Proceso a Proyectos Reales. En la Figura 11 se ilustra por medio de un gráfica la diferencia de la comparación de una plantilla retroalimentada (dando por hecho que se realizó todo el proceso descrito en este documento) versus la generación de código sobre otra tabla de la base de datos utilizando la misma plantilla XSL (la cual fue usada en una segunda iteración del proceso de desarrollo). Esta plantilla fue usada en un proyecto diferente a los que se mencionan en la Figura 10. Esta diferencia se muestra con los porcentajes calculados a partir del total de líneas de código y las líneas de código estimadas y refactorizadas para los casos correspondientes. En este artículo se presentó un proceso para realizar la estimación de un proyecto de software, basada en plantillas XSL de una fuente que representa en un archivo XML la estructura de las tablas de la base de datos. Este proceso consta de 4 fases iniciando con la generación de código a partir de un archivo XML y una serie de plantillas XSL. Además, en esta fase se realiza la estimación inicial de un porcentaje de líneas a refactorizar en la siguiente. En la segunda fase se realiza la refactorización de acuerdo a las especificaciones de los estándares a seguir. Posteriormente, en la tercera fase se compara el archivo original generado con el refactorizado para determinar la diferencia entre la estimación y la refactorización. Finalmente, en la última fase se procede a una fase de retroalimentación de las plantillas XSL tomando en cuenta la experiencia adquirida por los programadores durante la refactorización. Una de las ventajas de usar el proceso de estimación ágil es que permite que las iteraciones futuras se beneficien minimizando el número de líneas a refactorizar. El uso de plantillas XSL por su parte permite adaptar diferentes estructuras plasmadas en XML a diferentes lenguajes de programación. A medida que se desarrolla el modelo de la aplicación, se van simplificando las tareas de refactorización e incluyendo mejoras y nuevas tecnologías al código base que se genera, sin embargo, conforme se sube de nivel hacia la interfaz gráfica la adaptación de las plantillas es más complicada. 11. REFERENCIAS Figura 11. Historial del Uso de una Plantilla XSL para Generar Código . La inclinación de la línea de la primera iteración (Producto.java) en la gráfica indica que se tiene una diferencia entre la estimación y el resultado final. En la segunda iteración [1] Palmer, R. y J. Felsing, (2002). A practical guide to Feature Driven Development. Ed. Prentice Hall PTR [2] Weinberg, G., (1992 – 1997). Quality Software Management. Vols. 1 – 4. Ed. New York Dorset House. [3] Wikipedia, (2008). “Estimación de Proyectos de Software” [En línea]. Disponible en: http://www.wikipedia.org [Accesado el día 23 de Junio de 2008] [4] Gamma, E. et al., (1995). Design Patterns. Ed. Boston: Addison – Wesley. [5] Humphrey, W., (1994). A discipline for Software Engineering. Ed. Boston: Addison – Wesley. [6] Rodríguez, A., (2004). Publicación en Internet y Tecnología XML. Ed. Alfaomega [7] Sun Microsystems, (2008). “Especificación de JavaBeans” [En línea]. Disponible en: http://java.sun.com/products/javabeans/docs/spec.htmll [Accesado el día 14 de Agosto de 2008]