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.
Fases
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” ):
- Seleccionar una única tarea
- Crear rama de trabajo
- Escribir un test
- Solucionar el test
- Commit
- Refactorizar
- Commit
- repetir desde el punto 3 hasta terminar los requisitos de la tarea
- 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.