lunes, 4 de octubre de 2010

¿Me cuentas la historia de caperucita roja?


Siempre hemos escuchado que los casos de uso deben de ser fáciles de leer, que deben de estar escritos en un lenguaje natural, y que nos narran historias que encapsulan una funcionalidad del sistema de una manera clara y comprensible. Nos encontramos con que resulta bastante fácil en ocasiones detectar los casos de uso críticos y los actores que interactúan con ellos, pero el verdadero problema viene al momento de escribir un caso de uso. La verdad nunca me explicaron a ciencia cierta cómo se debe de escribir un caso de uso, sabía como era su estructura, que debía tener pre-condiciones y post-condiciones, que debía tener un flujo principal el cual era el "happy path" y podía tener flujos alternos y excepciones por mencionar algunas cosas. El problema se me presentó al momento de redactar el caso de uso, no tenía ni la mínima idea de como iniciar. Me habían explicado que el flujo se debía describir como una conversación entre el actor y el sistema, que un actor siempre iniciaba la ejecución del caso de uso,etc. etc.

Me enfrentaba ante la difícil situación de redactar el primero de los flujos de una respetable lista de casos de uso pendientes. Me di cuenta que el escribir casos de uso no es tan fácil como la gente piensa. Me enfoqué en una de las principales recomendaciones de los casos de uso: debe ser comprensible para cualquier persona.
En un caso de uso un error común es pensar ya en el diseño de la interfaz del usuario y redactarlo como tal. Por ejemplo: 'El cliente hace click en el botón de seleccionar vuelo' o 'El sistema actualiza la ventana con un combobox que muestra la información de los vuelos disponibles'. Se supone que un caso de uso debe ser escrito en base a los requerimientos que el sistema debe satisfacer y por lo tanto, la interfaz no forma parte de dichos requerimientos, es mas bien una elección de diseño para después (normalmente al implementar un caso de uso aprobado). Otro error común es mencionar a la base de datos: 'El sistema guarda la información en la base de datos' o 'Se guardan los datos de la reservación en la tabla FLIGHTS'. Lo mas sano será mencionar: 'El sistema registra la reservación'.

Otra cosa muy importante a considerar es que un caso de uso debe describir un comportamiento, por lo tanto no podemos hacer 'todo' mediante casos de uso. Existen herramientas adecuadas para todo, no podríamos representar un requerimiento de desempeño mediante un caso de uso, o detallar estructuras de datos dentro de los casos de uso. Por ejemplo: ' El cliente introduce su nombre', El cliente introduce su apellido paterno' y así sucesivamente por cada campo que haga referencia a los datos del cliente. Lo mejor en este caso sería tener la estructura de datos detallada en un diagrama adecuado para ello y enunciar en el caso de uso algo así: 'El cliente proporciona sus datos generales'. Podríamos incluso hacer referencia como un anexo al documento de diseño que contiene los detalles de dicha estructura.

En las plantillas de casos de uso de Rational Rose me encontré con algo interesante: un caso de uso tiene una descripción breve, la cual nos resumirá la funcionalidad que se desea implementar, pero aún hay más... un caso de uso debe de ser breve, ya que los casos de uso demasiado largos y complicados serán más difíciles de entender. Por ejemplo, en el caso de uso 'reservar vuelo' de la aerolínea no deberíamos incluir los detalles de cómo se va a realizar el pago del boleto, lo mejor será crear un caso de uso específico para ello: 'pagar boleto'. Entonces utilizaremos el 'divide y vencerás' y el 'pequeño es mejor', y así enfocarnos a la verdadera funcionalidad del caso de uso que deseamos describir. No hay que olvidar que aunque sean casos de uso cortos debemos describir siempre el comportamiento para alcanzar la funcionalidad del caso de uso.

Tampoco debemos enfocarnos en casos de uso de bajo nivel, tales como 'establecer seguridad del sistema', o 'conectarse al servidor', ya que estos casos de uso son meramente técnicos y al usuario final no le interesan (recuerden la abstracción) y batallaría mucho para interpretarlos. Generalmente estos casos de uso se elaboran detalladamente por personas que a final de cuentas tendrán la responsabilidad de implementar esas funcionalidades y características en el sistema.

Como punto final, un caso de uso es una historia que describe una funcionalidad, siempre debemos especificar quien ejecuta que acción, y redactar de manera comprensible cada paso, sin ambigüedades, y de una manera simple y breve.... mmm creo que quedé como al principio, en fin. Mejor les dejo esto para pensar un rato... ¿Cual sería el diagrama de casos de uso del cuento de caperucita roja?



sábado, 2 de octubre de 2010

This is like a flashback!


Uno de mis temas favoritos es Flashback de Calvin Harris. El hecho de que a veces sentimos que una situación ya la habíamos vivido, o el hecho de tener un recuerdo muy borroso sobre algo que probablemente fue traumático, pero que no alcanzamos a recordar a detalle lo ocurrido. En un proyecto de software en muchas ocasiones ocurren estos 'flashbacks' y a continuación les daré algunos ejemplos.
El primer flashback lo asocio con la corrección de errores de software, cuantas veces nos hemos enfrentado a un error de codificación difícil de corregir (si los famosos bugs) y le invertimos bastante tiempo, incluso días en detectar donde está el error. Muchas veces al final nos encontramos que lo que está provocando semejante error es una insignificancia, la cual nos ha costado bastante esfuerzo en depuración y un buen dolor de cabeza. Una vez corregido el error nos olvidamos de él... hasta que tiempo después vuelve a ocurrir nuevamente, y ¡ahí es donde viene el flashback! nos encontramos con un error de software que no tiene una explicación lógica, algo que funcionaba y de la noche a la mañana dejó de hacerlo, y lo peor del caso, un error similar (bueno, igual pero en otro proyecto) a uno que ya había ocurrido anteriormente y ya le habíamos dado solución. Y nos ponemos a pensar... ¡si esto ya me había pasado!, ¡si recuerdo que batalle tres días para corregirlo!, ¿alguien recuerda cómo lo solucionamos la vez pasada? Y por mas que intentamos recordar no lo logramos, entonces viene nuevamente el arduo proceso de depuración hasta llegar nuevamente a la solución, si en el camino logramos recordar cual era evitaremos seguir desperdiciando tiempo. Pero, ¿cómo llegamos a este flashback? simple, por la mala costumbre de no documentar los errores de codificación, y sobre todo las soluciones que les dimos a dichos errores. Que fácil sería abrir un libro (en el mas modesto de los casos) y localizar el error que nos acaba de ocurrir nuevamente y al que en otras ocasiones ya habíamos dado solución. El flashback sería simplemente una reunión entre los miembros del equipo para si alguien vagamente recuerde de un caso similar y proceder a revisar nuestro 'libro de registro de posibles flashbacks'. Recuerdo un proyecto en el debido a su importancia tuvimos que invertir algo de tiempo para implementar un software para seguimiento de errores, lo llamamos 'Bug Tracker' y nos fue de mucha utilidad. Si no tenemos el tiempo para diseñar un software para registro de errores bastará con llevar un registro manual de los errores en una libreta.
El segundo flashback que voy a mencionar es el que se encuentra relacionado al proceso de desarrollo de un proyecto de software, y se presenta cuando cometemos un error durante el mismo, ya sea administrativo o de ingeniería. Muchas veces nos encontramos con actividades que en vez de beneficiar al desarrollo del proceso lo complican, ya sea burocracia, detalles excesivos en el diseño, una mala planeación, omisión de tareas críticas, etc. y simplemente las vamos resolviendo 'al vuelo' y con bastantes presiones de tiempo. Una vez finalizado el proyecto nos apresuramos a darle cierre y olvidarnos para siempre de él. Mal hecho, el no realizar una reunión post-mortem del proyectos en donde documentemos las lecciones aprendidas provocará que mas adelante se puedan repetir los mismos problemas en otros proyectos, y al igual que en el primero consumirá tiempo, dinero y esfuerzo (siempre quise usar esa frase, es todo un clásico). Por lo tanto para evitar un 'esto ya lo había vivido' lo mejor será documentar nuestros éxitos y nuestros fracasos para cada proyecto de software y sobre todo ir retroalimentando nuestro proceso de desarrollo de software con el fin de evitar repetir los mismos problemas en un futuro (y tener otro flashback).
El tercer flashback del que les quiero hablar es uno que siempre debe estar presente en nuestros proyectos, las pruebas de regresión. Este flashback consiste en repetir con cada integración todas las pruebas realizadas sobre dicho software (si... TODAS). De ahí la importancia de diseñar nuestros casos de prueba y utilizar herramientas automatizadas para su ejecución. Pero ¿porqué es necesario probar todo nuevamente?, pues simple, para garantizar que todo lo que ya funcionaba siga funcionando. La integración es un proceso delicado, puede ser que entre las distintas configuraciones de software existentes se introduzca y propague un error, y podemos quizás dar por hecho de que una funcionalidad previamente probada siga cumpliendo con su cometido, y no probarla nuevamente, hasta el momento en que llegue a manos del usuario y entonces surja el error, y nuestra respuesta será... ¡si eso ya funcionaba! (vaya 2 flashbacks a la vez).
Como siempre, tomen mis opiniones para crear un caos de su proyecto, ya que nuestro objetivo del blog es desadministrar proyectos (creo que tuve un flashback).

viernes, 1 de octubre de 2010

Caminito de la escuela

Hace unos momentos me encontraba fuera de una escuela primaria platicando con una persona, eran las 7:40 A.M. y todo parecía muy tranquilo, poco tráfico, escasos alumnos ingresando al plantel, los padres de familia y alumnos se miraban muy contentos, relajados y 'platicadores'. Es mas, el oficial de tránsito que vigila que se respete el cruce de los alumnos ni siquiera tenía que intervenir, ya que los conductores cordialmente cedían el paso. Así pasaron 10 minutos más y aún todo se miraba tranquilo. La plática se alargó y por un momento hasta dudé de que hubiera actividades en dicho plantel educativo. De repente todo dio un cambio radical, a las 7:55 se desató el caos, por una parte veía llegar a los padres de familia muy tranquilos con sus hijos y sus caritas de desesperación, y por otra lo contrario, los padres muy molestos y regañando a sus hijos de que se apurasen que ya era muy tarde. El tráfico para que les cuento, había una fila inmensa de carros, todo mundo tocando el claxon y ahora si nuestro oficial de tránsito ni buscaba que hacer ya que nadie cedía el paso a los estudiantes. Por cierto, ya me ha tocado con anterioridad ver que entre esa fila de carros hay un 'profesor' que imparte clases en dicha escuela pero por las tardes, y en la mañana imparte clases en una escuela cercana, pues me ha tocado ver como este profesor casi le pasa encima a los alumnos, como toca como desesperado el claxon, y no respeta en lo mínimo la cortesía de ceder el paso, claro me imagino que entra a las 8:00 a su trabajo. Bueno la historia no acaba ahí, a las 8:05 aún seguía el tráfico, ya en menor afluencia, uno que otro alumno llegaba, algunos con prisas, algunos con toda la tranquilidad del mundo, digo, para que apurarse si ya de todas formas llegaste tarde. Echo un vistazo por dentro de la escuela y veo la formación de alumnos y a un grupo de niños separados de los demás notablemente nerviosos y mirando hacía el suelo mientras eran reprendidos por el director... eran los retardados. ¿cómo llegaron allí?, ¿fue por culpa directa de ellos?, ¿no saben que tienen que llegar a la hora indicada? ¿pudieron haber evitado el llegar tarde? ¿dependía de ellos? ¿se levantaron tarde? ¿no tenían listas sus cosas? ¿se tardan mucho en sus actividades para salir a la escuela? ¿hacen cosas que no deberían como ver TV por las mañanas? y me pregunto a cuantos de ellos les habrá dado tiempo de desayunar.

Al menos en este caso el castigo por llegar tarde fue sólo eso, que todos te vean que llegaste tarde y que el director los regañe en público. Pero en el caso de un proyecto de software... ¿cual es el castigo? ¿cómo evitar llegar tarde? después de todo para que preocuparnos por la fecha de entrega si buscamos desadministrar y que nuestro proyecto sea un fracaso costoso.

Por cierto, al ver que eran las 8:07 me despedí con un 'ya se me hizo tarde' y salí volando a mi oficina faltando a no se cuantas leyes de tránsito.

jueves, 30 de septiembre de 2010

Especificando con ambigüedad

En múltiples ocasiones he escuchado el término 'ambigüedad', que hay que evitarla, que no debemos incurrir en ella, que los requerimientos son ambiguos etc. etc. ¿Alguien se ha planteado qué significa este enemigo de la humanidad (y de los proyectos) llamado ambigüedad? Pues simplemente significa que 'algo' se puede interpretar de 'distintas' maneras. Y eso ¿en qué nos afecta? Supongamos que un conjunto de requerimientos es documentado por el equipo de análisis, la forma en que ellos hayan descrito al requerimiento dará lugar a una buena implementación de dicha especificación en el producto. La lista de requerimientos pasará por varias manos, y si existen requerimientos ambiguos, cada quien los entenderá a su manera, cada quien le dará un significado diferente al requerimiento (con eso de que cada cabeza es un mundo) y al final tendremos que diferentes miembros del equipo entendieron el mismo requerimiento de diferentes formas.
Si un requerimiento no se encuentra debidamente detallado (empezamos con imprecisiones), entonces producirá ambigüedad. Pero los requerimientos pueden ser ambiguos incluso por la forma en que están redactados, entonces tenemos que cuidar hasta el lenguaje con el que describimos los requerimientos. El decir 'el sistema debe ser flexible' realmente carece de significado, más bien deberíamos indicar las formas en que el sistema podría cambiar para responder a los cambios del entorno o del negocio. O en ocasiones he leído requerimientos que dicen: 'el sistema no debe' (negatividad y ambigüedad pura), no no y no (hablando de negatividad) los requerimientos deben de ser positivos y enunciar aquellas acciones que el sistema debe realizar. Otro ejemplo de un requerimiento ambiguo es 'el sistema debe acelerar la velocidad del proceso de negocio x', pensemos... como diantres vamos a saber cuales son los valores mínimos aceptables de velocidad para el 'proceso de negocio x' si no lo tenemos especificado. Estás lagunas de ambigüedad forzaran en la mayoría de los casos a que el desarrollador interprete e implemente a su juicio un requerimiento, algo así como 'rellenar los espacios en blanco'.
Pero claro, se nos está olvidando un rol que rara vez existe en un proyecto y nos podría auxiliar en el combate de la ambigüedad... si adivinaron, el arquitecto de software. Esta persona tiene la dura tarea de enfrentarse a las ambigüedades de los requerimientos y rellenar aquellos vacíos. Esta persona bien nos podría ahorrar el hecho de que cada desarrollador interprete a su manera un mismo requerimiento (pausa... el mismo requerimiento podría estar implementado mas de una sola vez de distintas maneras en un mismo proyecto). Y bien, esta persona podría ahorrarnos bastante tiempo en el proyecto, ya que un requerimiento ambiguo se podría convertir en tiempo desperdiciado de desarrollo, ya que podríamos haber implementado una solución acertada para un problema equivocado. Y si nos vamos mas allá del desarrollo... pongamos un ejemplo de un tester, leyendo e interpretando un requerimiento ambiguo a su manera, el tester realizará una suposición de lo que 'debe hacer' dicho requerimiento, la cual es muy probable que sea una interpretación distinta a la del desarrollador que lo implementó, y al final hasta podrían llegar a un interminable debate sobre de 'quien tiene la razón'.
Lo anterior no significa que debamos leer los requerimientos como desquiciados en busca de ambigüedades, mas bien significa que debemos de estar conscientes del problema que estos representan, tratar de llevar un buen control de cambios de los requerimientos, diseñar nuestros casos de pruebas (regresando al ejemplo de 'el sistema debe acelerar la velocidad del proceso de negocio x', no hay manera de probar si el sistema cumple con este requerimiento, por lo tanto al intentar diseñar un caso de prueba para este requerimiento se descubrirá la ambigüedad), y sobre todo mantener informados a todo el equipo acerca de cuales son los requerimientos.

Corregir una ambigüedad en una etapa tardía del proyecto será costoso. Pero pues para nuestro objetivo del blog que es desadministrar proyectos, las ambigüedades son aceptables siempre y cuando no se excedan del rango permitido de manera razonable y suficiente (nunca había visto tanta ambigüedad en una sola frase), total... que más puede pasar si una simple línea que detalla un requerimiento se puede interpretar de distintas maneras (sarcasmo puro).

¡Complica lo complicado!


Imaginemos el siguiente escenario: Un arquitecto de software presentando su flamante y enmarañado diseño ante el jefe de una empresa, el cual se queda impactado al ver tantos símbolos en tan poco espacio, definitivamente nunca había visto un diseño tan 'completo', 'novedoso' y 'admirable'. Es más, desea que dicho modelo se presente ante el cliente en la reunión de avance del proyecto de esta semana y exclama exaltado: 'Definitivamente los clientes quedarán muy impresionados al ver este diseño, y así entenderán lo complicado de nuestro trabajo. Felicidades Arquitecto'.
¿Ya se lo imaginaron? pues ahora analicemos como este comportamiento nos ayuda a lograr nuestro objetivo del blog. Ciertamente en muchas ocasiones nos complicamos demasiado la vida, somos adictos a la complejidad, lo complejo nos atrae, ver algo complejo nos seduce y nos hace pensar 'eso debe ser muy bueno, porque se ve bastante complejo'.
El manejar un automóvil es algo muy sencillo, la abstracción es muy adecuada a la naturaleza humana, no nos preocupamos de como funciona, simplemente lo utilizamos (por ello ruego que nunca me falle el carro ya que no sabría que hacer, a duras penas sé como llenar el tanque de gasolina y ni siquiera sé calibrar una llanta). En un software el nivel de abstracción debe ser de la misma manera, el cliente debería operar la interfaz de usuario de una manera natural, sin preocuparse de como fue construida, pero regresando al tema, el hecho de tener un diseño exageradamente complejo, aparte de apantallar al cliente (y a uno que otro jefe) va a provocar muchos problemas en el desarrollo del software y verdaderos dolores de cabeza a lo largo del proyecto.
Un diseño demasiado complejo nos va a retrasar en la mayoría de nuestras actividades, inclusive en aquellas de planeación y control, ya que nos va a orillar a las prisas y posiblemente dejemos de realizar ciertas actividades (pruebas, SQA por mencionar algunas) para poder cumplir con la fecha de entrega y conforme al diseño. Por naturaleza todas las decisiones de diseño son ya de por si complejas, existen demasiadas cosas que debemos considerar y debemos de tener en cuenta que estas decisiones afectaran a todo el proyecto (y al costo del mismo). La misma arquitectura puede incluso disminuir o incrementar los riesgos de un proyecto, es por ello que la elección de buenas decisiones es vital. Un diseño demasiado complejo se verá reflejado en un esfuerzo mayor de desarrollo, y por lo tanto todo lo que conlleva: pruebas, integración, mantenimiento, etc. El costo ni se diga, veremos como se eleva rápidamente hacia las fases finales del proyecto (al igual que el riesgo).
El tener buenas decisiones de diseño nos traerán beneficios, y las malas decisiones consecuencias. Entonces es un hecho que tenemos que administrar la complejidad, y sobre todo, definir nuestras abstracciones adecuadamente, ya que en una aplicación a gran escala la complejidad se eleva exponencialmente y se convierte en un factor crítico para el éxito de nuestro proyecto.
Lo anterior me hace pensar en la verdadera importancia y responsabilidad de un arquitecto de software y la importancia de las decisiones de diseño que va tomando a lo largo del proyecto, ya que deberá estar administrando la complejidad durante todo el ciclo de vida. Y también me hace pensar en la responsabilidad que tiene el administrador del proyecto de conocer y estar consciente de la complejidad del diseño, ya que esta influirá directamente sobre los recursos que se necesitaran durante el proyecto, tales como personas, tiempo y presupuesto.
Cabe recalcar la importancia de la abstracción, ya que esta nos llevará a tener interfaces más simples, y la falta de la misma nos llevará a una complejidad excesiva del sistema y muy posiblemente al fracaso de nuestro proyecto, por lo tanto... ¡Vamos a complicar lo complicado!

miércoles, 29 de septiembre de 2010

¿Desde cuando los patos le tiran a las escopetas?

Hola, el día de hoy les traigo un buen consejo para ser un buen desadministrador. Si deseas que tu proyecto sea todo un fracaso te será de gran ayuda el sentirte el 'Jefe de jefes' y 'llevar el puesto en alto' a donde vayas. Deberás creer que tu opinión es la única que vale, y que nadie más de tu equipo de trabajo merece ser escuchado, es más, ni siquiera mirarte a los ojos.

Cuantos de nosotros hemos visto o tenido este raro comportamiento, en el cual nuestro punto de vista es sagrado e intocable, totalmente exento de críticas en pocas palabras, la ley, sin contradicciones. ¿Y que pasa con nuestro equipo de trabajo? ¿No pueden opinar? ¡Claro que pueden! cuantas veces hemos descartado ideas brillantes sin siquiera haberlas escuchado, o peor aún, cuantas veces las hemos escuchado y pensado que son buenas ideas, pero simplemente el 'orgullo' nos hace rechazarlas al momento.

Sin duda uno de los puntos más importantes en un proyecto son las relaciones interpersonales y la comunicación efectiva a lo largo de toda la organización. El tener un equipo de trabajo al cual le inspires confianza, y se sientan con la libertad de expresar sus opiniones por muy diferentes que estas sean de las tuyas ayudará a impulsar el éxito de un proyecto. No debemos frenar la creatividad del equipo, esto sin embargo no significa que siempre sea un buen momento para incorporar dichas ideas al proyecto, pero las podríamos incorporar más adelante y el equipo quedará con un buen sabor de boca por haber aportado un granito de arena extra al proyecto.

He conocido líderes de proyectos con una gran habilidad de manejo de personal, ¡vaya forma de tratar al equipo de trabajo! todos lo respetan por sus habilidades, por su conocimiento, y confían plenamente en los planes y objetivos que establece conforme avanza el proyecto. Eso me hace reflexionar que el respeto se gana, no se impone.

Pero creo que me estoy desviando del tema central de este blog, si lo que buscamos es desadministrar el proyecto, la próxima vez que alguien del equipo nos contradiga basta con decirle: "¿Desde cuando los patos le tiran a las escopetas?"