Google

jueves, 28 de agosto de 2008

Conflicto de versiones

Es dificil para mi contar la cantidad de veces que he tenido que revertir los cambios en un codigo porque cometi un error o introduje un bug en el codigo. El control de versiones facilita muchisimo el trabajo cuando tengo se presenta esta situacion.

El control de versiones es la gestion de los cambios que se realizan sobre el codigo fuente escrito, facilitando la administracion de las distintas versiones de cada producto desarrollado, asi como las posibles especializaciones realizadas.

El control de versiones consta basicamente de un repositorio, el cual gestiona la informacion gestionada por el sistema. Este repositorio contiene el historial de las versiones de cada uno de los elementos gestionandos (cada archivo de codigo, imagenes, documentos, etc). Ademas cada desarrollador mantiene una copia local del repositorio, sobre la cual se hacen las modificaciones de los elementos. El desarrollador puede actualizar la ultima version del codigo o enviar los cambios que este haya realizado al repositorio.

Cuando se envia un cambio al repositorio, se crea un registro en el historial del mismo y se le asigna un numero de revision (el cual es incremental). El sistema de control de versiones automaticamente mezcla las diversas modificaciones para arrojar una ultima version.

Muchas veces cuando los grupos de trabajos son mas o menos grandes tienden a ocurrir "conflictos" en el codigo los cuales surgen porque el sistema de control de versiones no es capaz de fusionar los cambios enviados correctamente (por ejemplo dos desarrolladores modificaron la misma linea de codigo), por lo cual es importante tener tener unas convenciones sobre como y cuando enviar una nueva modificacion, de tal forma que se pueda reducir significativamente la aparicion de estos conflictos.

Lo ideal es hacer un check-in de los cambios cuando tenga una version del codigo estable. Una vez haya probado todos los cambios y este listo para ser enviado a un ambiente de produccion. Esto funciona bien cuando uno es el unico desarrollador o el grupo es bastante pequeno. Sin embargo cuando el equipo de desarrollo es grande lo mas adecuado es enviar una modificacion regularmente, eso si, el codigo debe ser probado antes para evitar el envio de codigo con errores. Y cada vez que se envia una modificacion se debe hacer una actualizacion del codigo, de tal manera de asegurarse de tener la misma version. De igual forma se debe comunicar al resto del equipo que se envio una nueva revision al repositorio de tal manera que el resto del equipo pueda tener en su copia local la ultima version de los codigos.

Esto no garantiza que los conflictos desaparezcan pero ayuda a que estos no aparezcan con tanta frecuencia. Particularmente en mi experiencia los conflictos aparecen bien porque no se envia los codigos regularmente (lo cual hace que mis cambios se envien tarde y otro desarrollador lo haya podido modificar) o bien porque no actualizo los codigos, con la consecuencia de que efectuo mis cambios sobre una version de codigo que no es la ultima.

jueves, 14 de agosto de 2008

El efecto mariposa

Si agita hoy, con su aleteo, el aire de Pekín, una mariposa puede modificar los sistemas climáticos de Nueva York el mes que viene

J. Gleick

El efecto mariposa es un concepto el cual indica que dadas unas condiciones iniciales, pequeñas variaciones sobre estas puede hacer que el sistema evolucione en formas totalmente diferentes. Es un concepto muy relacionado con la teoría del caos y aplicados a sistemas naturales de alta complejidad, como por ejemplo la meteorología. De hecho, fue el meteorologo Edward Lorenz quien en 1963 fue el primero en analizar este concepto en un trabajo de 1963. En dicho trabajo, Lorenz se percató que pequeñas diferencias en los datos de partida resultaban en grandes diferencias en los resultados.

Ahora bien, se puede hacer una simplificación o modificación de este concepto y aplicarlo a la informática. Los sistemas de información se definen como un conjunto de elementos que interactúan entre si con el fin de apoyar las actividades de una empresa o negocio. A pesar de que la definición parece ser simple, los sistemas informaticos son de alta complejidad, variando dicha complejidad de acuerdo con las caracteristicas de las actividaded que dicho sistema apoya.

Si se toma en cuenta tambien los requerimientos no funcionales, se debe hacer uso de librerias, APIs, servicios web, programación de diversas interfaces con otros sistemas (locales o remotos), interactuacción con la web, etc. se puede concluir que la complejidad de los sistemas de informacion aumenta significativamente, y por lo general, programar una aplicación de este tipo requiere de un equipo de programadores, analistas y arquitectos que puedan llevar a cabo el desarrollo de dicho sistema de la mejor forma posible.

Una de las caracteristicas del proceso de desarrollo de sistemas es lo cambiante de los requerimientos. Los requerimientos del sistema van cambiando a lo largo del proceso de desarrollo, bien sea porque se agregan, modifican o eliminan requerimientos. Pues bien, una modificación en los requerimientos implican cambios en los codigos ya funcionales (y probados). Estos cambios puede implicar la aparición de errores, haciendo que el sistema tenga comportamientos muchas veces inesperados. Como se puede ver, el concepto del efecto mariposa aplica perfectamente en el desarrollo de software.

La alta complejidad de los componentes de software y la necesidad de interacción entre estos (acoplamiento entre componentes) hace que sea muchas veces dificil cuantificar el impacto que un cambio puede tener en el comportamiento del sistema como tal. De alli es que cobra vital importancia la realización de pruebas sobre el codigo para garantizar que el software esta lo suficientemente estable para ser distribuido.

Se deben tomar precauciones al momento de efectuar cambios sobre un codigo funcional, un buen análisis del impacto de los cambios a realizar puede ayudar a reducir la cantidad de errores que puedan surgir por dicho cambio. Si a esto se le agrega la realización de pruebas exhaustivas (de regresión) para garantizar que el error ha sido corregido y no se hayan introducido nuevos errores.

Una buena práctica es programar una prueba que reproduzca el error en cuestión antes de corregirlo. Una vez programado y ejecutada la prueba se procede a corregir el error. Posteriormente se vuelve a ejecutar la prueba para verificar que el error ha sido corregido. Esta prueba entonces se agrega a un batch de pruebas que deben ejecutarse despues de cada cambio para garantizar que el error no vuelva a aparecer.

Una buena gerencia de sistemas debe entonces tener un mecanismo que permita identificar los errores que aparecen en el codigo, y un equipo de testers que se encargen del desarrollo de los casos de prueba y la ejecución de los mismos de forma tal que se pueda garantizar la calidad del sistema. En caso de no existir un equipo de testers esta labor recae sobre los programadores y estos van a enfocarse mas en la funcionalidad del sistema, dejando de lado la labor de escribir casos de prueba.

Si el equipo de desarrollo no posee un equipo de testers, entonces es altamente recomendable que cada cierto tiempo se detenga la labor de desarrollo para hacer testing, escribir los casos de prueba y ejecutarlos. Esto puede hacer que el desarrollo sea un poco mas lento pero a la larga resultará en un producto de mayor calidad, con menos errores y por lo tanto con un cliente satisfecho.

viernes, 9 de febrero de 2007

¿Cuándo está listo?

Cada vez que tenemos una entrevista con un cliente o usuario para levanta requerimientos, siempre surge esta pregunta, después de una sesión en la que el cliente te da todo un discurso explicandote que es lo que el sistema debe hacer, luego, con una sonrisa en la cara te pregunta, ¿Para cuándo está listo?

Esta pregunta no es fácil de responder, sobre todo porque uno como analista no ha terminado de digerir todos los requerimientos, y aunque lo que nos piden parece ser fácil, no lo es. No nos dejemos engañar por las apariencias.

Si uno dice está listo para tal fecha, perfectamente podemos estar poniendonos una soga en el cuello. Solo en los casos en que conocemos perfectamente lo que vamos a desarrollar es que podemos dar una estimación.

En el camino podemos encontrarnos con muchos obstáculos, y generalmente son cosas que no habiamos tomado en cuenta en el momento en que le dijimos con una seguridad a nuestro cliente, "esta listo para tal fecha". Ahora nos damos cuenta que el desarrollo se tomaba más tiempo del previsto.

Solo por poner un ejemplo sencillo, al intentar abrir un archivo, ¿Cuántas cosas pueden suceder que pueden provocar un error?. Vaya, ahora no resulta tan simple como llamar a la ventana de dialogo y listo.... una lista de cosas que pueden pasar son:


  • El archivo es un directorio
  • El archivo fue borrado mientras se seleccionaba el mismo y se presiona el botón Aceptar
  • Si el archivo esta en red, se pierde la conexión
  • El archivo está abierto y bloqueado
  • No se tiene permisos sobre la carpeta
  • ...

Esto es un ejemplo sencillo, imaginense lo que puede suceder en un caso más complejo...

Moraleja: Cuando elicitas los requerimientos solamente te están dando los casos de uso con el flujo normal de los eventos, y alguno que otro curso alterno. Hay que identificar todos los posibles flujos alternos que consigamos, priorizarlos y descartar los que no apliquen para el desarrollo. Una vez hecho esto es que podrás hacer una estimación de tiempo, y recuerda siempre poner un tiempo de holgura, porque Murphy siempre esta cerca ;)