No fue por desconocimiento: sé que hay que ejecutar las pruebas. El problema era que mi proceso permitía olvidarlo. Y ahí está la trampa, porque la reacción natural ante un error así es prometerse “la próxima vez tendré más cuidado”, que es exactamente lo que falló la primera vez.
Hace poco atendí los cambios que me pidieron en un Code Review. Había ejecutado las pruebas antes de abrir el Pull Request, pero después de modificar la implementación no volví a correrlas. El cambio rompió un test.
Un error que cambia el proceso
Un error deja de ser solamente un error cuando modifica nuestra manera de trabajar. Pero esa modificación tiene que quitarle responsabilidad a la memoria, no sumarle una regla más que recordar.
Por eso dejé de depender de acordarme. Agregué un hook de pre-push que ejecuta las pruebas antes de que cualquier cambio salga de mi máquina. Si un test falla, el push no ocurre.
#!/bin/sh
# .git/hooks/pre-push
xcodebuild test \
-scheme <TuEsquema> \
-testPlan <PlanDelModulo> \
-destination 'platform=iOS Simulator,name=iPhone 16' \
-quiet || exit 1
En un proyecto grande correr toda la suite puede tardar demasiado, así que conviene acotarlo a un test plan del módulo en el que estás trabajando. Y a nivel de equipo, la versión robusta de la misma idea es un pipeline de CI que no permite hacer merge con pruebas fallando. La diferencia con “tendré más cuidado” es que ya no depende de cómo esté yo ese día.
Cada observación debería sobrevivir al Pull Request
Después de recibir suficientes comentarios sobre responsabilidad de funciones, naming, arquitectura, código duplicado, números mágicos o pruebas, algunos empiezan a aparecer antes de que exista el Pull Request. El reviewer se instala, de alguna manera, en nuestra cabeza.
Pero eso no ocurre solo, y cuando ocurre es lento y desordenado. Lo que lo acelera es escribirlo: llevo una lista de las observaciones que recibo en mis reviews. Cuando un tipo de comentario aparece por segunda vez, deja de ser un comentario y se convierte en una pregunta que me hago antes de abrir el PR.
Al revisar esa lista descubrí algo útil: las preguntas se dividen en dos grupos.
Las que se pueden automatizar. ¿Siguen pasando los tests? ¿Introduje un número sin nombre? ¿Rompí alguna convención de estilo? Estas no deberían vivir en mi cabeza, sino en el hook, en el CI o en un linter como SwiftLint. Cada una que automatizo es una que el reviewer ya no tiene que señalar.
// Lo que un reviewer terminaría comentando
if amount > 5000 { showLimitError() }
// Lo que conviene escribir desde el principio
private enum TransferLimits {
static let maxAmount: Decimal = 5_000
}
if amount > TransferLimits.maxAmount { showLimitError() }
Las que requieren criterio. ¿Esta función hace una sola cosa? ¿Su nombre explica lo que hace, o lo que hacía cuando la empecé? ¿Esta lógica pertenece a esta capa o la estoy metiendo donde era más cómodo? ¿Este comentario explica algo que el código no puede decir por sí mismo? Estas no se automatizan, y son las que vale la pena entrenar.
No se trata de conseguir un Pull Request sin comentarios. Un review sin observaciones no necesariamente es un mejor review. El cambio importante es dejar de usar el Code Review solo como mecanismo de corrección y empezar a usarlo como mecanismo de aprendizaje.
El objetivo no es sustituir al reviewer
Anticipar observaciones no significa prescindir de otra mirada. Quien revisa nuestro código tiene un contexto diferente, puede cuestionar decisiones que ya normalizamos y muchas veces detecta consecuencias que no habíamos considerado.
Una pregunta aparentemente sencilla puede revelar una decisión arquitectónica importante: ¿por qué estamos identificando esta entidad por su nombre y no por su ID?
Tal vez haya una razón temporal: servicios que todavía no están disponibles, mocks incompletos o la necesidad de mantener un flujo funcional mientras otras piezas se desarrollan. Eso puede ser válido. Pero el Code Review obliga a convertir una decisión implícita en una decisión consciente: esto funciona para las condiciones actuales, conocemos la limitación y sabemos que deberá cambiar cuando tengamos la información definitiva.
La calidad no siempre consiste en tener de inmediato la solución perfecta. También consiste en saber exactamente qué compromisos estamos aceptando.
Comentarios diferentes
Quizá una señal de crecimiento como developer no sea recibir cada vez menos comentarios, sino recibir comentarios diferentes. Los primeros desaparecen porque ciertas prácticas ya forman parte de nuestra manera de programar, o porque una herramienta se encarga de ellas. Entonces la conversación puede moverse hacia arquitectura, diseño, mantenibilidad, rendimiento o comportamiento del producto.
Por eso pienso que el Code Review no empieza cuando presionamos Create Pull Request. Empieza mucho antes, cuando miramos una función que acabamos de escribir y, antes de continuar, nos preguntamos:
Si este código no fuera mío, ¿qué cuestionaría?