Codigo Limpio y Agilidad

¡Fantástico! Todo es ágil hoy en día, todas las empresas aman la agilidad, todo el mundo hace ágil, pero... ¿realmente lo hacen?

Problemas del enfoque en cascada:

Vamos a hablar de la cascada, sí, el chico malo de la ciudad, el que todo el mundo odia. La idea principal de la metodología en cascada es:

Waterfall cycle

  1. Obtenemos los requisitos, lo que queremos hacer, las necesidades de los interesados.
  2. Se planifica cómo hacerlo, a menudo con un análisis y diseño de la solución.
  3. Se implementa, creando software funcional.
  4. Se entrega el software y se espera el feedback, creando documentación durante el proceso.
  5. Mantenimiento de la solución funcional.

Una vez que entregamos la solución, pedimos feedback y si necesitamos cambiar algo, comenzamos todo el proceso nuevamente.

Esto es genial siempre y cuando los requisitos sean super estables y sepamos que no cambiarán durante la implementación, algo que en el mundo real es prácticamente imposible ya que SIEMPRE cambian.

Si fuéramos una tela, no tendríamos ninguno de estos problemas, ya que sabemos los materiales específicos necesarios para crear algo, los colocamos en la máquina, y el resultado siempre será el mismo.

Pero trabajamos con soluciones de software para satisfacer las necesidades de las personas, y estas siempre cambian y evolucionan. Aquí viene el mayor problema con la metodología en cascada. Tenemos que esperar hasta el final de la implementación para recibir comentarios y luego comenzar todo el proceso nuevamente, ¿y qué pasa si las necesidades del usuario han cambiado en el ínterin? Acabamos de desperdiciar mucho tiempo útil.

Una gran analogía es la del piloto de un avión, le gustaría ser informado lo antes posible si hay algún problema con el avión y no esperar hasta que el motor falle, o peor aún, el avión se estrelle para recibir una notificación.

¿Por qué Agile?

Bueno, aquí está el punto: un proyecto es una sucesión siempre en evolución de eventos, ¡por ejemplo, el análisis nunca termina! Por lo tanto, recibir comentarios lo antes posible es la clave principal de la metodología Agile. Aquí, buscamos la participación de los interesados en todo el proceso, entregando la mínima cantidad de funcionalidades esperando una respuesta, esperando que sea positiva; y si es negativa, no hay problema, podemos abordarla lo antes posible sin tener que esperar al fin del mundo para hacerlo.

Entonces, la forma en que las empresas suelen usar Agile es la siguiente:

Agile cycle

  1. Continuamente obtenemos requisitos, y al trabajar en pequeñas funcionalidades, podemos elegir cuáles son las necesidades más críticas e implementar un plan de acción para entregar pequeñas partes que puedan satisfacer este objetivo.

  2. Continuamos haciendo un análisis de los requisitos para preparar el trabajo futuro. La cantidad corresponderá al marco de tiempo que ya decidimos según las necesidades.

  3. Ahora, con todo preparado, estamos cómodos para comenzar a trabajar en nuestras tareas dentro de un sprint. Representa el marco de tiempo que decidimos en el que nos comprometemos a entregar una cierta cantidad de trabajo y puede ser variable según la necesidad.

  4. Entregamos las funcionalidades y continuamos con el proceso nuevamente. La principal diferencia es que comenzamos el trabajo con comentarios de los interesados de la iteración anterior.

Podemos fallar en la entrega dentro de un marco de tiempo ajustado, y eso no es un problema al principio, ya que medimos el equipo y recopilamos comentarios para ajustarnos al siguiente sprint. Después de algunas iteraciones, podemos estimar la cantidad correcta de trabajo que el equipo puede entregar en un cierto contexto.

Por qué piensas que estás haciendo agile pero en realidad ... no lo estás haciendo

Esto es normal, piensas que estás haciendo agile porque tienes reuniones diarias y eso hace que el equipo sea ágil, pero en realidad esa es solo una ceremonia de muchas. No se puede definir si se es ágil o no por las ceremonias que tienen lugar dentro del proyecto, ya que es más bien una forma de pensar.

Puede que estés trabajando en sprints, utilizando scrum, haciendo retrospectivas y todas esas cosas increíbles, pero también puede que estés trabajando en características enormes, no entregando en cada sprint, no aceptando ningún cambio hasta que termines tu trabajo o incluso siendo dueño de tu conocimiento y no compartiéndolo con el equipo. Si te encuentras en cualquiera de estos últimos puntos ... eh ... no estás haciendo agile.

Programación Extrema

Esta es una práctica impresionante que, según R.C. Martin, cofundador del manifiesto ágil y autor de Clean Agile, es la verdadera esencia del mismo.

Consiste en la organización de prácticas en tres anillos llamados el "Círculo de la Vida". Cada anillo representa un aspecto diferente del desarrollo de proyectos:

Extreme Programing

El "Anillo Exterior" representa el aspecto empresarial y contiene todas las prácticas enfocadas en los negocios que, juntas, crean el ambiente perfecto para el desarrollo de proyectos.

El "Anillo Intermedio" representa el aspecto del equipo y contiene todas las prácticas enfocadas en el equipo para mejorar la colaboración e interacción del equipo:

El "Anillo Interior" representa el aspecto técnico, que contiene todas las prácticas relacionadas con la mejora del trabajo técnico.

TDD

TODO el mundo odia hacer pruebas, por ejemplo, los clientes odian PAGAR a las empresas por el "desperdicio" de tiempo de sus desarrolladores Front-End haciendo pruebas, y al final... dinero. Entonces, ¿por qué nosotros, los "desperdiciadores" de tiempo y dinero, deberíamos querer implementar pruebas, verdad?

Bueno, hay algunas cosas en mi mente que pueden compensar todo ese odio:

  1. Calidad del código
  2. Mantenimiento del código
  3. Velocidad de programación (sí, estás leyendo este punto correctamente)

Comprensible, ¿verdad? Escribimos pruebas para que pasen los casos de uso, para escribirlas debemos estar organizados porque si no... será imposible probar nuestro código. Pero hay cosas que considerar, ¿cómo escribimos pruebas de manera que realmente aumente la calidad de nuestro código de alguna manera significativa?

Primero, veamos qué significa calidad de código, y luego les diré lo que significa para MÍ la calidad del código.

Si buscas una respuesta, esta es la que encontrarás:

"Un código de calidad es uno que es claro, simple, bien probado, libre de errores, refactorizado, documentado y con buen rendimiento".

Ahora bien, la medida de la calidad depende de los requisitos de la empresa y los puntos clave suelen ser la confiabilidad, mantenibilidad, testabilidad, portabilidad y reutilización. Es realmente difícil crear código con un 100% de calidad, incluso Walter White no pudo crear metanfetamina con más del 99,1% de pureza; surgirán problemas de desarrollo, plazos y otras situaciones de contexto y tiempo que pondrán en peligro la calidad de tu código.

No puedes escribir código legible, mantenible, probable, portable y reutilizable si te apresuran a terminar una tarea de 4 puntos de historia en solo una mañana (realmente espero que no sea tu caso, y si lo es... ¡tú puedes!)

Entonces, aquí va lo que significa calidad de código para mí. Hacerlo es una mezcla de hacer lo mejor con las herramientas actuales, buenas prácticas y experiencia, contra los límites de contexto existentes para crear el código más limpio posible. Mi recomendación a todos mis estudiantes es que primero alcancen el objetivo y luego, si tienen tiempo, lo usen para mejorar la calidad tanto como sea posible. Es mejor entregar algo feo que una funcionalidad incompleta, pero hermosa. La calidad de tu código aumentará con tu experiencia en el camino, a medida que ganes más, sabrás los mejores pasos para alcanzar un objetivo en la menor cantidad de tiempo y con las mejores prácticas.

El código de calidad también se relaciona con el nivel de comunicación que puedes proporcionar a tus compañeros de equipo o cualquier persona con una simple mirada. Es fácil ver un código y decir "¡wow, esto es genial!" y también decir "¡wow, qué desorden!". Así que cuando codificas, debes pensar que no eres el único trabajando en ello, incluso si trabajas solo como un ejército de desarrollador único, eso ayudará mucho.

Permíteme darte algunas herramientas para escribir un mejor código, primero abramos un poco tu mente.

Diseño atómico, punto de vista de Front End

Separa tu código en la cantidad mínima de lógica posible, cuanto más pequeño sea el código, más fácil será de probar. Esto también trae más beneficios, como la reutilización del código, un mejor mantenimiento e incluso un mejor rendimiento; a medida que el código se vuelve más pequeño y mejor organizado y dependiendo del lenguaje / marco que usemos, podríamos terminar con menos ciclos de procesamiento.

El mantenimiento mejorará enormemente, ya que estamos codificando pequeñas piezas de trabajo, cada una con el acoplamiento más suelto y la cohesión más alta posible, podemos rastrear y modificar el código con el mínimo número de problemas.

Déjame mostrarte cómo pensar atómicamente y cómo puedes llegar a una aplicación completa a partir de una pequeña entrada.

Primero tenemos nuestra entrada:

Input example

Cosas simples, eso es lo que llamamos un Átomo, la mínima pieza de lógica posible. Si lo codificas de forma atómica, puedes reutilizar esta entrada en cualquier lugar de tu aplicación y, más adelante, si necesitas modificar su comportamiento o apariencia, simplemente modificas un pequeño átomo con el resultado de tener un impacto en toda la aplicación.

Ahora, supongamos que agregas una etiqueta a esa entrada:

Input with label example

¡Felicidades! Ahora tienes lo que se llama una Molécula, la mezcla entre átomos, en este caso una etiqueta y una entrada. Podemos seguir avanzando y reduciendo la granularidad.

Podemos usar la entrada con la etiqueta dentro de un Formulario para crear un Organismo, la mezcla entre moléculas:

Organism example

Si mezclamos Organismos, obtendremos una Plantilla:

Template example

Y una colección de plantillas crea nuestra Página, y luego, usando la misma lógica, nuestra Aplicación.

Usar esta forma de pensar hará que tu código sea realmente mantenible, fácil de navegar para rastrear errores y, más que nada... ¡fácil de probar!

Si escribes algo que no sea un Átomo, sería muy difícil probar cualquier cosa, ya que la lógica tendría un alto acoplamiento y, por lo tanto, sería imposible separarla lo suficiente como para verificar casos específicos.

Un ejemplo sería probar un código altamente acoplado, para validar solo una cosa simple, uno tendría que comenzar a incluir una pieza de código... y luego otra... y otra, y después de que termine, verá que incluyó casi todo el código porque había demasiadas dependencias de un lugar a otro.

Y esa es la clave para incluir un jugador más valioso en todo esto.

Programación Funcional

La programación funcional es un paradigma que especifica formas de programar de manera que dividimos nuestra lógica en métodos declarativos, sin efectos secundarios. De nuevo...piensa de manera atómica.

Cuando comenzamos a aprender a programar, normalmente lo hacemos de manera imperativa, donde la prioridad es el objetivo y no la forma en que lo alcanzamos. Aunque es más rápido que la programación funcional, que lo es, puede traer muchos dolores de cabeza aparte de dejar de lado todos los beneficios de la otra forma.

Escribamos una comparación en JavaScript.

Forma imperativa de buscar un elemento dentro de un array:

var exampleArray = [
	{ name: 'Alan', age: 26 },
	{ name: 'Axel', age: 23 },
];

function searchObject(name) {
	var foundObject = null;

	var index = 0;

	while (!foundObject && exampleArray.length > index) {
		if (exampleArray[index].name === name) {
			foundObject = exampleArray[index];
		}

		index += 1;
	}

	return foundObject;
}

console.log(searchObject('Alan'));

// { name: 'Alan', age: 26 }

Y ahora la manera funcional de alcanzar el mismo objetivo:

const result = exampleArrayMap.find(element => element.name === name);

console.log(result);

No solo es más corto, sino que también es escalable. El método map que estamos aplicando al array es declarativo de ECMAScript, lo que significa que cada vez que ejecutamos el método con los mismos parámetros, siempre obtendremos el mismo resultado. Tampoco modificaremos nada fuera del método, eso es lo que se llama efectos secundarios, el método devuelve un nuevo array con los elementos que cumplen la condición.

Por lo tanto, si creamos métodos que representen las unidades mínimas de lógica posibles, podemos reutilizar el código funcional y probado en toda la aplicación y mantenerlo si es necesario. Una vez más... piensa de manera atómica.

Ahora que sabemos la forma de pensar para crear un código de alta calidad y fácil mantenimiento, pasemos a lo que es una Historia de Usuario.

Historia de Usuario y TDD

¡Vaya título! Todos conocen las historias de usuario, cómo definirlas, qué hacer con ellas, pero nadie sigue la misma forma de escribirlas o incluso su estructura.

Una historia de usuario es la explicación de una funcionalidad desde el punto de vista del usuario. Normalmente se ve así:

¿Qué? Como usuario (quién), quiero tener la posibilidad de... (qué) para... (por qué)

¿Cómo? (casos de uso) 1- paso 1 2- paso 2 3- paso 3 ...

Como puedes ver, definimos quién...el usuario, lo que quiere hacer...la funcionalidad, por qué queremos esta funcionalidad...lo que mientras lo escribimos incluso podemos descubrir que no tiene sentido crearla porque el objetivo no está claro, y cómo la crearemos...los casos de uso.

Los casos de uso representan el número de requisitos que necesitamos cumplir para decir claramente que una historia de usuario está terminada, normalmente cuentan la historia del camino feliz a seguir. También hay lugares donde se describen las entidades relacionadas con la historia de usuario y los casos extremos (camino triste) y creo que es una práctica realmente buena, pero al igual que al escribir código de alta calidad...necesitamos identificar los límites de nuestro contexto para ver cómo podemos escribir el contenido lo más específico posible sin transformar nuestra tarea en un documento difícil de seguir y consumir.

Ahora, TDD, Desarrollo Guiado por Pruebas, es un proceso donde definimos nuestras pruebas antes incluso de escribir una sola línea de código, así que...¿cómo probamos algo que ni siquiera está creado? Bueno, esa es la magia de esto, puedes tomar tus casos de uso y definir lo que necesitas para cumplir cada uno de ellos, crear pruebas alrededor de ellos, hacer que fallen y luego arreglarlos para que pasen...así de simple.

La idea principal detrás del TDD es pensar en:

  1. ¿Qué quieres hacer?
  2. ¿Cuáles son los requisitos principales?
  3. Escribir pruebas que fallarán a su alrededor.
  4. Crear tu código sabiendo lo que quieres hacer.
  5. Hacer que la prueba pase.

Si piensas que las pruebas son consumidoras de tiempo, bueno, lo son, pero porque tal vez lo hayas hecho previamente de la manera clásica y mala de codificar todo primero y luego intentar probar tu código. ¿Recuerdas de lo que hablábamos sobre la calidad del código, las buenas prácticas, etc.? Bueno, esos son los elementos principales que te ayudarán a probar tu código y si no los estás implementando correctamente, terminaremos con una funcionalidad imposible de separar y probar.

Es por eso que codificar sabiendo lo que quieres probar, utilizando la programación funcional y una forma de pensar atómica puede ser tan beneficioso, porque estarás creando lógica, identificando los requisitos y al final...aumentando la velocidad de codificación.

Así que aquí está, la prueba también ayuda a aumentar la velocidad de codificación, a medida que escribes código más manejable, es más fácil modificar un requisito (caso de uso) de tu funcionalidad, ya que lo has identificado mediante una prueba que te dirá si tu refactorización fue correcta. También reduce la posibilidad de errores, por lo que se dedica menos tiempo a solucionar problemas más adelante.

Flujo del TDD:

TDD flow

Aquí hay un flujo TDD sobre cómo mejorar la calidad del código sin romper nada:

TDD code quality improvement