Los ingenieros de software se comunican constantemente a través de múltiples canales: mensajes en Slack, documentos de diseño, hilos de solicitudes de comentarios (RFC) o comentarios en revisiones de código. Sin embargo, existe un medio de comunicación fundamental que a menudo se descuida: el propio código.
El código va más allá de ser un simple conjunto de instrucciones para una máquina. Es un mensaje dirigido a futuros desarrolladores encargados de leerlo, ampliarlo o depurarlo, a compañeros de equipo que revisan el trabajo y también a uno mismo meses después, cuando el contexto inicial se ha desvanecido. Un mensaje en un commit puede entenderse como una conversación en Slack que debe tener sentido independiente: sin hilos anexos, sin posibilidad de preguntar para clarificar y, en ocasiones, leído años después de haber sido escrito.
«El código es un mensaje para tu yo dentro de seis meses, cuando todo el contexto original se ha perdido.»
Este enfoque implica replantear nuestra manera de trabajar. Por ejemplo, al preparar un commit, el objetivo debe ser que se comprenda de forma autónoma. ¿Se puede revisar esta solicitud de incorporación de cambios (pull request) fácilmente y en orden? ¿Explican los comentarios por qué existe el código o simplemente repiten lo que ya dice el código?
El proceso local de desarrollo puede ser caótico e iterativo: experimentar, reescribir y descartar ideas es parte del camino hacia soluciones eficientes. Sin embargo, cuando un cambio está listo para integrarse en la base de código, las reglas cambian. Ya no se trata de un simple fragmento de código modificado (diff), sino de un legado que otros usarán para entender cuándo se modificó un archivo, cuándo se introdujo un error o qué problema trataba de solucionar una petición de cambio. Entonces es vital detenerse y preguntarse: ¿Esta contribución narra una historia que otros puedan seguir sin dificultad?
Una solicitud de incorporación de cambios es una historia
Una forma útil de visualizar una pull request es pensar en ella como un libro donde cada commit es un capítulo y el código modificado dentro del commit, el texto que lo compone. Nadie lee un libro saltando entre páginas aleatoriamente; la secuencia es lo que aporta sentido. Al revisar commits en orden, el revisor debe poder entender el razonamiento sin conjeturas ni la necesidad de retener en memoria todos los cambios simultáneamente.
«Nadie lee un libro saltando páginas al azar. La historia tiene sentido porque el autor fue intencionado con su orden.»
Un ejemplo práctico podría ser esta cadena de commits:
Add search endpoint to API Add basic relevance ranking Extract ranking logic into standalone module Add unit tests for ranking Add integration tests for search endpoint
Siguiendo estos cinco commits en orden, se comprende que se construyó una función de búsqueda, que la lógica de relevancia fue modularizada y que se implementaron pruebas de unidad e integración, todo sin necesidad de una explicación adicional. La propia sucesión de commits cuenta la historia de manera clara.
Para lograr esta claridad, cada commit debe abordar un cambio único y significativo. Un commit que combine renombrar un elemento y modificar su comportamiento no es correcto porque mezcla dos cambios distintos. Los títulos de cada commit son tan importantes como el contenido y deben aportar contexto comprensible. Mensajes como Fix ABC-123 solo remiten a información externa que podría no estar disponible en el futuro.
Es recomendable usar mensajes breves que comiencen con un verbo que describa la acción, como por ejemplo:
- Extraer validador
- Refactorizar: usar validador en formulario
- Corregir: manejar caso límite en envío
Leídos en secuencia, estos mensajes permiten entender la evolución del código.
Durante la revisión, es importante evitar reescribir commits ya existentes mientras la conversación sigue abierta. En su lugar, se deberían añadir nuevos commits que incorporen las modificaciones sugeridas. Cambiar el historial mediante force-push rompe la correspondencia entre los comentarios y las líneas de código, dificultando la revisión. Mantener intacta la historia original y agregar las correcciones encima facilita seguir la evolución de la propuesta para cualquier persona que la revise posteriormente.
El lector al otro lado
Cuando el código se escribe pensando en la comunicación, el revisor pasa de intentar deducir las intenciones a simplemente acompañar una narración. Aunque implica más esfuerzo para el autor, reduce las fricciones para el resto del equipo, especialmente para quienes no participaron en la creación original. En equipos, esta inversión compensa con creces porque una solicitud clara se revisa más rápido, y a largo plazo se dedica menos tiempo a interpretar intenciones y más a valorar las modificaciones concretas.
El revisor no es el único lector relevante. En ocasiones, alguien necesitará volver al código años después para entender por qué existe cierta línea o bloque. Un historial de commits completo ofrece este contexto, mostrando qué commit lo introdujo, la petición de cambio asociada y las decisiones o concesiones de diseño implicadas. Sin ese rastro, es fácil «arreglar» algo que fue intencionadamente diseñado así.
«El código muestra qué sucede. Lo que a menudo no revela es por qué existe, qué limitación está salvando.»
Esta misma idea se refleja en los comentarios dentro del código. Un comentario que señala algo obvio como // incrementa el contador no aporta valor. En cambio, uno que explica razones de diseño o dependencias temporales, por ejemplo, // debe ejecutarse antes de configurar la suscripción para evitar callbacks prematuros, es documentación esencial que puede evitar horas de depuración y prevenir errores.
La importancia de los commits claros en la generación de código con IA
Las herramientas de inteligencia artificial pueden generar código rápidamente, pero esa velocidad no sustituye el contexto necesario. El costo de limpiar código generado por IA suele ser mayor y más alejado de las ganancias de productividad que los equipos anticipan. Por ejemplo, si dejamos que el código generado se incluya en un solo commit gigante titulado «implementar función» sin más detalles, perderemos toda la trazabilidad del razonamiento que hubo detrás.
En cambio, si los agentes de IA siguen las mismas buenas prácticas que los desarrolladores humanos —como realizar commits atómicos con mensajes informativos— se puede hacer legible su razonamiento: qué se construyó primero, dónde se refactorizó, qué se probó y en qué orden. Esto no solo facilita la comprensión, sino que alerta sobre posibles lagunas en la lógica antes de pasar a producción. Por ejemplo, un salto desde «añadir endpoint» a «añadir tests de integración» sin nada intermedio puede ser una señal de que algo se omitió. Un historial limpio es auditable de una forma que un único diff volcado nunca será.
En definitiva, el código sigue siendo un mensaje; simplemente, el autor puede no ser humano.
La estructura también cuenta
Si has prestado atención a esta exposición, habrás notado que cada encabezado anticipa el contenido de la sección, facilitando la navegación y comprensión sin necesidad de leer palabra por palabra. Lo mismo ocurre con mensajes de commit bien estructurados y unas pull requests cuidadas. La estructura es parte fundamental de la comunicación y, cuando se hace bien, no deja lugar a confusiones ni suposiciones por parte del lector.