domingo, 14 de febrero de 2010

Consejos últiles para gestión proyectos de software

Si bien la gestión de proyectos de software no es una ciencia exacta, mas bien es un arte o una destreza que se mejora con la experiencia, existen algunos consejos útiles para no cometer errores que pueden causar el fracaso de un proyecto.

Quien haya gestionado algún proyecto de software sabe que debe hacer malabares entre múltiples temas de gestión, como las personas (el equipo de desarrollo, el cliente, etc), los tiempos, las entregas, las estimaciones erróneas y sus costos extra, la replanificación, etc. Para comenzar un proyecto de software con el pie derecho aquí dejo algunos consejos útiles:

Pruebas unitarias
Desde el inicio del proyecto se deben establecer las pruebas unitarias que se implementarán en la etapa de implementación, estableciendo por escrito cuales serán los casos de prueba y sus respectivos resultados esperados.
Esto sirve para tener un criterio claro de lo que se desea probar y para estimar el tamaño de las pruebas a implementar, este costo se debe considerar para la etapa de implementación, ya que la implementación no es solo para la funcionalidad del sistema que estemos creando, es también para las pruebas de dicho sistema.
Si no se planifican las pruebas unitarias desde el inicio, no se considerará su costo de implementación, y las estimaciones serán erradas. Por otro lado la calidad del software se verá afectada por no tener un criterio claro de pruebas a implementar.

Documentación
Desde el comienzo del proyecto se debe hacer énfasis en la documentación que será creada, ya que el software no es solo un conjunto de archivos fuente, el software es eso más la documentación. Sin una correcta planificación de la documentación a generar, el equipo de desarrollo no sabrá qué debe documentar y cómo. Es necesario definir estándares de documentación y capacitar al equipo de desarrollo en los mismo, además es útil hacer incapié en lo valioso que es contar con documentación correcta y completa, ya que muchas veces el equipo de desarrollo desestima la documentación y no la hace, o la hace incorrecta o incompleta.
También es útil fijar la documentación necesaria desde el inicio del proyecto, ya que nos llevará tiempo crear esa documentación, y ese tiempo debe ser contemplado en la planificación para no tener atrasos, replanificaciones innecesarias y costos extras.
Es bueno contar con plantillas para los documentos que deban ser creados, de forma de partir con una plantilla que siga los estándares de documentación que se fijen, ahorrando tiempo al equipo de desarrollo.

Comunicación
La poca o mala comunicación entre los miembros del equipo de desarrollo y con el cliente es la principal causa de fracaso en los proyectos de software. La comunicación es un tema muy sensible, ya que es necesario planificarlo y dedicarle tiempo.
La planificación de la comunicación implica determinar qué medios de comunicación se usarán, entre qué personas serán usados esos medios, y para qué motivo particular se usarán. Muchas veces no todas las personas debe tener contacto directo con otras personas, por ejemplo ¿qué pasa si el cliente le envía un email directamente a un miembro del equipo de testing cuando el cliente debe ser atendido solo por el responsable del proyecto?
Otras veces cuando se tienen grupos de trabajo por área, y cada grupo tiene varios integrantes, es bueno definir un encargado de la comunicación de cada grupo, así la comunicación entre los grupos se hace mediante dos personas, en lugar de juntar a los grupos completos, muchas veces desperdiciando horas de trabajo.
Los grupos no deben ser islas, el trabajo de cada grupo, por ejemplo desarrolladores, testers, analistas, etc, debe ser público para todos los miembros del equipo de desarrollo.
Las charlas de pasillo son muy importantes para la comunicación. Una situación distendida, por ejemplo ir a tomar café a la cocina, puede ser un pretexto excelente para comunicar a los miembros del equipo de desarrollo, para preguntar por el avance en su trabajo, qué problemas encontraron, etc.
Una llamada por teléfono o un email a cada miembro del equipo, nunca está de más.

Medir el avance
Medir el avance del proyecto no es una tarea sencilla, muchas veces nos encontramos en una situación donde le preguntamos a un miembro del equipo ¿cómo vienes con eso? y él nos responde: "venimos bien". Esa respuesta no nos dice nada, no nos dice "tenemos el 75% implementado", nos dice "venimos bien", esa es una respuesta que debemos evitar recibir. Para esto es necesario planificar desde el inicio del proyecto cuál será el mecanismo de medida del avance. Para esto primero es necesario determinar el alcance del proyecto, o sea todo lo que se va  a hacer y lo que no se va a hacer. La medida de avance más simple es la del 100%, o sea ir marcando las tareas terminadas, el problema de este enfoque es que no podemos hacer medidas intermedias del avance, o la tarea está en 0% o en 100%, nunca vemos un 25% o 50%. Para medir avances intermedios es bueno partir una tarea en pedazos y asignarle a cada pedazo un valor, si la tarea completa tiene valor 100, cada subtarea tendrá su propio valor, el cual se irá ganando a medida que se avance en cada una de ellas, este es el enfoque del "valor ganado".
Medir el avance de un proyecto nos permite saber si las estimaciones de tiempo que hicimos al principio son correctas, y nos permite detectar desvíos de esas estimaciones. Cuando se detectan desvíos es útil analizar las causas, y muchas veces se termina en una replanificación. Por ejemplo, si estimamos 10 horas para una tarea y vemos que ganamos el 50% del valor de la tarea en 7 horas, estimaremos que la tarea será finalizada con 14 horas de dedicación, o sea que o el equipo debe apurarse para terminar el 50% de la tarea en 3 horas o se le debe sacar tiempo a otra tarea posterior para no atrasar todo el proyecto.

lunes, 19 de octubre de 2009

Resolución de problemas según Steve jobs

Es muy interesante lo que dice el señor Jobs porque es lo que nos pasa en cada nuevo proyecto. Al principio pensamos en que sabemos de qué se trata y de que la solución en la que estamos pensando es el "santo grial" por lo simple y práctica, y al ahondar en el problema nos damos cuenta de que ni es el santo grial, ni de que el problema era tan simple, ni de que la solución era tan práctica. La moraleja es: primero, no quedarnos con las primeras ideas, segundo, profundizar en el análisis del problema antes de elegir una solución, tercero, la solución será tan complicada como el problema que estemos resolviendo.

"...when you start looking at a problem and it seems really simple with all these simple solutions, you don't really understand the complexity of the problem. And your solutions are way too oversimplified, and they don't work. Then you get into the problem, and you see it's really complicated. And then you come up with all these convoluted solutions. That's sort of the middle, and that's where most people stop, and the solutions tend to work for awhile. But the really great person will keep on going and find, sort of, the key, underlying principle of the problem. And come up with a beautiful elegant solution that works."

sábado, 21 de febrero de 2009

El proceso de desarrollo de software

Este es el primer artículo del blog y quería tratar el tema más básico de la ingeniería de software: ¿cómo se fabrica el software?. En este artículo se describe de forma general como es el proceso de desarrollo de software y abre las puertas para discutir en profundidad distintas técnicas que se pueden utilizar para facilitar el desarrollo.

Un proceso es una serie de pasos, que en este caso se necesitan ejecutar para generar un producto de software a partir de determinados recursos (humanos, tiempo, dinero, etc).

A grandes rasgos, un proceso de desarrollo de software consiste de las siguientes etapas:
  • Análisis
  • Diseño
  • Implementación
  • Pruebas
  • Producción
En las cuales, la salida de cada etapa es entrada de la siguiente. El producto generado como salida de una etapa puede tener distintas formas, por ejemplo pueden ser documentos, diagramas, código fuente, etc. El tiempo y otros recursos que se le asignan a cada etapa dependerá del tipo de proyecto que se esté realizando, tal vez un sistema con poca funcionalidad pero donde hay que resolver un problema complejo, las etapas de análisis y diseño sean las más largas, mientras que si se tiene mucha funcionalidad pero más simple, tal vez las etapas de implementación y pruebas sean más largas. Obviamente esto no se puede generalizar para todos los tipos distintos de proyectos.

Objetivos de cada etapa del proceso de desarrollo de software:

Analisis:
En esta etapa lo más importante es entender cual es el problema, no el cómo será resuelto. Esta idea es necesario tenerla bien clara, ya que en general los informáticos tendemos a plantear soluciones antes de comprender en profundidad los problemas o necesidades de nuestros clientes. La salida de esta etapa serán un conjunto de documentos que explican cual es el problema que se quiere resolver, es básicamente especificar lo que el cliente necesita o quiere, por eso una de las salidas más importantes de esta etapa es la "Especificación de requerimientos" (otros nombres a esto pueden ser "Análisis de requerimientos", "Definición de requerimientos"), también se utiliza la palabra "requisito" en lugar de "requerimiento". La idea es que esta especificación sea lo que el cliente pide pero en un lenguaje más formal para que no haya ambigüedades. La ambigüedad en las especificaciones son un factor de pérdida de tiempo en los proyectos, sobre todo cuando quienes leen estas especificaciones no están en contacto con quienes las crearon.

En la "Especificación de Requerimientos" se plasman las funcionalidades que deberá tener el sistema que se vaya a construir, esto es necesario para cuando se planteen las opciones de posibles soluciones a los problemas planteados (podríamos decir que: funcionalidad = problema a resolver). Aunque hablamos de funcionalidad, hay otra clase de requerimientos del cliente que pueden no tener que ver con la funcionalidad del sistema, por ejemplo: ante una consulta, el sistema no puede demorar más de 1 segundo en responder, a esto le llamamos "requerimientos no funcionales", por que no es sobre que el sistema ofrezca la funcionalidad de consulta, es sobre el tiempo que esta tarda, lo que se considera un requerimiento de "Tiempos de respuesta". Algunos ejemplos de requerimientos no funcionales pueden ser: "facilidad de uso", "seguridad", "estabilidad", etc.

En futuros artículos mostraremos las distintas formas de especificar requerimientos, y más sobre requerimientos no funcionales.

Diseño:
Si bien en la etapa anterior se especificó el "qué" quiero resolver, en la etapa de diseño se debe especificar el "cómo lo quiero resolver. Por eso hacíamos incapié en el no tentarse en plantear soluciones en la etapa de análisis, ya que eso es tarea de la etapa de diseño.

En esta etapa se toman las especificaciones de requerimientos producidas en la etapa anterior, a partir de las cuales se puede comenzar a plantear alternativas de cómo resolver cada problema planteado en dichas especificaciones. En general el abordaje de esta etapa se hace de lo más grande a lo más chico, del caso más general al caso más particular, y existen varias técnicas para realizarlo. Por suerte existen las "buenas prácticas" en diseño de software, y podríamos decir que muchas de las buenas soluciones están basadas en estas prácticas, también conocidas como "patrones de diseño", que no son más que el planteo de un problema genérico (que incluye varios problemas particulares, por eso lo podemos aplicar al problema que estemos resolviendo) y plantea una solución genérica, que es considerada la mejor solución para ese tipo de problema. Existe abundante literatura sobre patrones de diseño. Algunos de los sitios sobre patrones:
La salida esperada de esta etapa es un documento de diseño donde se especifiquen las soluciones de los problemas que se deben resolver, en un lenguaje formal/técnico, con diagramas UML para ayudar a la comprensión de las soluciones, por ejemplo:
En otros artículos discutiremos más sobre técnicas de diseño, patrones y UML.

Implementación:
En esta etapa el objeto más importante a construir es el código fuente de nuestra aplicación. Para esto, es necesario tener todos los problemas resueltos, o sea, el diseño de las funcionalidades que van a ser implementadas. Con un buen diseño, la tarea de implementación es mucho más fluida, y el implementador se ocupa solo de resolver problemas de implementación, y no otros problemas (por ejemplo: si se necesita una funcionalidad que no fue diseñana).

Existen muchas técnicas y buenas prácticas a seguir en la implementación, pero la elección de la técnica correcta dependerá de las características del proyecto y la tecnología con la que se trabaje. La tecnología (a veces) es un determinante de cómo se hacen las cosas. Además la tecnología va de la mano del tipo de proyecto que se está llevando a cabo, aunque muchas empresas utilizan la tecnología que conocen para implementar todos los proyectos que les llegan ( me viene a la mente un dicho "Para quien solo tiene un martillo, todos los problemas parecerán clavos").

En el futuro publicaré artículos sobre algunas técnicas y prácticas de implementación.


Pruebas:
En esta etapa sometemos a nuestro "Frankenstein" a las más duras pruebas, para ver si lo que construímos en la etapa anterior (el código fuente de nuestro sistema) funciona como debería. Cuando decimos "funciona como debería", el "como debería" está definido en la "especificación de requerimientos" que hicimos en la primer etapa. Es bueno que entre la etapa de Análisis y Diseño se cree un "Plan de pruebas" que diga lo que se va a probar y como, así cuando llegamos a la etapa de pruebas, éstas se guían mediante ese plan.

La salida de esta etapa es la lista de pruebas que se realizaron y su resultado: pasó la prueba / no pasó la prueba. De modo que para esos casos que no pasaron la prueba (por ejemplo, un resultado dió distinto al que se esperaba) deben ser corregidos y probados de nuevo. Este bucle de prueba-corrección-prueba se debería repetir hasta que todas las pruebas den como resultado "pasó la prueba". Así que deberíamos terminar con código fuente donde el 100% de nuestras pruebas fueron pasadas, pero ¿quiere decir esto que nuestro sistema no tiene nungún error?, la respuesta es simple: NO. Esto se debe a que puede haber una funcionalidad que no hayamos probado que contenga errores, o simplemente se nos olvidó probar un caso y justo un trozo de código, que tenía un error, no fue ejecutado.

En futuros artículos veremos algunas técnicas para realizar pruebas y para armar un plan de pruebas.

Producción:
Luego de que nuestro sistema pasa las pruebas, se pone en producción. Esto quiere decir que se pone a funcionar donde debería funcionar, por ejemplo si nuestro cliente es una empresa y desarrollamos un sistema contable, es muy probable que haya que instalar el sistema en la empresa, y comience así a ser utilizado por usuarios reales (los contadores). Pero esta etapa no es un simple "instalo el software y me voy", en general hay muchos problemas que resolver: la configuración del equipo de producción es distinta a la del equipo de desarrollo, falta instalar el software de base (sobre el que funciona el nuestro), faltan librerías, hay que entrenar a los usuarios, el sistema puede fallar, etc, etc, etc.

Luego de la puesta en producción viene el mantenimiento del software, que es la etapa más larga del "ciclo de vida del software", pero está fuera del proceso de desarrollo. En el mantenimiento se corrigen errores que se encuentren, se agrega funcionalidad con la cual el sistema no contaba y el cliente de pronto necesite, etc.

miércoles, 10 de diciembre de 2008

Bienvenid@s!

En breve comenzaremos a publicar artículos relacionados a la ingeniería de software y la concepción de sistemas de información, analizando diferentes procesos, técnicas, mecanismos y herramientas de la ingeniería de software que nos ayudarán a construir sistemas complejos de una forma ordenada, eficiente y eficaz.