martes, 20 de septiembre de 2011

Ingeniería de software: el nuevo concepto.

Habitualmente se piensa en la "Ingeniería de Software" como "Ese conjunto de cosas que no sirve para nada, pero que hay que hacer". Yo soy el primero.

Eso se debe a una única razón: Está mal planteada.

Si se exige a los empleados/compañeros que hagan algo y eso se les olvida, les causa dificultades o les hace perder el tiempo, es que no es correcto. Hay que buscar maneras de que los empleados/compañeros noten que hay un beneficio por realizar ciertas tareas.

En los modelos típicos de Ingeniería, hay ciertas "fases". Éstas se irán repitiendo en ciclos de varios días, semanas o, incluso, meses:

  • Especificación de requisitos
  • Diseño
  • Desarrollo
  • Pruebas
  • Documentación

Hay muchos modelos que son variantes de este pequeño esquema. Y es erróneo.

Especificación de requisitos

Esta fase está muy bien, pero a menudo se hace a muy bajo nivel. Se trata de explicar a los desarrolladores lo que quiere el cliente.

¿Y por qué no al revés?

Lo que propongo es que se le explique a ambos al mismo tiempo. ¿Cómo puede resultar esto posible? Pues de una manera muy sencilla: comenzando por el manual de usuario.

Si al cliente se le entrega el manual de usuario, puede detectar cosas que faltan al mismo tiempo que va aprendiendo a utilizar la herramienta.

Si al desarrollador se le entrega el manual de usuario, ya sabe cómo tienen que funcionar las cosas (seguramente le haga falta muy poca información adicional).

¿Todo está en el manual de usuario?

Si todo lo que el desarrollador necesita está en el manual del usuario, significa que el manual del usuario está mal. Hay un conjunto de cosas que no pueden incluirse en éste. El manual de usuario debe decir qué operaciones se pueden realizar o cómo llegar hasta estas operaciones. Lo que el manual de usuario no dirá serán cosas como ():

  • Seguridad, ya que gran parte de ésta se dará por sobreentendida -lo que puede llevar a error-.
  • Rendimiento o tiempos de respuesta, ya que el manual se centrará en lo que hace, no en cuánto tiene que tardar.
  • Escalabilidad; el manual de usuario es para un usuario, pero nuestra aplicación puede ser para muchos.
  • Tolerancia a fallos, o de qué fallos puede recuperarse el sistema.
  • ...

En general, este manual de usuario permite definir la interfaz y funcionalidad que el cliente necesita. El resto de requisitos tendrán que especificarse de otra manera (¿BDD?).

Una lista completa de lo que debería incorporar este apartado de especificación la proporciona Steve McConnell en su libro "Code Complete":

  • Organización del programa: Bloques principales del producto y sus responsabilidades (no estoy de acuerdo con ésta).
  • Clases principales (tampoco, ya que deben surgir de una necesidad del programa)
  • Diseño de datos (tampoco, ya que también deben surgir de una necesidad, aunque es posible que sí necesitemos dotar de cierta inteligencia a ese diseño)
  • Reglas de negocio, que puede estar en el manual de usuario.
  • Diseño de la interfaz de usuario, que sí puede estar en el manual de usuario.
  • Manejo de recursos
  • Seguridad
  • Rendimiento
  • Escalabilidad
  • Interoperabilidad, que también puede estar en el manual de usuario
  • Internacionalización/Localización
  • Entrada/Salida
  • Procesamiento de errores
  • Tolerancia a fallos
  • .

Como bien apunta Rubén en el comentario, estos puntos deben hablarse con el cliente, y deben validarse con él. Así mismo, es posible que varíen con el tiempo; quizá no de una manera radical, pero sí en pequeños aspectos que no se han tenido en cuenta. Por eso debe obtenerse realimentación del cliente de una forma periódica.

Diseño

En ocasiones es bueno tener una base sobre la que comenzar a construir, aunque no siempre es lo correcto. Aún así, soy de la opinión de tener una pequeña arquitectura base, aunque sea del middleware a utilizar.

Como bien indica Rubén, cuando el proyecto es grande e implica a numerosas personas, sí será necesario identificar los distintos componentes y diseñar la interacción entre ellos. Sin embargo, el comportamiento interno de éstos debe emerger de las necesidades de entrada/salida.

Desarrollo

En mi opinión, todo desarrollo debería seguir estos pasos (recién reconstruidos gracias a la lectura de "Introduction to Task Driven Development"):

  1. Seleccionar una única tarea
  2. Crear rama de trabajo
  3. Escribir un test
  4. Solucionar el test
  5. Commit
  6. Refactorizar
  7. Commit
  8. repetir desde el punto 3 hasta terminar los requisitos de la tarea
  9. Merge

Pruebas

Las pruebas unitarias se han ido realizando a medida que se va construyendo el software. Además, al tener la documentación final, es posible ir construyendo las pruebas de integración simultáneamente con el resto del sistema. No es necesario tener una fase específica para ello, tan solo sería un "check" en la lista de tareas a realizar: "Sí, se han lanzado las pruebas de sistema".

Documentación

Tampoco es necesaria. Ya se ha realizado durante la fase de toma de requisitos. Incluso se ha podido ir traduciendo a diferentes idiomas si era necesario.

Si hacían falta imágenes, éstas deberían haberse incluido mediante prototipos. Cambiar las imágenes de un documento debería ser un proceso rápido y limpio. Por eso estoy en contra de los sistemas de maquetación complejos tipo Word o Libre Office: Lo mejor es un formato basado en texto:

  • Si está basado en texto, se puede subir fácilmente al DVCS, con todas las ventajas de éste: ahorro de espacio, control de versiones, control de cambios, integración con el Tracking System, ....
  • Se puede tratar como el propio código: con sus bugs y sus mejoras.
  • Es más sencillo proporcionarlo en otro formato

Así que yo voto por lenguajes tipo Wiki, TXT, HTML o LaTeX (personalmente, me quedo con Wiki o LaTeX, más bien con este último).

Conclusión

Creo que resultaría mucho más gratificante para todos tener un proceso de producción de software más a la medida del desarrollador, tratando de orientar el proceso a sus necesidades y no imponerlo.

A menudo, el desarrollador es el último mono a la hora de la toma de este tipo de decisiones. Creo que debería dársele un papel más importante, ya que es el primer afectado.

2 comentarios:

  1. No estoy de acuerdo con algunos de los comentarios (esto es solo mi opinión, claro está).

    En cuanto a los requisitos, no me parece que el manual de usuario sea un buen punto de comienzo. El manual debe entrar en cierto tipo de detalles que en el momento de explicar la idea al programador te desvía del objetivo final y te despista. Cosas como nombres concretos de los elementos visibles de tu aplicación, la forma concreta de provocar una acción (un menú, o un botón acá o allá, o doble click sobre un nodo... poco importa al principio). En ese sentido creo que Scrum lo resuelve perfectamente: ¿hay que implicar al usuario final y al programador en el análisis de requisitos? Sí y por supuesto que sí. En las reuniones de planificación de Sprint hay dos partes, una de análisis y estimación de las historias y otra de diseño de las mismas. En Scrum existe un rol denominado "End User" que es precisamente el usuario final o un representante del mismo. Esta persona entiende perfectamente el dominio donde se desarrollará el proyecto y colabora en la correcta compresión y análisis de las historias. Por supuesto el equipo de desarrollo también participa en la reunión.

    El hecho de que sea una reunión hablada, cara a cara, y centrándose en los aspectos esenciales; me parece clave para la correcta comprensión de los requisitos.

    A esto solo añadir que, en mi humilde opinión, el tipico consultor o ingeniero de requisitos visitando al cliente y luego haciendo un informe que pasa por unos diseñadores que hacen el diseño perfecto y que los programadores entienden a la primera y hacen funcionar desde el primer momento es una utopía. Una reunión cara a cara con los interesados (grupo de desarrollo y usuario) es real y funciona.

    En cuanto al diseño, me parece absolutamente imprescindible y mucho más cuando hay un grupo de desarrollo (y no se trata de un desarrollo realizado por una sola persona). El hecho de aclarar la forma en que se llevarán a cabo las funcionalidades requeridas, qué piezas formarán parte de la solución, cómo se integran y comunican, qué formatos se utilizan, etc. es absolutamente básico y todo eso es lo que yo considero el diseño. El truco está en llegar a la profundidad necesaria: En mi opinión, diagramas de clase totalmente completos, con todos y cada uno de los miembros y atributos de cada clase del producto, diagramas de secuencia con la definición de cada operación, etc. es una exageración innecesaria. Veo perfectamente suficiente el que un grupo de desarrollo de gente preparada, que trabaja codo con codo, acuerde cara a cara un diseño. Éste debe documentarse y ser ni mas ni menos que un acuerdo de cómo se va a resolver el problema plasmado de una forma que resulte cómoda a todos. Sin el diseño el proyecto muy probablemente encontrará problemas serios durante su desarrollo (de tecnología, consistencia, integridad, etc.). Un diseño totalmente exhaustivo es tan pesado y poco practico que puede llevar al grupo a ignorar esta etapa y pasarse al otro extremo. En ese sentido, estoy también de acuerdo con la filosofía de Scrum, en la que el diseño lo realiza el grupo de desarrollo como una 2ª parte de la reunión de planificación de Sprint.

    Por lo demás, totalmente de acuerdo.

    ResponderSuprimir
  2. Hola, Rubén.

    Si relees la entrada, verás que he modificado los dos puntos que comentas: requisitos y desarrollo.

    Te doy la razón en casi todo :D

    ResponderSuprimir