domingo, 20 de diciembre de 2015

CapicuaGen: Proyecto de generador de codigo

Me encuentro estos días por comenzar mi proyecto de fin de master en "Investigación en ingeniera de software". Después de mucho debatir el tema decidí hacer un producto orientado a la generación automática de código, y a la construcción de software desde un enfoque generativo. ¿Que quiere decir esto? Bueno básicamente que construiremos un software, cuya misión es construir otro software, o mas exactamente el código de dicho software. El generador de código que voy a hacer se llamara CapicuaGen, nombre que elegí de forma aleatoria entre varias opciones, y espero, quizás, publicarlo como GPL (o otra licencia afín). En los siguientes meses iré publicando los avances que vaya haciendo en este tema y según sea posible el código fuente, quizás en GitHub.

Para comenzar, publico la propuesta del proyecto, sobre la que voy a comenzar a construir.

Situación actual


Durante la creación de sistemas empresariales, es común que se den las siguientes circunstancias:

  • Software muy parecido a desarrollos anteriores, pero lo suficientemente diferente para impedir que se reúse software y librerías de una forma clara y consistente.
  • Cortos tiempo de desarrollo.
  • Numero de recursos limitados (tanto económicos como humanos).
  • Equipos que atacan varios frentes que no tiene que ver con el sistema a desarrollar en cuestión (los recursos desarrollando o soportando varios sistemas a la vez).

El resultado de toda esta combinación de factores causa los siguientes problemas en el desarrollo de un sistema:

  • Lentitud en el desarrollo.
  • Retrasó en los tiempos de entrega.
  • Elevación de costos.
  • Multitud de horas extras realizadas por el equipo, lo que a su vez en la motivación de este.
  • Sacrificios en la calidad del sistema, lo que a su vez lleva a fallos en el sistema.

Como conclusión impactamos aspectos relativos al producto en si, como la calidad y el tiempo de entrega, y por otro lado impactamos en el equipo de personas que trabaja en el sistema.

Objetivos


Los objetivos a conseguir son los siguientes:

  • Agilizar la construcción de un sistema a partir del uso de generadores de código, que creen de manera adecuada las características comunes de cada sistema, ensamblándola apropiadamente.
  • Reducir la programación manual de un sistema a los elementos particulares que así lo requieran, esto es, aquellos elementos que son exclusivos del sistema y por lo tanto no están incluidos en otros sistemas.

Con el cumplimiento de estos dos objetivos se espera satisfacer las siguientes necesarias:

  • Aumento de la calidad del software al generarse en parte de forma automática. Los fallos detectados se podrían corregir en los elementos generadores y aplicar automáticamente al código de los sistemas.
  • Los codificadores no perderían tiempo realizando tareas repetitivas y se concentraría en las tareas que realmente da valor al sistema, y no en aquellas que se duplican sistema tras sistema.
  • Reducción de tiempo de desarrollo, en base a la generación de código automático, lo cual a su vez reduce el número de hora extras a desarrollar por un sistema.

Propuesta


Se realiza la siguiente propuesta de solución:

  • Es necesario detectar las características (features) comunes a un sistema, y las posibles variaciones de dichas características.
  • El análisis de dichas características detectadas y sus posibles variaciones, serán incorporados dentro de un generador de código, llamado Generador de características.
  • Los generadores de características serán los encargados de crear el código fuente que implementan las mencionadas características en base a una configuración sobre su variabilidad.
  • Los generadores de características deben ser independientes unos de otros, aunque pueden tener una serie de interfaces con las que exponer servicios a otras características, con el menor acoplamiento posible (debe ser lo más independientes posible).
  • La configuración de la variabilidad debe ser lo más versátil posible, si en una primera versión se uso XML, se intentara usar Ruby como lenguaje de configuración, parecido a la configuración de los archivos RakeFile o a un archivo podFile de CocoaPods.
  • Igualmente la generación de un sistema se llevara a cabo mediante la agrupación de varios generadores de características, que interactúan entre sí, para crear el código de dicho sistema.
  • La configuración, tanto del sistema, como de la variabilidad del sistema deben hacerse a través de una interfaz grafica que facilite dicha tarea.
  • Cuando se genera el código de un sistema, es necesario considerar que el sistema no puede generarse en un 100% de forma automática, por lo que habrá una parte del sistema que será creada automáticamente, y otra parte que lo creara el programador. Es importante que el generador reconozca la parte creada manualmente por el codificador y no sea reemplazado su código en ninguna circunstancia.
  • La creación de generadores de características en sí, es construida de forma manual, y se crean en parte a base de plantillas de código y analizadores de código, realizados en Ruby
  • Estos generadores de características una vez creados, podrán ser usados por varios programadores, con lo que se creara un repositorio centralizado en los que los programadores puedan subir sus generadores de características, o bajar los generadores de característica creados por otros programadores, algo parecido a las gemas de Ruby.
  • Hay que considerar que el generador de características, genera código, esa es su funcionalidad, es decir en ningún caso son librerías o framework a usar en nuestro código, sin embargo el código generador si puede usar librerías o framework externos.
  • Unos de los objetivos de generar el código, es aumentar la calidad del sistema, haciendo que el código generador implemente patrones de software, así como estándares y mejores prácticas de programación.
  • Hay que considerar que si tenemos un sistema generado con una versión de un generador de características y descargamos una nueva versión de las características podemos volver a generar el código y aprovechar las nuevas mejoras y cambios de esta versión.

martes, 1 de diciembre de 2015

Regla N°10 de la Ingeniería de Software: Si no es sencillo está mal hecho


El desarrollo de un software tiende a complicarse… a complicarse mucho. Se complica sacar el proyecto a tiempo, se complica las relaciones con el equipo de trabajo, con los proveedores o con los recursos. Debemos mantener esa complejidad bajo control, teniendo en la mente que todo lo que hagamos cumplir la regla "Si no es sencillo, está mal hecho".

La sencillez muchas veces se confunde. Sencillez no quiere decir fácil, es casi siempre lo contrario. Es difícil hacer las cosas sencillas. Casi siempre invertir en sencillez es un proceso costoso al principio y ventajoso al final del proyecto. El objetivo de esta regla es conseguir sistemas que estén guiados por la sencillez.

Para considerar un sistema sencillo debe cumplir las siguientes características:

  • Sencillo de entender.
  • Sencillo de explicar.
  • Sencillo de mantener.


Algunos consejos para conseguir sencillez son los siguientes:

  • Usa programación orienta a objetos: No veas un sistema como un flujo que va desde un punto ‘A’ a un punto ‘B’, sino como entidades que se relaciones entre ellas, e intercambian información.
  • Cada vez que uses una sentencia if, preguntante si no está organizando el código para evitar usar herencia (donde cada parte de if y el else debiera ser una clases hija con determinadas características).
  • Usa patrones de software: Son formas comprobadas de resolver determinados problemas, son extensamente conocidos, y son válidos tanto para incorporarlos en nuestros sistemas, como campo de estudio acerca de su sencillez.
  • Vuelvo a hacer: La primera vez que resolvemos un problema posiblemente no sea de la forma más sencilla posible, sin embargo ya tendremos una imagen clara del problema, si no estamos convenidos que la solución es lo suficientemente sencilla, es mejor rehacerla con la experiencia que ya tenemos. El problema de la complejidad es que crece como una bola de nieve, por eso es mejor rehacer partes de las que no estamos seguros de su sencillez.
  • Enfócate en hacer módulos que hagan muy pocas cosas pero que lo hagan muy bien.
  • Reúsa código: Casi todos los entornos y lenguajes de programación, como Java, Ruby o .NET, tienen repositorios de librerías, muchas excelentes, que resuelven muchas problemas comunes. Es bueno conocerlas y usarlas.
  • Pero no hagas tu código dependiente de librerías externas, encapsula apropiadamente las librerías para sea sencillo su reemplazo en caso que sea necesario.
  • Hablando de patrones, usa el patrón fascade (fachada), dicho patrón encapsula en funcionamiento de sistemas complicados, exponiéndolos con una interfaz mucha más sencilla. Este patrón es extremadamente útil cuando nos comunicamos con sistemas viejos, librerías en otros lenguajes o simplemente con elementos que no son sencillos, ni claros, pero no podemos modificarlos, ya sea porque no tenemos el código fuente, o porque se sale del ámbito de nuestro desarrollo. El patrón fascade lo expondrá para nosotros de una forma sencilla, y la complejidad del código a consumir no será contagiada a nuestro código.
  • Haz sistemas que no dependan de la implementación interna de otros sistemas (o módulos): Los sistemas se comunican por interfaces definidas, pero dichas interfaces debe ser independiente de sus respectivas implementaciones, es decir se debe poder cambiar la implementación sin afectar a las interfaces, ni a los sistemas con los que se consumen.