Antes de desplegar a la infraestructura virtual, el código tiene que ser testeado, porque código que no está probado, está roto. El crear los tests y, eventualmente, una forma automática de ejecutarlos es un paso previo a llevar a cabo tareas de integración y despliegue continuo (que se verán a continuación).
Haber superado al menos los tests del objetivo anterior.
En ingeniería del software hay que aprender a tomar decisiones técnicas sobre las herramientas, servicios y bibliotecas que se van a usar en el proyecto, y a justificarlas documentalmente. Esto es lo que se busca en este objetivo: adoptar una cultura de tomar decisiones objetivas, basadas en el proyecto, y justificarlas.
Una guía de cómo abordar la consecución de este objetivo.
La ingeniería del software consiste en resolver problemas, y muchos de esos problemas van a ser qué (otro) software se va a usar para resolverlo. En general, a partir de una historia de usuario se plantean muchos problemas; alcanzar un producto mínimamente viable requiere identificar cuales son esos problemas y crear un marco para tomar una serie de decisiones que sean, a la larga, si no las mejores (nunca hay mejores soluciones en ingeniería de software) sí suficientemente razonables para el proyecto con vistas al siguiente producto mínimamente viable y al mantenimiento, a medio plazo, del proyecto.
El mantenimiento a largo plazo es un problema totalmente diferente.
Ya se ha tomado al menos una decisión, cuál es el lenguaje del proyecto, y esperamos que se haya justificado lo suficiente. Pero a partir de ahora, casi en cada objetivo habrá que decidir qué se va a usar, siguiendo una serie de criterios más o menos generales
- Los estándares que haya en cada lenguaje o aspecto específico del mismo. Si hay un estándar, primero hay que conocerlo; a continuación simplemente hay que seguirlo y adaptar el resto de los criterios al mismo.
- Las mejores prácticas: en cada lenguaje evolucionan continuamente; estas aconsejan cuál es la herramienta más adecuada o al menos qué tipo de herramienta se considera la más adecuada; en el momento de iniciar un proyecto y tomar una decisión es cuando hay que ponerse a buscar de qué se tratan. En muchos casos no te darán una sola herramienta, sino un conjunto de herramientas, pero hay otros criterios para elegir.
- La deuda técnica. La deuda técnica es lo que hay que "pagar" para poder avanzar en un proyecto; es, en general, todo tipo de código difícil de mantener que fuerce al equipo a pagar en su tiempo (y sudores). Son deudas que se incurren cuando se adopta una solución rápida a un problema sin pararse a pensarla mucho, cómo simplemente escoger el marco MVC que sea más popular en cada momento. En muchos proyectos no queda otro remedio que incurrir en esa deuda técnica, y la decisión estará influda por eso. Sin embargo, en un proyecto recién comenzado, hay que intentar no tomar una decisión que aumente la deuda técnica; por ejemplo, si elegimos una herramienta que no se mantiene con asiduidad estaremos aumentando la deuda técnica porque el grupo tendrá que seguirla usando, sin más remedio, y más adelante tendrá que pagar refactorizando para usar otra herramienta. En general, las mejores prácticas asegurarán que no aumenta la deuda técnica, pero en algunos casos, si hay varias elecciones posibles, habrá que tenerla también en cuenta.
- Criterios objetivos adicionales: sobre todo, seguridad, prestaciones o algo que se pueda reducir a la cantidad de tiempo que se va a invertir en mantener lo relacionado con la decisión. La mayoría de las herramientas tendrán benchmarks que las comparen con otras; pero siempre se puede intentar hacer pruebas sobre el propio proyecto. Si miramos a este objetivo en particular, habrá gestores de dependencias que funcionen mejor con muchas dependencias, otras que funcionen mejor con pocas dependencias. ¿Cuantas dependencias tiene nuestro proyecto? En función de eso lo decidimos.
- Debemos tratar de evitar criterios subjetivos: familiaridad, "buena
documentación", "popularidad" (si uno ha oído hablar mucho de él, no tiene por
qué ser mejor). Herramientas con las que se está muy familiarizado, como
jQuery
, ya no se consideran el estado del arte (desde hace muchos años, además). Y otras comobootstrap
son bastante discutibles.
En cualquier caso, esta toma de decisiones y su documentación es lo esencial a la hora de alcanzar este objetivo (y la mayoría de los objetivos sucesivos). No es importante que se haya elegido uno y no otro. Es más, si es una mala decisión se puede cambiar más adelante, en función de la evolución del proyecto. Lo importantes es que el estudiante adquiera y ponga en práctica la constumbre de tomar decisiones informadas y justificar las mismas.
En ese sentido, el estudiante debe esforzarse en tratar de hacer su propia elección y no inspirarse en la hecha y ya aceptada para otro estudiante. Dado que lo importante es el aprendizaje del estado del arte y la buena documentación de la toma de decisiones, el hecho de que tome la misma decisión que otra persona (y además lo documente de la misma forma) indica exactamente lo contrario, que no ha tomado esa decisión ni ha aprendido a documentarla y por tanto no ha superado el objetivo.
En todo proyecto hay una serie de tareas que se llevan a cabo de forma repetitiva; estas tareas van desde las más obvias, que es ejecutar el programa o ejecutar los tests (lo que haremos más adelante) hasta instalar dependencias.
Empezando por instalar las dependencias, la mayoría de los lenguajes modernos tienen herramientas específicas para llevarlas a cabo; estas herramientas analizan las bibliotecas que se declara que se utilizan, y a partir de ahí trata de instalarlas de la mejor forma posible, siguiendo las instrucciones, e instalando todas las demás librerías que son prerrequisitos para las mismas, resolviendo posibles conflictos también de la mejor forma posible.
En general, tanto expresar estos requisitos como interpretar tal fichero e instalarlos necesitan un gestor de dependencias y diferentes lenguajes son también diferentes en la forma de proporcionar uno. En el caso más general, sin embargo, habrá diferentes gestores de dependencias para elegir.
Esta es solo una de las tareas que hay que hacer; pero hay muchas otra que
también requerirán automatización. Por ejemplo, la ejecución de los tests usando
las herramientas de construcción o de gestión de tareas del lenguaje que se esté
usando; por ejemplo, incluir un objetivo make test
dentro de un
Makefile
. Normalmente, estas tareas u órdenes son estándar para cada lenguaje
y generalmente también Travis (o el sistema que elijáis) las ejecutará
automáticamente salvo que le digas lo contrario. En algunos casos, como Python,
las herramientas de construcción como poetry
solo necesitarán un fichero
pyproject.toml
que instale las dependencias, si las hubiera.
Sin embargo, en otros lenguajes el fichero de tareas (task runner o task manager) correspondiente permitirá especificar dependencias, versión del lenguaje, instrucción específica que se va a usar para hacer test y también metadatos adicionales como licencia o autor. En general, hay un continuo que va desde los gestores de dependencias hasta los gestores de tareas pasando por otros que son herramientas de construcción, por ejemplo. En muchos casos un gestor de dependencias completo puede hacer bastantes tareas, por eso puede ser preferible a usar el mismo + un gestor de tareas, ya que en ese caso habría que incluir una dependencia adicional.
En muchos lenguajes modernos, el gestor de dependencias es, primero, una
herramienta independiente del compilador o intérprete principal, y, segundo, no
especificada por el mismo, habiendo por tanto diferentes opciones a elegir entre
todas las que siguen la especificación principal (que suele ser el formato de
especificación de tales dependencias). Por ejemplo, Python y la mayoría de los
intérpretes de Javascript especifican el formato de las dependencias, el fichero
pyproject.toml
y package.json
respectivamente, pero no qué programa tiene
que trabajar con él.
Pero sí los estándares a los que se acogen, porque siempre hay que conocer los estándares.
En este caso habrá que establecer los criterios para elegir uno de ellos sobre otros y justificar la elección que eventualmente se tome.
En algunos casos este gestor de dependencias elegido también podrá ejecutar para el usuario una serie de tareas con alguna limitación; justificar que se elija una herramienta específica para ambas cosas también tendrá que hacerse, coo es natural.
Finalmente, todo cambio en el repositorio debe, eventualmente, ser parte de un producto mínimamente viable que va a recibir el cliente; por eso hay que incluir este tipo de instrumentación en algún milestone.
El material del curso cero incluye varios temas relacionados con el desarrollo basado en test. Se recomienda encarecidamente que se entiendan los conceptos, antes de proceder a hacer el trabajo relativo a este objetivo en si. Adicionalmente, se puede consultar este trabajo sobre los task runners o gestores de tareas.
Preguntas antes de entregar que tienes que hacerte, y copiar en tu PR marcando todo lo que se aplique:
* [ ] ¿Incluye el fichero `iv.yaml` las claves de todos los objetivos
anteriores?
* [ ] ¿Se ha desarrollado el fichero para las tareas a partir de un
issue?
* [ ] ¿Ese issue está asignado a un milestone?
* [ ] ¿El milestone incluye, entre sus productos mínimamente viables, la
existencia de herramientas que permitan automatizar tareas?
* [ ] ¿Hemos justificado correctamente en caso de elegir un gestor de
dependencias el que se use como gestor de tareas?
* [ ] ¿El PR, que también es un issue, está asignado al mismo milestone?
* [ ] ¿La tarea `check` efectivamente comprueba la sintaxis de los fuentes
existentes y sólo eso?
* [ ] ¿Se ha comprobado que las instrucciones incluidas en el `README.md` son
completas y correctas?
Se vuelve a recordar al estudiante que se debe seguir este guión de objetivo, y no inspirarse por lo que hayan hecho otros estudiantes, especialmente para comprobar la sintaxis de los fuentes (se trata solo de comprobar la sintaxis, es decir, si compila correctamente).
Se tendrá que haber actualizado el repositorio que se usara en los objetivos anteriores y añadir al fichero de este objetivo el nombre del proyecto, el autor y un enlace al mismo y hacer un pull request.
La descripción del proyecto tiene que seguir progresando, así que el
README.md
tiene que incluir una descripción real de la clase que se
vaya a comprobar y qué uso va a tener dentro del servicio (o
servicios) web que se van a desplegar más adelante. En un proyecto el
README.md debe estar escrito para la persona que llegue, y no para que
se corrija. Si hay documentación adicional, tendrá que enlazarse desde
este README.md
.
Habrá que añadir al fichero iv.yaml
la clave automatizar
, que tendrá las
siguientes subclaves:
fichero
apuntará al fichero que se va a usar, a partir de ahora, para ejecutar diferentes tareas. En ese fichero, que será específico del lenguaje en algunos casos (en otros será genérico, como un Makefile), se tendrán que ir poniendo todas las tareas que se hagan en el proyecto, empezando pormake install
omake installdeps
y continuando, en este mismo, conmake test
.orden
dirá qué hay que usar en la línea de órdenes para ejecutarlo. Se comprobará, en este objetivo, que en elREADME.md
existe la cadenaorden check
explicando cómo comprobar la sintaxis de la entidad o entidades que se hayan programado hasta ese momento.
Entre las tareas que estén automatizadas, se tendrá que incluir necesariamente la que corresponde al objetivo anterior, es decir, comprobar que la sintaxis de los fuentes que haya hasta ese momento sean correctos. Se puede incluir alguna adicional, siempre dentro del producto mínimamente viable en el que se esté trabajando.
Se consigue si se han configurado correctamente las herramientas de construcción y justificado mínimamente su elección en un documento aparte.
El plazo de entrega aconsejado es de diez semanas a partir del comienzo de las clases; en años anteriores, entre los que aprobaron
- el 50% lo había entregado en 7 semanas,
- el 75% en 10 semanas,
- el 90% en 12 semanas;
El alcanzar este objetivo avanzará, en principio, 7.5% de el apartado correspondiente de la asignatura.