Codificación prolija y documentación


Codificación prolija y documentación

A lo largo de mi carrera he visto muchas aplicaciones, he creado muchas otras y aprendí una lección valiosa: nadie quiere mantener aplicaciones que NO entienden.

Pero... ¿Qué son aplicaciones que no se entienden? Son aplicaciones que no respetan patrones, que se escriben rápido sin pensar en quién va a tener que mantenerlo, aplicaciones que son hasta difíciles de levantar en un entorno local.

Yo soy alguien que no le gusta vivir con las ventanas rotas, es decir, alguien que si ve algo malo lo va a arreglar. No porque esté malo, sino porque mantenerlo así provocará "vandalismo" y que todo cada vez está peor (simplemente por cascadeo: esto funciona entonces copio y pego; o peor, lo vi en internet así entonces debe ser así).

La codificación y documentación es una gran ventana que fácilmente se puede romper y es por eso que hay que mantener un código prolijo, sano y corregirlo en el momento que se detecta que está empezando a desmoronarse.

No es difícil de realizar esto. A continuación te dejo algunos tips:

  • Aprendé las bases del lenguaje Y framework que estás utilizando. Pero no solo con videos, cursos o a necesidad: leé la documentación que suele dar mejor visibilidad de lo que es capaz, realiza cosas que sean mas que un crud o algoritmos básicos, ponete a prueba y genera tráfico intenso que realmente desafíe tu código.

  • Respeta los principios SOLID, patrones de diseño y de arquitectura. Aprendelos así seas backend o frontend. Te van a facilitar mucho el mantenimiento y comprensión de las aplicaciones en las que te veas involucrado.

  • Codifica lo más posible a un lenguaje natural y lee lo que escribiste, si no lo entendes, volvé a escribirlo. También codifica pensando en los test unitarios ¿Se hacen más fáciles o más difíciles?

Y en este punto me quiero detener.

Lenguaje natural al escribir código y comentarios

Cuando hablamos de documentación me encontré con muchas opiniones distintas, ninguna mejor que la otra pero sí muy diferentes entre sí: que el código se documenta solo, que los test te dan los casos de uso, que la documentación se desactualiza en el tiempo y un montón de excusas más para no documentar nada y que quede todo en la cabeza de una persona durante... unas semanas hasta que agarre otro proyecto.

Imaginemos que somos los nuevos en un equipo, no tenemos experiencia y el equipo se compone por cinco aplicaciones distintas y solo tres personas, incluyéndote. El backlog está lleno de bugs, requerimientos nuevos y el líder está todo el tiempo pidiendo cosas nuevas. Te ponen una tarea importante: cambiar una fórmula que se aplica cada vez que un usuario VIP realiza una consulta_.

Todo empieza bien, bajas el repositorio, tu compañero más o menos te indica como encontrar el código y te encontras con algo así:

type CalculatorOfThings struct{
	User int
	Type int
} 

// quick attention calculation
func (cot CalculatorOfThings) Get() int{
	switch cot.type {
	case 1:
		return 5
	case 2:
		return 10
	case 3:
		return 25
	default:
		return 0
	}
}

Yo te pregunto ¿Sabés qué hace la fórmula? ¿Por qué retorna lo que retorna? Posiblemente lo sepas, por que te lo explicaron. Pero ¿Y si hace un año atrás fuiste vos el que la escribió? ¿Te acordarías?. Personalmente encontrarme con estas situaciones me parece un espanto porque:

  • No se da contexto de nada en el código
  • No se que significan las constantes
  • El switch no especifica cuales son las condiciones.

Y puede parecer extremo, porque es un ejemplo, pero situaciones así se ven día a día en todos los repositorios.

Ahora leelo de la siguiente manera:

type TypeUser int
type PriorityAttention int

const (
	USER_NORMAL TypeUser = 1
	USER_FREQUENT TypeUser = 2
	USER_VIP TypeUser = 3

	NO_PRIORITY PriorityAttention = 0
	PRIORITY_LOW PriorityAttention = 5
	PRIORITY_MEDIUM PriorityAttention = 10
	PRIORITY_HIGH PriorityAttention = 25
)

type CalculatorOfThings struct{
	User int
	Type TypeUser
} 

// Function used by the support shift manager. Soon to be deprecated, it is recommended to use user methods.
func (cot CalculatorOfThings) GetPriorityAttention() int{
	switch cot.type {
		case USER_NORMAL:
			return PRIORITY_LOW
		case USER_FREQUENT:
			return PRIORITY_MEDIUM
		case USER_VIP:
			return PRIORITY_HIGH
		default:
			return NO_PRIORITY
	}
}

El código sin dudas es más largo, sin embargo ahora podemos entender qué está haciendo la struct CalculatorOfThings y su función, sabemos qué es su atributo Type y qué representa cada valor. Además de qué es 0, 5, 10 y 25.

Hacer este tipo de cambios es realmente muy rápido y ayuda no solo a uno como desarrollador, sino a las siguientes personas que deben mantener el código.

Los cambios que hicimos fue:

  • Evitamos el uso de valores mágicos usando constantes. Es decir, nombrar los valores 0, 5, 10, 2 y los types 1, 2 y 3.
  • El comentario APORTA al uso de la función, contextualiza y advierte. Leer lo que hace puede hacerse leyendo el código de la misma, cuando ejecutarla y en qué contexto debe ser parte de la descripción de la función (el comentario). Además, la mayoría de los lenguajes permiten este tipo de comentarios y luego al pasar el mouse por encima podemos entender qué hace, los parámetros que usa, que devuelven... Todo eso lo hace ese comentario.
  • Ahora cuando leemos la función y cada línea de código, tenemos una idea más certera de qué condiciones tiene, cuando lo hace y qué devuelve. Permitiéndonos dar una idea de qué input tenemos que tener, cómo tenemos que ejecutar y qué podemos esperar (facilitando los tests).

Documentación de las aplicaciones

La realidad de las documentaciones es que tienden a desactualizarse muy rápido pero ¿Por qué sucede esto? La respuesta es simple: porque la tratamos como dos cosas separadas, por un lado la aplicación y por la otra la documentación.

Existen muchísimas herramientas que nos permiten tener código bien documentado y necesitamos aprender a usarlas.

Un claro ejemplo de esto es swagger. La cual nos permite tener los endpoints de nuestras aplicaciones documentados y compartir esta documentación permite a otros equipos (incluso a nosotros mismos) saber qué cosas pueden hacer nuestras aplicaciones.

Ejemplo swagger

También tenemos los ya mencionado tooltips de las funciones, que nos muestran qué hace cada función, sus parámetros y sus respuestas:

Tooltip function

Tenemos distintos tipos de documentación que permiten entender el porqué nuestra aplicación hace lo que hace. Como pueden ser los ADR, los RFC e incluso los distintos diagramas UML (¡que son muchos, no uno solo!). Recomiendo tener estos documentos de fácil acceso, referenciado en un lugar visible y si es posible dentro del repositorio del proyecto ¿Por qué? Para darle seguimiento.

Existen otras herramientas, muchas de hecho, incluso específicas para cada lenguaje. Investigar nuevas es responsabilidad de cada uno, pero te aseguro que vale la pena. Mientras más automatizado estén, mejor, nadie quiere escribir documentación y hoy con la IA es mucho más fácil.

Clean CodeDocumentaciónPrincipios SOLIDBuenas PrácticasRefactorizaciónPatrones de DiseñoSwaggerADRTesting
Volver