archivo

Archivo de la etiqueta: requisitos funcionales

En el desarrollo de software los extremos no son buenos. A veces se le da al programador un diseño tan detallado que básicamente lo que hace es traducirlo a código fuente en el contexto del framework con el que trabaja. Otras veces no existe diseño o bien las especificaciones no son completas y son los programadores solos o en colaboración con analistas los que rellenan los huecos.

Desde mi punto de vista es importante que el programador sepa lo que tiene que hacer, es decir, que las especificaciones las conozca y que también conozca los objetivos no funcionales pero sobre esa base es necesario darle libertad para que dentro de esas restricciones pueda realizar la solución que resulta más conveniente.

Es necesario tener en cuenta que si se realiza un desarrollo en base a un análisis y/o diseño que se realizó hace tiempo es muy posible que quien lo hiciera no tuviera en cuenta determinados factores que sí son conocidos en el presente y no resulta lógico no echar cuenta a una solución mejor por tener en cuenta un trabajo que se efectuó sin conocer determinados tipos de detalles.

También es importante precisar que ese margen de maniobra permite que el programador dentro de esas restricciones pueda expresar su creatividad (algo que todos llevamos dentro) y realice su trabajo más motivado, algo que todos sabemos termina produciendo resultados de mayor calidad.

Como siempre es importante evaluar el contexto. No hay verdades absolutas. Es posible que en determinadas situaciones tener un nivel de detalle importante resulta fundamental, por ejemplo, cuando se externaliza a otro equipo de trabajo las tareas propias de programación de un desarrollo (o parte de él), aunque incluso en estos casos hay que tener en cuenta que la comunicación seguirá siendo necesaria (y se debe considerar un problema si no la hay) porque siempre quedará algún detalle que no se ha especificado al 100%.

Se tiene en mente que un producto equivocado es aquel que no cumple las especificaciones funcionales del área usuaria, sin embargo, podemos encontrarnos con aplicaciones que satisfaciendo eso son productos equivocados. ¿Qué cómo es posible eso? Pues todos esos sistemas que son inmanejables (mala experiencia de usuario y/o baja productividad de uso), que tienen infinidad de errores (o los suficientes para hacerlo insufrible)o que tienen otro tipo de deficiencias no funcionales relevantes.

Por eso cuando se esté definiendo un producto no solo se debe hacer desde el punto de vista funcional también hay que tener en cuenta y mucho la visión no funcional. La suma de una cosa y la otra son las expectativas del usuario (si bien hay cierta parte no funcional que no valorará, al menos, de primera mano) y todos sabemos que lo más complicado de capturar.

Me gusta mucho la siguiente cita de Mike Cohn porque refleja un riesgo real existente en todos los proyectos de desarrollo de software y que no se valora como se debiera (tal vez por el hecho de que se piensa de que siempre se va a acertar con el resultado): “El error más crítico en la mayoría de los proyectos es el riesgo de desarrollar el producto equivocado. Pese a eso este riesgo es prácticamente ignorado en la mayoría de los proyectos”.

Precisamente porque ese riesgo existe es otra de las razones que empujan a pensar que en la mayoría de los proyectos el enfoque más adecuado para su desarrollo es el iterativo e incremental a ser posible con ciclos cortos y visto desde una perspectiva ágil.

Las expectativas del usuario y la calidad del software están muy por encima de las especificaciones funcionales, por eso que el producto final termine satisfaciendo el catálogo de requisitos funcionales (por mucho que se hayan refinado) no asegura ni el éxito del producto ni su calidad final.

Si solo pensamos en requisitos funcionales estamos limitando nuestra visión sobre lo que debe ser el producto final. Cada uno puede tener una definición de lo que considera calidad del software, en la mía no es condición suficiente la verificación de los requisitos funcionales (y probablemente muchos de vosotros estéis de acuerdo conmigo). Son importantes, no digo lo contrario, pero no es lo único.

Por un lado tenemos las expectativas que, si bien podría englobar los aspectos funcionales, contiene ingredientes adicionales como son la experiencia de usuario y la productividad en el uso de la herramienta (muy ligado a la anterior).

Y por otros los requisitos no funcionales (algunos de ellos serán detectados de manera temprana por los usuarios y podrían afectar a las expectativas del usuario sobre el producto), como por ejemplo, la mantenibilidad (deuda técnica), la disponibilidad, el rendimiento, los recursos que requiere y consume, etc…

Pocas reflexiones pueden describir mejor en pocas palabras la realidad evolutiva del software que la realizó Jeff Sutherland, creador junto a Ken Schwaber de la metodología Scrum: “Los usuarios no saben lo que quieren hasta que lo ven y siempre se reservan el derecho a cambiar de opinión”.

Es cierto que hay técnicas que ayudan a afinar en los requisitos, como son los prototipos, pero por muy bien que estén hechos, hasta que no lo utilizan (voy más allá del hecho de que lo vean) no terminan de dar las indicaciones necesarias para que el producto satisfaga sus expectativas.

Esto nos lleva a un enfoque iterativo incremental en el desarrollo de software, como modelo de referencia para ajustarnos a esta realidad.

Es la evolución natural de los desarrolladores que han trabajado con el ciclo de vida clásico o en cascada y de las organizaciones que han venido utilizando esa metodología.

Está comprobado que la cascada no produce buenos resultados ya que se ajusta a un modelo ideal de desarrollo de software en el cual las especificaciones de los usuarios son las adecuadas (para lo cual el usuario tiene que tener perfectamente claro qué es lo que quiere y cómo lo quiere ver plasmado en un sistema de información y, por otro, que el equipo de proyecto capte de la mejor manera posible esas expectativas) y que no cambian durante el proceso de diseño y construcción.

El desarrollo de software tiene una naturaleza adaptativa, evolutiva, no predictiva y por tanto el ciclo de vida en cascada no se ajusta a ese patrón.

Por ese motivo, el primer paso que suelen dar los desarrolladores y organizaciones habituados a ese esquema de desarrollo es dividirlo en fases y convertirlos en desarrollos incrementales. El siguiente paso que se suele dar es revisar al final de cada fase las desviaciones respecto a las expectativas, de manera que se tenga en cuenta para la siguiente fase la cual además de funcionalidades nuevas tendrá los desarrollos necesarios para realizar los ajustes de la fase anterior, pasándose de esta forma a un ciclo de vida iterativo incremental.

Una vez llegado a ese punto el salto a una metodología ágil es cuestión de tiempo.

Los requisitos funcionales y no funcionales de un sistema de información determinan el mapa inicial de lo que los usuarios esperan del sistema. Se trata de una predicción sobre lo que que quieren y que después tendrán que constrastar con el producto final.

Lo normal es que exista una diferencia entre una versión de un producto y lo que se esperaba de ella, por lo que después son necesarios mecanismos de ajustes que disminuyan esa distancia a unos umbrales razonables o que la eliminen. Lo ideal es que esa diferencia sea la menor posible y los analistas funcionales y orgánicos y los responsables de codificar el proyecto intenten que así sea, sin embargo los proyectos de desarrollo de software están sometidos a muchos factores que afectan negativamente a ese objetivo.

En cualquier caso, los requisitos representan necesidades y expectativas de los usuarios y es necesario, por tanto, conocerlos y tenerlos en cuenta como referencia en el desarrollo del producto software.

Por tanto, este área de proceso requiere que los requisitos estén perfectamente identificados y, además, sean conocidos y entendidos por todos los implicados en el proyecto (equipo de proyecto, usuarios, responsable técnicos del cliente, etc…).

Otro de los requerimientos de este área es que se tenga control sobre el cambio en los requisitos, para ello es necesario que solo un grupo reducido de personas tengan la capacidad de decidir en ese sentido.

Esto no quiere decir que cualquier usuario no pueda proponer cambios, antes al contrario, cualquier aportación debe ser acogida de forma positiva, el matiz en este caso, es que esas propuestas deben ser analizadas por unos pocos (que se entienden que son designados como expertos del proceso o procesos que se informatizan) y que con el asesoramiento de los técnicos software (sería lo más recomendable) toman la decisión sobre qué cambios realizar, cuáles no y en definitiva, cuáles son las prioridades.

Ante una decisión de cambio en los requisitos, este área de proceso tiene el requerimiento de que el resto de artefactos/entregables del proyecto se mantengan consistentes.

Por este motivo hay que tener mucho cuidado a la hora de definir los entregables documentales de un proyecto, ya que cuántos más y más complejos sean, mayor será el esfuerzo necesario para ponerlos consistentes. Es importante apoyarse en herramientas CASE para facilitar la consecución de este objetivo.

Otro requerimiento es la trazabilidad bidireccional y sobre esto habría mucho que hablar. Si se toma al pie de la letra quiere decir que debería poder conocer todos los componentes de ingeniería del software y del producto software (a nivel de clase) asociados a un requisito y también en el sentido contrario, es decir, que partir de una clase se sepa a qué requisito o requisitos puede afectar un cambio en la misma. El objetivo de esto es poder realizar un análisis de impacto y servir también de soporte para la detección de inconsistencias entre los requisitos y los productos derivados del proyecto (incluido el propio sistema de información).

Sin embargo, esta trazabilidad bidireccional resulta costosa de conseguir y no resultaría aconsejable su aplicación en determinados tipos de proyectos (se estaría matando moscas a cañonazos) y en otros, llegar a nivel de clase en el código no aportaría mucho ya que la organización en capas, de las clases, etc… viene condicionada por el generador de código utilizado y el framework.

Para poder respectar en lo posible este objetivo, es importante definir un nivel de entregables documentales acordes a la naturaleza del proyecto (maś entregables, más complejidad, así que hay que tener cuidado con esto) y tener un conocimiento del framework de desarrollo y de la arquitectura de la aplicación, de manera que se sepa de manera rápida donde hay que mirar para conocer el impacto de la modificación de determinados requisitos (lo que se hace es mirar de más arriba la codificación de la aplicación y no entrar a un detalle a nivel de clase). También resulta fundamental un código lo más claro y limpio posible.

Sobre la trazabilidad lo importante, entiendo que debe ser quedarse con el espíritu de la misma y tener unos procedimientos en el proyecto que permitan hacer un análisis de impacto y análisis de consistencia en un tiempo razonable. Hay que recordar que CMMI establece un modelo de referencia, determina el qué pero no el cómo.

Soy de la opinión de que en el desarrollo de software los requisitos funcionales y de interfaz de usuario deben quedar resueltos antes de empezar a codificar, sin embargo hay ciertos aspectos que no cobran su verdadera forma hasta que uno se enfrenta a su programación, hasta que se siente el código.

Sentir el código, es una cita que leí a Alex Bergonzini en su Twitter y desde luego no le falta razón ya que en la programación se enfoca el problema.

Martin Fowler también le da importancia a sentir el código en su siguiente reflexión (traducción libre): “Cuando te sientas a escribir código, aprendes cosas a las que no puedes llegar en el proceso de modelado… ya que hay un proceso de feedback al que solo puedes llegar desde la ejecución de determinadas funcionalidades y viendo como funcionan”.

El desarrollo de software es adaptativo y todo no se puede prever, a veces hay que experimentar hasta encontrar una solución satisfactoria para el usuario, eso es totalmente compatible con los desarrollos ágiles. Ahora bien, el hecho de que los principios ágiles indiquen que no hay que elevar ninguna funcionalidad a definitiva no quiere decir que todo deba ser consecuencia de la experimentación, porque construir y tirar módulos software además de ser caro puede provocar una desmotivación importante en el equipo de proyecto.

Otra confusión muy típica entre términos la tenemos entre el mantenimiento evolutivo y el mantenimiento perfectivo.

Cuando hablamos de mantenimiento evolutivo lo hacemos en base a unas modificaciones en los requisitos que sirvieron de base para la construcción del sistema o la incorporación de otros nuevos (ampliación del sistema) independientemente del tamaño de estos cambios con respecto al conjunto de la aplicación.

En el caso del mantenimiento perfectivo lo que se pretende es sacar brillo a lo que ya está hecho (mejorar la calidad), es decir, refactorizar alguna parte de la aplicación para hacerla más mantenible o más eficiente, hacer modificaciones en el modelo de datos (y en consecuencia en la aplicación) con los mismos objetivos, reestructurar alguna pantalla o conjunto de pantallas para que los usuarios puedan realizar sus tareas de una manera más efectiva, etc…

Nos centramos mucho en los requisitos funcionales y en cierto modo es lógico que así sea, ya que si una aplicación no cumple el propósito y expectativas que se tiene sobre la misma de nada vale que la calidad del producto y del desarrollo sea impecable.

Parto de la base de que no es nada fácil conseguir lo que el usuario o el cliente busca, entre otras cosas porque es complicado que ambos tengan del todo claro lo que quieren (sí lo pueden tener en la cabeza, pero una aplicación son muchos detalles y es difícil que tengan en cuenta todos) y también que los analistas entiendan e interpreten a la perfección lo que les están contando.

Precisamente porque el desarrollo de un producto tiene asociado inherentemente tareas de mantenimiento correctivo y evolutivo es necesario ir más allá de que el producto funcione, entendiendo que el diseño y codificación realizados deben hacerse pensando en que habrá que modificar la aplicación, para ello desde un primer momento hay que pensar también en la calidad de la aplicación desde el punto de vista de la arquitectura, diseño y construcción.

No tener en cuenta estos detalles provocarán en el sistema desarrollado una deuda técnica que se arrastrará en los mantenimientos y tenderá a empeorar salvo que se decida atajar, ya que el software tiende a deteriorarse con los mantenimientos, siendo este deterioro muy sensible en aquellos casos donde el producto no ha tenido una ejecución buena desde el punto de vista de la calidad del código.

Sonar permite ver de manera muy sencillo lo que esconden las aplicaciones debajo de la alfombra a través de las diferentes métricas que permite obtener. Es cierto que solo son un conjunto de métricas y que hay que saber interpretarlas de manera individual, colectiva y en el contexto de cada aplicación, pero permiten dar una visión objetiva y externa tanto a clientes como a proveedores, ya que no hay trampa ni cartón si ambas partes conocen el juego de métricas y reglas que se le van a pasar al código.

Desde mi punto de vista Sonar es una herramienta de implantación obligatoria en los departamentos de desarrollo y/o de calidad del software, ya que además de permitir detectar aspectos del desarrollo que generan deuda técnica, permiten determinar la complejidad (y por tanto tiempo y esfuerzo) de los mantenimientos y puede ser utilizada para establecer determinados acuerdos de niveles de servicio en cuanto al software que se entrega.

Hace un tiempo tuve la oportunidad de leer en un foro el debate suscitado entre un par de personas en el que una hacía referencia a la calidad de la documentación que le generaba un determinado proveedor y otra hacía mención a la calidad del código que le generaba otro proveedor. Por lo visto ambos conocían a los proveedores y precisamente lo que destacaban de uno era lo que le faltaba al otro.

¿Cuál es mi opinión al respecto? Pues que si bien es valorable que un proveedor entregue documentación de calidad y otro entregue código de calidad, ambos tendrían mucho que aprender de un proveedor que entregue una buena documentación (aunque no sea excelente) y además un buen código (aunque tampoco sea excelente).

Entiéndase por calidad no sólo el continente, sino el contenido (sobre todo el contenido), porque se puede entregar una documentación excepcional que para nada refleje en su conjunto lo que el usuario desea y se puede entregar un código que saque roce el diez en la realización de las pruebas unitarias y en una revisión estática de código, pero que después no verifique el conjunto de requisitos funcionales.

No obstante, hay un aspecto que es importante señalar: una documentación de calidad siempre es un buen punto de partida, una mala (o nula) documentación supone siempre un riesgo muy importante para el proyecto.