056.1 Lección 1
Certificación: |
Open Source Essentials |
Versión: |
1.0 |
Tema: |
056 Colaboración y comunicación |
Objectivo: |
056.1 Herramientas de desarrollo |
Lección: |
1 de 1 |
Introducción
Existen miles de herramientas de desarrollo de software, tanto de código abierto como de código propietario. ¿Y por qué no? A los programadores les encanta desarrollar herramientas para ellos mismos y para sus colegas; es natural que inviertan mucho tiempo en intentar encontrar una herramienta que funcione mejor, que elimine algunas molestias de su flujo de trabajo o facilite la implementación.
Esta lección se centra en el proceso de desarrollo y explica cómo encajan en él los distintos tipos de herramientas de desarrollo. Se nombrarán algunas herramientas específicas, ya que cualquiera de ellas podría estar marcada como obsoleta o en desuso y ser reemplazada por una nueva cuando lea esta lección.
Objetivos del desarrollo
Las herramientas de programación combinan múltiples objetivos que a veces entran en conflicto entre sí. A continuación, se muestran ejemplos de algunos objetivos de desarrollo:
-
Producir programas robustos y precisos.
-
Producir programas que se ejecuten rápidamente.
-
Producir programas que puedan escalarse.
-
Producir programas que sean altamente adaptables a diferentes tipos de usuarios, diferentes dispositivos (como computadoras portátiles, teléfonos celulares y tabletas) y diferentes entornos.
-
Acelerar el proceso de desarrollo.
-
Acelerar la implementación de funciones recientemente desarrolladas o correcciones de errores.
-
Reducir el trabajo tedioso, así como la cantidad de errores de programación administrativa que pasan a las etapas de prueba..
-
Admitir códigos heredados y dispositivos que la organización tiene dificultades en reemplazar.
-
Trabaje junto con otras herramientas conocidas.
-
Permitir una fácil reversión en caso de errores o cambios en los planes.
Estos objetivos, y otros, conducen a los procesos descritos en esta lección y a las herramientas de desarrollo resultantes.
Procesos generales de desarrollo
Esta sección contrasta dos modelos generales de importancia histórica: el modelo en cascada (introducido en una lección anterior) y la integración continua/entrega continua (CI/CD).
Modelo de cascada
Aunque el modelo en cascada todavía se utiliza ampliamente, especialmente en las grandes organizaciones, ha caído en desuso entre muchos desarrolladores. Este modelo fue popular desde la década de 1950 hasta la de 1970. Algunos elementos del modelo todavía se pueden encontrar ampliamente en la actualidad, como las definiciones formales de los requisitos y los programas de prueba justo antes de su lanzamiento (garantía de calidad).
Incluso cuando se adoptó el término “cascada” para este modelo, ya había quedado ampliamente desacreditado. Entre los problemas que presentaba se encontraban los siguientes:
-
Cambiar los requisitos fue difícil una vez que comenzó el desarrollo.
-
Los requisitos y diseños se malinterpretaban a menudo porque el texto en lenguaje sencillo puede ser ambiguo. Este problema dio lugar a productos que no cumplían los requisitos previstos y tardaban meses en solucionarse.
-
El proceso era lento. Se podía conseguir un nuevo lanzamiento solo una vez al año o incluso con menos frecuencia.
-
Los errores causados por la interacción de diferentes módulos eran difíciles de detectar hasta una etapa avanzada del proceso, lo que eventualmente se convertía en más demoras.
-
El proceso creó barreras entre las diferentes partes de la organización, lo que fue malo para la calidad del producto y para el espíritu del cuerpo organizacional.
Principios de integración continua/entrega continua (CI/CD)
El modelo en cascada fue desafiado en la década de 1970 por una serie de movimientos que llevaron al modelo más popular (si no universalmente utilizado) en la actualidad: CI/CD. Las etapas de la adopción de las prácticas de CI/CD incluyen el Manifiesto Ágil, publicado en 2001, SCRUM y DevOps. El nuevo modelo se basa en los principios de una comunicación estrecha entre los miembros del equipo, la participación del usuario final o cliente, la rápida implementación de correcciones de errores y nuevas características, pruebas rigurosas y continuas para preservar la calidad en un entorno de rápido movimiento, a veces incluso caótico.
La CI/CD automatiza tantos pasos como sea posible en las etapas que van desde la escritura del código hasta la implementación del programa completo para los usuarios finales. La CI/CD requiere definir cada paso formalmente y reemplazar una acción humana (como instalar software manualmente) con un procedimiento ejecutado por un programa. Por lo tanto, la CI/CD es parte de un movimiento conocido con la frase “todo como código” e “infraestructura como código”.
Además, una vez que un equipo ha incorporado sus procesos al código, estos procesos se pueden corregir, actualizar y registrar históricamente, al igual que el código. Todo lo que escriba el equipo, ya sean programas, procedimientos automatizados o documentación, debe almacenarse en un sistema de control de versiones, que se describe en una próxima lección.
Cuando se automatizan varios procedimientos, estos pueden ejecutarse en secuencia. Por ello, los equipos suelen hablar de un canal de CI/CD, lo que significa que un paso exitoso en el canal desencadena automáticamente uno o más procesos posteriores. Un canal debe supervisarse de forma automatizada para que cualquier fallo en el camino provoque que el canal se detenga y notifique a los miembros del equipo sobre el fallo.
Aunque en las siguientes secciones se analizan el CI y la CD por separado, tienden a combinarse y la línea divisoria entre ellas es borrosa.
Integración Continua (IC)
La integración continua se refiere a la rápida incorporación de pequeños cambios en el código. El repositorio central que se utiliza para crear el producto para los usuarios finales se conoce como repositorio central (o repositorio principal). Cada programador crea un espacio de trabajo personal (a menudo llamado sandbox) en su computadora y extrae del repositorio central los archivos que necesita para reparar o actualizar.
El programador podría utilizar una computadora personal portátil o de escritorio (lo que se conoce como sistema de desarrollo local), descargar las partes relevantes del repositorio central y luego cargar los cambios después de realizar pruebas locales. Como alternativa, el programador podría aprovechar la tendencia popular denominada “computación en la nube” y trabajar en un sistema compartido administrado por su organización, un sistema de desarrollo remoto.
El programador generalmente busca errores mediante un depurador, un programa independiente que ejecuta el trabajo del programador en un entorno controlado. Más adelante analizaremos los depuradores y otras herramientas para detectar errores.
Para detectar errores lo antes posible en el proceso de desarrollo, el programador también ejecuta pruebas en el código antes de subirlo al repositorio principal. Estas pruebas se denominan pruebas unitarias porque cada una se centra en un elemento minúsculo del código: por ejemplo, ¿una función incrementó un contador como se suponía que debía hacerlo?
La última etapa de la integración continua consiste en comprobar los cambios que el programador ha realizado en el repositorio central. En esta etapa, las herramientas ejecutan pruebas de integración para asegurarse de que el programador no haya dañado nada en el proyecto conjunto.
No importa lo lejos que haya llegado la automatización, algún miembro experto del equipo debe intervenir en el punto de integración para asegurarse de que el cambio sea el deseado por el equipo. Las pruebas automatizadas pueden determinar que nada se ha estropeado e incluso si el cambio crea el efecto deseado en el programa. Pero estas pruebas no pueden comprobar todos los principios que el equipo considera importantes.
Por lo tanto, antes de proceder a la implementación, un miembro del equipo debe verificar la seguridad, el cumplimiento de los estándares de codificación, la documentación adecuada y otros principios. (No es de sorprender que también existan herramientas para algunas de estas tareas; las analizaremos más adelante en esta lección).
Durante la integración continua se realizan muchas pruebas, que deben realizarse de forma rápida y fiable para soportar el ritmo del desarrollo moderno. Por lo tanto, las herramientas modernas para integrar código y ejecutar pruebas están automatizadas. Un programador debería poder ejecutar un conjunto completo de pruebas unitarias con un solo comando o con el clic de un botón.
Generalmente, se ejecuta una prueba de integración parcial o total cada vez que el programador carga código en el repositorio principal. Cualquier error detectado por las pruebas se puede informar rápidamente al programador.
Entrega continua (CD)
Como se explicó en la sección anterior, la CI consiste en procedimientos automatizados que conducen a una nueva versión del programa en el directorio central. La entrega continua se refiere a todo lo que sucede después de esa etapa para llevar la nueva versión al campo donde los usuarios finales pueden beneficiarse de ella. La D en CD a veces se expande a “desarrollo” o “implementación” además de “entrega”.
Las tareas principales del CD son probar el código exhaustivamente y cargarlo en las computadoras de los usuarios o en un repositorio de aplicaciones.
En la fase de desarrollo de producto se ejecuta una serie de pruebas para garantizar al máximo que el producto funciona bien. Se puede ejecutar un conjunto más amplio de pruebas de integración, junto con otras pruebas para determinar el impacto en los usuarios, el rendimiento y la seguridad. En una sección posterior de esta lección se describen algunas de estas pruebas.
Las pruebas deben realizarse en sistemas distintos a los de producción. Una falla catastrófica no solo podría hacer caer un sistema, sino que también podría corromper los datos de los usuarios. Además, las pruebas compiten por el tiempo del sistema y degradan el rendimiento para los usuarios.
Por lo tanto, para realizar pruebas, lo mejor es configurar un entorno informático completo que refleje el entorno de producción, con hardware y software similares. El entorno intermedio donde se ejecutan las pruebas antes de la implementación suele denominarse entorno de ensayo.
Por supuesto, no sería práctico hacer que el entorno de prueba tenga el mismo tamaño que el entorno de producción, pero se deberían incluir los elementos esenciales en producción (como las bases de datos).
Un requisito de la automatización de CD es distinguir entre los entornos de prueba y producción. Todas las instalaciones y procesos de código deben adaptarse al entorno de destino.
El CD ofrece el mayor potencial para un desarrollo rápido cuando el código es un servicio que se ejecuta en los propios sistemas de la organización. Si, por ejemplo, se trata de un sitio de venta minorista que ofrece una página web interactiva, se tiene acceso a todos los servidores web. Se pueden actualizar varias veces al día y revertir los cambios rápidamente si resultan ser un problema para los usuarios.
Herramientas comunes de desarrollo de software
Estas secciones presentan tipos comunes de herramientas utilizadas por los equipos de programación en tres niveles: generación de código, pruebas e implementación.
Compiladores
Una herramienta de programación fundamental es el compilador, que convierte lenguajes de programación muy sofisticados y de alto nivel en instrucciones que se ejecutan en el procesador de la computadora.
Los ordenadores ejecutan código máquina, que consiste en cadenas de bits (unos y ceros) que el procesador convierte en instrucciones y datos: cargando un valor de la memoria en un registro, sumando los valores de dos registros, etc. Los procesadores se distinguen por los diferentes formatos y conjuntos de instrucciones que tienen, por lo que también tienen diferentes códigos máquina. Los proveedores intentan inventar nuevos procesadores que utilicen el mismo código máquina para permitir que los clientes ejecuten sus viejos programas en los nuevos procesadores. Cuando los proveedores hacen esto, hablamos de familias de procesadores.
La siguiente etapa en los primeros años de la programación fue el lenguaje ensamblador, que proporcionaba términos legibles para humanos, como ADD, para cada instrucción. Los programadores escribían en lenguaje ensamblador y enviaban su código a una herramienta llamada ensamblador para traducir el lenguaje ensamblador a código de máquina. El código de máquina también se denomina lenguaje de máquina.
Luego se crearon lenguajes de nivel superior. Hoy en día, se pueden crear flujos de control complejos sin siquiera especificar sus detalles; basta con indicar los resultados deseados. Estos programas requieren un compilador para convertir el código fuente en código de máquina. Los compiladores pueden realizar transformaciones y optimizaciones bastante inteligentes.
Muchos lenguajes tienen varios compiladores disponibles. Puedes encontrar una selección de compiladores para lenguajes muy populares, como C y Java. En la comunidad de código abierto y gratuito, la mayoría de la gente usa la Colección de compiladores GNU (GCC) o el compilador LLVM para C y C++.
Originalmente, un compilador compilaba cada archivo de código fuente para producir un archivo de objeto intermedio y luego combinaba todos los archivos de objeto en un programa invocando otra herramienta llamada vinculador. Los compiladores modernos pueden compilar varios archivos a la vez para realizar optimizaciones que trascienden los límites de los archivos.
Los compiladores solían compilar en lenguaje ensamblador, lo que podía resultar útil porque cada tipo de procesador de ordenador admitía un código de máquina diferente, pero podía admitir el mismo lenguaje ensamblador. Existen múltiples variantes de lenguajes ensambladores. El último paso en la compilación y el enlace era producir código de máquina. Al igual que con el enlace, los compiladores modernos saben cómo ensamblar el código en código de máquina.
Pero en muchos lenguajes modernos existe otra etapa: el código intermedio, que suele denominarse código byte. Este código se ha compilado en un formato binario de alto nivel para que sea portable. Por ejemplo, el lenguaje Java se compila en código byte para que el programa pueda cargarse en muchos tipos diferentes de procesadores.
Al producir código de bytes a partir del código fuente, el compilador ha hecho gran parte del trabajo. Luego, cada computadora aloja su propia versión de un programa llamado máquina virtual que completa la transformación del código de bytes en un conjunto de instrucciones que la máquina virtual puede ejecutar. A veces, el código de bytes también se compila en código de máquina. Pasar del código de bytes a un conjunto de instrucciones es más conveniente para los usuarios finales que pasar de un lenguaje de programación de alto nivel a código de máquina. Esto fue una gran ventaja para Java cuando se inventó, porque sus diseñadores querían que se ejecutara dentro de un complemento de máquina virtual para navegadores web, donde el procesador y el entorno operativo del usuario podían ser bastante variados.
Los diseñadores de Java promocionaron los beneficios del código de bytes mediante la frase publicitaria “Compila una vez, ejecuta en cualquier lugar”. Más tarde surgieron otras ventajas del código de bytes. Se podían crear nuevos lenguajes que proporcionaban una experiencia muy diferente a los programadores (facilitando el trabajo de programación y produciendo un código más fácil de mantener) y, al mismo tiempo, creando el mismo código de bytes que admitían las máquinas virtuales de Java. Las funciones de estos lenguajes eran fáciles de mezclar en los programas Java existentes.
Por último, existen algunos lenguajes, como Python, para los que no es necesario compilar el código fuente: basta con introducir instrucciones en una herramienta de procesamiento llamada intérprete, que convierte el código directamente en código de máquina y lo ejecuta. Los intérpretes son más lentos que los compiladores, pero algunos se han vuelto lo suficientemente eficientes como para no afectar demasiado al rendimiento. Aun así, algunas bibliotecas populares en el lenguaje Python incluyen funciones a las que los desarrolladores pueden acceder en el lenguaje interpretado, pero que están programadas en el lenguaje C, para acelerar la ejecución.
Muchos lenguajes interpretados también ofrecen compiladores, que generan código de bytes o código de máquina, que luego se ejecuta más rápido que el intérprete.
Existen herramientas de compilación que ayudan a los programadores a gestionar archivos y funciones. Un programa complejo puede contener cientos de archivos y el programador deberá compilar distintas combinaciones de archivos utilizando distintas opciones del compilador en distintos momentos (por ejemplo, para facilitar la depuración). Una herramienta de compilación permite a los programadores almacenar distintas opciones y combinaciones de archivos y elegir fácilmente el tipo de compilación deseado. Maven y Gradle son herramientas de compilación habituales para Java y lenguajes relacionados.
Herramientas de generación de código
El programador no tiene por qué empezar a codificar con una pantalla en blanco. Recientemente han surgido servicios que generan código basándose en la descripción en texto simple de lo que se desea. Se trata de una forma de IA generativa y al igual que otros servicios similares, algunas personas se quejan de que se basa en el trabajo de antiguos programadores sin compensación y produce un código fuente menos sólido (hasta ahora). Aparte de las controversias éticas, muchos programadores dicen que la generación automática de código ha mejorado enormemente su productividad.
Una forma de generación de código que ha estado disponible en muchos lenguajes de programación durante muchos años es la refactorización. Examina un programa grande, que puede evolucionar fácilmente con el tiempo hasta convertirse en una maraña de archivos y funciones. La refactorización mueve las funciones para crear una estructura más lógica para el programa con el objetivo de mejorar la capacidad de mantenimiento y reducir la duplicación del código fuente.
Algunos programadores tienen la tarea de reproducir el funcionamiento de otro código. Es posible que necesiten escribir un programa nuevo para reemplazar un programa heredado con código fuente faltante que debe ser retirado. O pueden estar imitando el programa de un competidor. Este tipo de investigación se llama ingeniería inversa. Una herramienta útil para este propósito es un desensamblador, que convierte el código de máquina en lenguaje ensamblador. También existen desensambladores para código de bytes.
Depuradores
La mayoría de los programadores pasan más tiempo depurando que codificando. La gente no piensa de forma perfectamente lógica y, por lo tanto, olvida algún detalle que la computadora necesita para ejecutar el programa de la manera deseada. Por lo tanto, es probable que su código falle en el primer intento y puede beneficiarse enormemente de un depurador para descubrir el error.
Un depurador respalda esfuerzos de investigación intensivos que pueden reducir horas del proceso de búsqueda de errores.
Un programador puede pedirle al programa que se detenga en algún punto clave del programa (un punto de interrupción), como el comienzo de una función o un bucle. El depurador puede mostrar los valores de las variables e incluso los registros de la computadora en el punto actual del programa. El programador también puede ejecutar cada instrucción, una a la vez, y ver los resultados (paso a paso). Si el programador desea ver cuándo y cómo cambia una variable durante la ejecución, puede establecer un punto de vigilancia.
El depurador más destacado en el mundo del código abierto y gratuito, en particular para C y C++, es el depurador GNU, que funciona con el compilador GNU mencionado anteriormente. Otros lenguajes también tienen depuradores dedicados.
Herramientas Analíticas
Aunque la depuración suele permitir descubrir errores con bastante rapidez, es mejor eliminar los errores ortográficos y otros problemas básicos en una fase más temprana del proceso de programación. Existen muchas herramientas analíticas ingeniosas para comprobar un programa. El análisis estático examina el código de un programa. El análisis dinámico ejecuta un programa y comprueba si hay problemas durante su ejecución.
Una de las primeras formas de análisis estático se denominaba linter. Puede detectar, por ejemplo, si se asigna el valor de una variable de punto flotante a un entero. Esto puede producir problemas, y puede que el compilador lo detecte o no. En producción, puede dar lugar a resultados incorrectos.
Hoy en día, la mayoría de los compiladores pueden hacer el trabajo de un linter. Algunos compiladores, como el del lenguaje Rust, se destacan por su rigurosidad al rechazar código mal escrito.
Muchos otros tipos de herramientas analíticas se ejecutan por separado del compilador. Por ejemplo, las herramientas de análisis de seguridad pueden encontrar problemas que hagan que un programa sea vulnerable a la piratería. Un error común de los desarrolladores, por ejemplo, es cuando su código llama a una función y no verifica si esa función devolvió un error.
Entornos de desarrollo integrados (IDE)
Muchos programadores utilizan editores de texto para introducir y editar su código. Los editores de texto son diferentes de los procesadores de texto, que introducen una gran cantidad de formato (como cursiva y negrita, viñetas y listas numeradas, etc.). El procesador de texto produce texto sin adornos, algo que requieren los lenguajes de programación.
También existen herramientas sofisticadas dedicadas a ayudar a los programadores a desarrollar sus programas. Estas herramientas están alertas al lenguaje de programación en uso. Por ejemplo, si comienza a escribir el nombre de una variable de función, la herramienta puede sugerirle que complete la tarea. Estas herramientas pueden verificar errores mientras está codificando, formatear el código de una manera consistente y agradable, ejecutar herramientas analíticas y depuradores, compilar el código, manejar los check-ins en los sistemas de control de versiones y encargarse de otras tareas por usted. Por lo tanto, se denominan entornos de desarrollo integrados (IDE).
Eclipse es un IDE de código abierto popular.
Tipos comunes de pruebas de software
Las pruebas son una parte importante del desarrollo de software. Los programadores ejecutan pruebas unitarias a medida que desarrollan el código. Otros tipos de pruebas se ejecutan normalmente cuando un programador devuelve el código al repositorio principal o durante la implementación.
Pruebas unitarias
Hemos visto que un programador debe tener mucho cuidado para encontrar errores antes de enviar el código para su integración en el repositorio principal. Las pruebas unitarias son fundamentales para detectar errores.
Escribir estas pruebas es tanto un arte como una ciencia, y el volumen de código de prueba puede superar el volumen de código de producción. Incluso existe un modelo de desarrollo llamado desarrollo impulsado por pruebas (TDD), en el que los programadores escriben pruebas antes de escribir el código que quieren probar. Los defensores del TDD afirman que cubre las lagunas en las pruebas y ayuda a garantizar que el código haga lo que el programador quiere que haga.
Es importante comprobar si hay errores durante la ejecución del programa, así como también si hay errores. Si el usuario u otra parte del programa envía una entrada no válida a una función, es importante que la función detecte el problema y envíe un mensaje de error adecuado.
JUnit es una popular herramienta de código abierto para ejecutar pruebas unitarias en programas Java.
Integración, regresión y pruebas de humo
Si bien las pruebas unitarias se centran en las acciones individuales de funciones específicas, el equipo también debe ejecutar pruebas a un nivel superior para asegurarse de que el producto, en su conjunto, funcione correctamente. Las pruebas generalmente imitan el comportamiento del usuario. Por ejemplo, en una aplicación de gestión de restaurantes, las pruebas podrían verificar si el usuario recibe el artículo que solicitó.
Cuando un cambio en un programa rompe alguna función que funcionaba antes, la falla se llama regresión y las pruebas se llaman pruebas de regresión.
Mientras un equipo prepara un producto para su lanzamiento, la primera etapa de pruebas suele ser muy breve. El equipo comprueba las actividades más importantes que realiza un programa y detiene las pruebas si surgen errores, ahorrando así tiempo. Este tipo de pruebas se denominan pruebas de humo, porque una aplicación que funciona mal con tanta facilidad es como un dispositivo defectuoso que se incendia.
Algunos productos implican la interacción del usuario; las aplicaciones web y móviles son ejemplos comunes. Por lo tanto, se han creado herramientas para emular las interacciones del usuario. La prueba se ejecuta automáticamente y activa el código que se habría ejecutado si un usuario presionara el botón. Selenium es una herramienta popular en esta categoría.
Pruebas de aceptación
Los programas con una interfaz de usuario necesitan un nivel adicional de pruebas, además de demostrar que reaccionan correctamente a determinadas entradas. Los programas también deben verse bien en la pantalla. Las pruebas de aceptación verifican el impacto del programa en el usuario. Los equipos de control de calidad generalmente realizan estas pruebas después de que las pruebas de integración y regresión demuestren que el programa es formalmente correcto y cumple con las expectativas del usuario.
Pruebas de seguridad
Obviamente, la seguridad es fundamental, e incluso un pequeño fallo de seguridad puede exponer a una organización a daños importantes. Hemos visto que los programadores pueden ejecutar herramientas analíticas para comprobar la seguridad del código. En la etapa de control de calidad, las pruebas también pueden determinar si el programa tiene vulnerabilidades. Las pruebas ejecutan el programa con entradas maliciosas y se aseguran de que el programa rechace la entrada sin fallar, realizar acciones no deseadas o revelar información confidencial.
Un tipo de prueba que ha demostrado ser útil en algunas situaciones es la prueba de fuzzing. El marco de prueba simplemente genera cadenas de basura aleatoria y las envía como entrada al programa. Esto puede parecer una pérdida de tiempo, pero a menudo descubre vulnerabilidades que las pruebas ordinarias no detectan.
Pruebas de rendimiento
Una vez que otras pruebas determinan que el programa funciona correctamente, los equipos deben determinar si se ejecuta con la suficiente rapidez. Las pruebas de rendimiento requieren un entorno similar a aquellos en los que los usuarios interactuarán con el programa. Por ejemplo, si los usuarios enviarán solicitudes desde una gran distancia a través de una red, las pruebas de rendimiento también deben realizarse en una red de larga distancia.
Algunas bibliotecas de programación se prueban a través de benchmarks: pruebas estándar utilizadas para comparar diferentes bibliotecas o diferentes versiones de la misma biblioteca.
Entornos de implementación comunes
Una herramienta de CI/CD permite crear canales de forma sofisticada. Al igual que los programas informáticos, un canal de producción puede contener pruebas y ramificaciones. Mediante la ramificación, puede realizar un conjunto de actividades en el entorno de prueba y otro en el entorno de producción. Puede utilizar la herramienta para instalar automáticamente la base de datos correcta u otro software necesario para diferentes programas.
La CD se superpone con DevOps. En entornos de nube, las herramientas de CD y DevOps crean los sistemas informáticos virtuales de forma automatizada con todos los componentes necesarios para que se ejecuten los programas. Las herramientas automatizadas (a veces llamadas herramientas de orquestación) comprueban las fallas de los sistemas virtuales y los reinician automáticamente.
La función principal de la herramienta CD es iniciar y recorrer cada canal de procesamiento. La herramienta verifica los resultados de cada etapa del canal de procesamiento y decide si continuar o detenerse. La herramienta también permite programar y registrar sus actividades.
A menudo, es necesario ejecutar una tarea repetidamente con pequeñas variaciones. Por ejemplo, los equipos distinguen entre implementar en un entorno de prueba y en producción. Por lo tanto, las herramientas de CD proporcionan parámetros que se pueden completar con diferentes valores cuando se ejecuta la canalización.
A veces, un proceso requiere comandos que tradicionalmente se ingresaban en la terminal. Por lo tanto, una herramienta de CD proporciona mecanismos para ejecutar comandos arbitrarios. Por lo general, proporciona ganchos (hooks) como preprocess
para ejecutar comandos antes de una etapa del pipeline y postprocess
para ejecutar comandos después de una etapa del pipeline.
Jenkins es probablemente la herramienta de código abierto más popular para la orquestación descrita en esta sección.
Ejercicios guiados
-
¿Cuáles son algunas formas de comprobar la seguridad de un programa?
-
¿Por qué escribirías múltiples pruebas unitarias para una sola función del programa?
Ejercicios exploratorios
-
Su equipo ha heredado una aplicación antigua que se ejecuta con lentitud y a la que es difícil agregarle funciones. ¿Cuáles son algunas formas de mejorar la aplicación sin tener que descartarla y escribir una nueva desde cero?
-
En proyectos grandes, con frecuencia, el Equipo A quiere que se implemente una característica en una parte del sistema que mantiene el Equipo B, pero el Equipo B no considera que la característica sea una prioridad. ¿Cómo puede el Equipo A codificar la característica como parte del proyecto del Equipo B?
Resumen
En esta lección se han explicado los tipos de herramientas que se utilizan en el proceso de desarrollo: compiladores y otras herramientas de generación de código, analizadores, pruebas y herramientas de CI/CD que automatizan la integración y la entrega. Existen muchas opciones para cada una de estas actividades, y una herramienta que hoy es popular puede ser reemplazada en un año. Comprender cómo se combinan todas estas herramientas en el proceso de desarrollo le ayudará a identificar lo que necesita.
Respuestas a ejercicios guiados
-
¿Cuáles son algunas formas de comprobar la seguridad de un programa?
Primero, los expertos humanos pueden examinar el código.
Existen muchas herramientas de análisis estático y dinámico para detectar malas prácticas de programación que exponen un programa a amenazas de seguridad.
Otras herramientas envían información maliciosa a los programas en ejecución y verifican sus reacciones.
-
¿Por qué escribiría varias pruebas unitarias para una sola función de programa?
Una función de programa normalmente tiene que ejecutarse en muchas variedades de entrada, y cada variedad merece su propia prueba. Por ejemplo, la función podría manejar un valor de entrada de cero de una manera especial. También necesita anticipar la entrada no válida y escribir pruebas para demostrar que la función la maneja adecuadamente.
Respuestas a Ejercicios Exploracionales
-
Su equipo ha heredado una aplicación antigua que se ejecuta lentamente y a la que es difícil agregarle funciones. ¿Cuáles son algunas formas de mejorar la aplicación, sin descartarla y escribir una nueva desde cero?
Primero, asegúrese de que el proyecto esté bajo control de versiones, si no estaba allí ya.
Después de agregar una nueva función, ejecute pruebas de regresión para determinar dónde falla el programa y asigne programadores para que averigüen qué funciones son responsables. Estas funciones se pueden reemplazar de forma selectiva.
Las pruebas de rendimiento pueden identificar funciones particulares que se ejecutan lentamente, de modo que pueda concentrar sus esfuerzos en corregir o reemplazar el código más ineficiente.
Si el código está en un lenguaje que ya no es popular, considere agregar funciones en un lenguaje preferido por el equipo. Asegúrese de que las funciones en el nuevo lenguaje se puedan integrar con las funciones antiguas.
-
En proyectos grandes, con frecuencia, el Equipo A quiere que se implemente una característica en una parte del sistema que mantiene el Equipo B, pero el Equipo B no ve la característica como una prioridad. ¿Cómo puede el Equipo A codificar la característica como parte del proyecto del Equipo B?
El Equipo B puede permitir que el Equipo A cree una nueva rama, codifique la característica y envíe la rama al Equipo B para que se fusione con su proyecto. Sin embargo, el Equipo A no debe tener la autoridad para hacer lo que quiera. El Equipo B debe proporcionar documentación y ayuda para que el Equipo A siga los estándares del proyecto. Un miembro del Equipo B también debe revisar la presentación del Equipo A y ejecutar todas las formas habituales de pruebas de integración.
Esta forma de colaboración a veces se llama InnerSource, porque se parece al código abierto pero se lleva a cabo dentro de una sola organización.