Páginas

Mostrando entradas con la etiqueta Devops. Mostrar todas las entradas
Mostrando entradas con la etiqueta Devops. Mostrar todas las entradas

viernes, 17 de marzo de 2023

La economía del software según J. B. Rainsberger

Este artículo está basado en una conferencia de 2019 titulada “The economics of software design” de J.B. Rainsberger y que está disponible en Youtube en ver conferencia .

Lo que aquí relato es mi libre interpretación de lo que cuenta Rainsberger, lo digo porque puedo estar equivocada y tergiversar sus palabras. O sea son mis palabras, no las suyas, por si acaso. Es para que no me pase lo mismo que al tipo de la cola del cine en la película “Annie Hall” cuando habla sobre el trabajo de Marshall MacLujan ver escena.

El objetivo de la conferencia es explicar porque son necesarias prácticas ágiles a la hora de desarrollar software. Rainsberger con mucho talento sigue un hilo sólido que explica a desarrolladores y no desarrolladores porqué usar practicas ágiles va a mejorar los sistemas de información.

Rainsberger dice que hay tres asuntos importantes en los que hay que centrar la atención cuando se desarrolla software:

  • Las funcionalidades desarrolladas (Features)
  • El diseño del software (Design)
  • La retroalimentación (Feedback)

Funcionalidades desarrolladas

La refactorización es la piedra angular del desarrollo de código. Esta refactorización facilita mejorar el coste marginal. El coste marginal es un término financiero que se puede definir como el incremento de coste al producir N+1 unidades de determinado producto, respecto al coste de producción de N unidades. Llevando esto al mundo software, se puede traducir en el coste de añadir una nueva funcionalidad o cambiar una funcionalidad ya existente. Es menor de añadir o modificar funcionalidades si el sistema está bien diseñada, es decir no es un galimatías. Los patrocinadores del software (financiero de la empresa u organismo) entienden de costes marginales, los desarrolladores de diseño del software. Entonces, si para tener un mejor coste marginal es necesario refactorizar los promotores entienden que refactorizar es necesario, los desarrolladores ya lo saben. La forma de refactorizar constantemente es utilizar TDD (Test Driven Development).

Diseño del software

Para su exposición Rainsberger utiliza el siguiente gráfico.

Aquí la curva representada por g representa el aumento del coste de seguir modificando un sistema que no se desarrolla con “Diseño Evolutivo”. Inicialmente desarrollar el sistema es menos costoso, pero con el tiempo el coste de mantenerlo se eleva exponencialmente, según Rainsberger siguiendo el comportamiento del interés compuesto según Bernoulli, de hay la formula (1+1/n)ⁿ -> e. Sin embargo la curva representada por f corresponde a los sistemas que se desarrollan con “Diseño Evolutivo” (básicamente empleando TDD), en estos el diseño está mejorando constantemente y eso contribuye a que aunque cada vez el sistema sea más complejo el crecimiento de costes sea mucho más moderado. En términos más vulgares que el galimatías sea menor, aunque la complejidad sea mayor.

También dice Rainsberger que el punto t₀ en el caso de los sistemas que no se desarrollan con "Diseño Evolutivo" es el momento en que económicamente es más rentable tirar el sistema y hacerlo de nuevo. Cómo según él nadie sabe calcular cuando llega ese momento, es mejor trabajar con “diseño evolutivo” para evitar el desastre.

Retroalimentación

En cuanto a la producción del software existe un modelo clásico llamado “En cascada” que implica las fases:

Requisitos -> Análisis-> Diseño-> Codificación -> Pruebas -> Puesta en marcha

En este modelo la retroalimentación se ejecuta demasiado tarde. Esto provoca que la cantidad de re-trabajo suela ser ingente porque cuando algo no se ajusta a lo esperado ya hay mucho que cambiar.

En “XP (eXtreme Programming de 1999)” se expuso que era mejor realizar un ciclo de desarrollo y pruebas constante que pusiera en evidencia si lo que se estaba desarrollando era lo que se necesitaba. XP y a continuación Agile aconsejan prácticas que mejoran la retroalimentación: pequeños ciclos de desarrollo, pruebas unitarias para conocer el estado interno del sistema y pruebas de aceptación para saber si el sistema está de acuerdo con las necesidades del usuario.

Rainsberger expone que las técnicas para llevar esto a cabo son TDD y BDD. También las prácticas de DevOps ayudan a la retroalimentación y facilitan la labor coordinada de los equipos de desarrollo y operaciones.

Conclusiones

Esta conferencia apoya de forma empírica y heurística el desarrollo basado en técnicas ágiles.

No hay fórmulas mágicas, pero desarrollar software no es fácil y yo también estoy convencida de que todas las prácticas ágiles contribuyen a que el mundo del desarrollo de software mejore.

Buenas noticias, eso nos beneficia a todos a los informáticos y a los no informáticos.

domingo, 5 de abril de 2020

Cómo usar Git y GitHub


Git es un repositorio distribuido. Esto quiere decir que cada desarrollador tiene un repositorio instalado en local. Además hay un repositorio común donde compartir el código, en el caso que nos ocupa el repo común será un proyecto en GitHub.

El proyecto GitHub tiene una rama principal llamada master, esta va a contener la última versión del código funcionando. Se pueden crear ramas para distintos desarrollos pero en esta forma de uso solo se va a trabajar con la rama master.

Pasos a seguir para trabajar con Git y GitHub en el proyecto politicagitgithub:


Primera vez. Para crear el repositorio local git y descargar el contenido del repositorio de GitHub a local

-     Instalar Git. Para ello descargar un fichero ejecutable desde https://git-scm.com/downloads, el fichero a descargar depende del sistema operativo en el que queremos instalar Git. Se ejecuta y para asegurar la correcta instalación, ir a una pantalla de comandos y ejecutar el comando git --versión,  el sistema muestra la versión de Git instalada.

-          Para contener el repositorio local del proyecto se crea una carpeta en el sistema de archivos. En esta carpeta se crea el repositorio local con git clone de la siguiente manera:

1.       Acceder a la URL https://github.com/MarisaAfuera/politicagitgithub.
2.       Pulsar  el botón  "Clone or download"y entonces se muestra la pantalla:

 
3.     Copiar la URL y abrir una ventana de git bash que se habrá instalado con git. Situarse en la carpeta del proyecto yejecutar el comando:

git clone https://github.com/MarisaAfuera/aficionbaloncesto.git


Para el trabajo del día a día

Cuando un desarrollador va a empezar un trabajo sobre el código, lo primero que hace es traer (pull) a su repo local la última versión que hay en la rama master de GitHub. Para ello utilizar el  comando git pull origin master.

Después en local (su equipo) crea una rama para empezar a desarrollar lo que corresponda. Para crear la rama en la que va a trabajar usa el comando git checkout –b .

Trabaja añadiendo, modificando y borrando código en la rama creada en local. Cuando acaba ejecuta los comandos:


  •  git add . Este comando añade al repositorio local en la rama actual los ficheros nuevos, elimina los borrados y cambia los modificados.
  •  git commit –m “<motivo de los cambios>”. Este comando compromete (los da por buenos)  los cambios en local y los marca con el mensaje que escribimos en “motivo de los cambios”.
Ahora hay que integrar los cambios con el código de los demás desarrolladores llevando los cambios al repositorio remoto, en este caso GitHub. Para ello se  comunica al equipo que se va a realizar un “merge” a master de GitHub. El objetivo es que mientras se hace este merge, ningún otro integrante del equipo interfiera haciendo cambios a master. Para integrar los cambios realizados con el código que hay actualmente en master se ejecutan los siguientes comandos:

  •  git checkout master. Para volver a master del repo local.
  •  git pull origin master. Para traer al repo local los últimos cambios a master del repo compartido en GitHub.
  •  git merge nombre-de-rama. Para mezclar los cambios de la rama del repo local con el código en master.  Pueden surgir conflictos que se deben resolver para realizar el merge, algunos conflictos tendrán que ser resueltos en colaboración con otros integrantes del equipo.
  •  git push origin master. Para llevar los cambios a master de GitHub.

Conclusión

Esta es una posible forma de uso de Git y GitHub para el control de versiones del código y la documentación de un proyecto. Esta en una forma muy sencilla de uso de estas herramientas. La política de uso que se emplee en cada caso será algo que los equipos de desarrollo deben acordar cuando aborden un proyecto de desarrollo.
 

domingo, 23 de febrero de 2020

Qué es el "Chaos Monkey"


Chaos Monkey es una herramienta software que de forma aleatoria detiene instancias y contenedores que están ejecutándose en el entorno de producción. El objetivo es exponer a los sistemas a fallos para ayudar a los ingenieros a proveer servicios que sean capaces de reaccionar a caídas y otros problemas inesperados.

La herramienta es de uso libre y se puede descargar en https://github.com/Netflix/chaosmonkey

Gareth Bowles, antiguo empleado de Netflix, en su presentación de 2015  "I Don't Test Often ... But When I Do, I Test in Production" que se puede consultar en https://www.youtube.com/watch?v=xkP70Zhhix4 explica los motivos que condujeron a Netflix a desarrollar una herramienta basada en la ingeniería del caos.

Gareth explica que debido a las características del servicio que proporciona Netflix, se hacía muy difícil probar en un entorno que no fuese el de producción. A veces la cuota de internet que ocupan los clientes de Netflix supone hasta un 34% del total del tráfico de Internet. Simular esto en un entorno de pruebas era imposible.

Entonces se les ocurrió que podían hacer varias cosas:
  1. Chaos Monkey
  2. Coverage en producción
  3. Canary deployment

1. Chaos Monkey 

Es una herramienta software que provoca la caída de servicios en producción. De esta forma los ingenieros pueden experimentar las consecuencias de la caída y aprender a que hacer para preveer los efectos no deseados de la caída. Las caídas provocadas se hacen a horas de trabajo, donde todos los ingenieros están en la oficina y pueden ponerse manos a la obra para arreglar los problemas inmediatamente. Esto es una ventaja frente a caídas fuera de horas, que hacen que los desarrolladores y operadores tengan que salir corriendo y trabajar a deshoras o en jornadas interminables.

Cómo Chaos Monkey funcionó bien, se decidieron a desarrollar otros monkeys: Chaos Gorilla simula la caida de una zona completa de servidores y Chos Kong de una región que agrupa zonas. 

También idearon otros monkeys que por ejemplo degradan el tiempo de respuesta Latency Monkey o simulan que un servidor no cumple los estándares de configuración Conformity Monkey.

2. Coverage en producción

Es una forma de telemetría, en la que se mide que líneas de código se ejecutan en producción y cuantas veces se ejecutan.
Estas mediciones permiten saber cúal es la parte de código que se debe de probar más porque se ejercita más veces. Es decir, se pueden planificar, construir y ejecutar pruebas más efectivas.

3. Canary deployment


Se trata de desplegar software inicialmente en solo algunos servidores. Con este despliegue se comprueba si el nuevo software responde a las expectativas: funciona bien, no degrada el servicio, los usuarios lo encuentran útil, etc. El nombre de este tipo de despliegue proviene del uso de canarios en las minas para controlar la calidad del aire. En el caso de que el canario se viese afectado por la calidad del aire, las personas tenían tiempo de escapar antes de que la mala calidad del aire les afectase a ellos.

Una vez comprobado que el software cumple con las expectativas se procede a desplegarlo en el resto de los servidores. O no desplegarlo si no cumplió las expectativas.

Conclusión

Estas iniciativas han contribuido al éxito de Netflix que sin duda es una plataforma ampliamente utilizada. Por lo tanto aprendamos de ellos y quizás en otros ámbitos algunas de estas técnicas puedan usarse para ayudar a mejorar.

miércoles, 25 de septiembre de 2019

Test Driven Development: ¡Además mejora el diseño!

Se puede escribir el código de las aplicaciones pensando que lo único importante es que se construya en el menor tiempo posible y con el menor coste. Esta forma de proceder, ha quedado patente durante los 70 años que se lleva escribiendo software, que lleva a aplicaciones que son difíciles de mantener, y el mantenimiento de las aplicaciones es, a menudo, una etapa de larga duración en el ciclo de vida de las aplicaciones.

Para que sea fácil arreglar los errores que surjan en las aplicaciones (webs, apps, microservicios, apis, etc.) es necesario que el software esté bien diseñado. Son muy peligrosos los códigos espagueti llamados así porque todo está enmarañado como en un plato de espaguetis. En estos casos los cambios de cualquier tipo son muy peligrosos porque son muy propensos a errores. Es difícil buscar errores o donde se hacen las cosas si se trata de modificar una funcionalidad. También es difícil de prever las consecuencias de modificar una parte de código, en cuanto a las consecuencias que esto tendrá en el resto del sistema.

Por todo esto la técnica de desarrollo Test Driven Development (TDD) puede venir a ayudar. TDD es una forma de desarrollo que por sus características mejora dos aspectos muy importantes del código: se tienen que construir y ejecutar constantemente las pruebas unitarias automatizadas y el diseño de los sistemas construidos mediante esta técnica tiende a ser "bueno".

Tener pruebas unitarias es bueno porque nos sirven de red de seguridad de nuestro código. Cuando cambiamos algo, podemos comprobar si las pruebas unitarias se siguen ejecutando con éxito. En caso contrario tenemos una alarma que detecta que algo en el cambio no ha ido bien.

Que el diseño sea "bueno" hace que los desarrolladores puedan comprender mejor el código y este pueda ser modificado con más versatilidad.

Existen numerosas aproximaciones para hacer buenos diseños en ingeniería del software. Hay recomendaciones generales y otras enfocadas a algún paradigma de programación en particular. Algunos consejos generales para un buen diseño son:
  • Poco acoplamiento y mucha cohesión. Dos principios fundamentales de la ingeniería del software
  • No hagas lo que no necesitas: You Ain't Gonna Need It (acrónimo YAGNI.
Para más información ver el artículo de Martin Fowler's disponible en http://martinfowler.com/bliki/Yagni.html.
  • Reutiliza el código Don't Repeat Yourself (Acrónimo DRY) 
  • Keep it simple, stupid. Keep it simple, stupid (Acrónimo KISS)
  • Algunos principios para la programación orientada a objetos son los principios SOLID. Solid es un acrónimo formado con las palabras: Single responsability, Open-Close, Liskov substitution, Interface segregation y Dependency inversion. 

Con el objetivo de demostrar que TDD es una técnica de programación que ayuda a obtener buenos diseños de código, Alex García y Viktor Farcic en su libro Test-Driven Java Development, presentan una Kata TDD basada en el juego Conecta4.

La Kata consiste en hacer dos desarrollos del mismo juego, uno sin seguir TDD y otro siguiendo esta técnica de programación. El código de ambos desarrollos se puede descargar en  https://bitbucket.org/vfarcic/tdd-java-ch05-design.git

Conecta 4 es un juego de 2 jugadores en el que se dispone de un tablero de 7 columnas por 6 filas. Los jugadores juegan por turnos introduciendo sus fichas por la parte de arriba de cada columna. Las fichas se amontonan en las columnas. Gana el jugador que consigue colocar 4 fichas de su color en línea, ya sea vertical, horizontal o diagonal. Para más datos sobre las reglas del juego https://es.wikipedia.org/wiki/Conecta_4

Analizando el código descargado de bitbucket de ambas versiones se aprecia que efectivamente el diseño es distinto. Ambas implementaciones se resuelven en una clase escrita en Java, pero los métodos difieren. Para ilustrar esto se muestran los dos figuras siguientes. Una muestra los métodos empleados en la Kata no TDD


La  otra muestra los métodos empleados en la Kata TDD

Análisis de las diferencias entre las Katas

En las figuras se muestra mediante diagrama de secuencia los métodos que tiene cada una de las clases. Las flechas a la derecha representan las llamadas entre métodos.
 
La kata TDD resuelve con 9 métodos frente a la no TDD que se resuelve con 6. Este hecho ya tiene un aroma de mejor diseño. ¿Por qué? Pues por qué esto indicar que cada método hace menos cosas y por lo tanto es más sencillo. Pero detallando más ¿Qué tiene el diseño de connect4TDD que le hace mejor que el de connect4?
  • La modularización de las funciones se ha hecho adecuadamente esto cumple el principio "single responsability". Los métodos tienen una única misión cuya funcionalidad está bien encapsulada. Por ejemplo, hay un método checkPositionToInsert() que se encarga de comprobar si hay espacio en la columna para una nueva ficha. En la versión que se hizo sin TDD este método no existía y por lo tanto esta responsabilidad estará incluida en algún método que además hará más cosas o sea tendrá más responsabilidades.
  • Los métodos que hacen menos cosas cumplen el consejo KISS-Mantén el código lo más sencillo posible. Al tener más métodos cada uno tendrá menos funcionalidades que abordar y será más sencillo.
  •  Cumple el consejo YAGNI- No lo pongas si no lo necesitas, al implementar el código tras implementar la prueba unitaria, solo se codifica lo estrictamente necesario para que la prueba se ejecute con éxito. No hay código superfluo.
  • En el conector de Connect4TDD se ha incluido un argumento tipo PrintStream para especificar cúal es el canal de salida. De esta forma si se quiere hacer uso de la clase para mostrar el tablero por un PrintStream distinto a System.out se puede hacer simplemente indicando el canal al construir el objeto de la clase Connect4TDD. Esto se puede entender cómo un desacoplamiento de Connect4TDD y el canal de salida. Sin ser exactamente inyección de dependencias, está relacionado con este principio.

Conclusiones 

Emplear la técnica TDD mejora el diseño de las aplicaciones y proporciona aplicaciones que se pueden probar de forma automatizada. 

En el canal DevOps es fundamental de disponer de pruebas automatizadas para optimizar el trabajo de los equipos de desarrollo y operaciones. Esta técnica pone pues una primera piedra para realizar mejorar que consiguen que las áreas de tecnologías de la información sean más productivas y por consiguiente más competitivas.