💡 Key Takeaways
- Rule I Follow #1: Functions Should Do One Thing (But I Define "One Thing" Differently)
- Rule I Follow #2: Meaningful Names Are Non-Negotiable
- Rule I Follow #3: Comments Explain Why, Not What
- Rule I Follow #4: Keep Functions and Classes Small (With Nuance)
He estado mirando el código de otras personas durante 14 años como arquitecto de software senior en una empresa fintech de tamaño medio, y puedo decirte exactamente cuándo dejé de ser un fanático del código limpio: fue a las 2:47 AM de un martes en marzo de 2019, cuando nuestro sistema de procesamiento de pagos falló porque alguien había pasado tres días refactorizando un módulo perfectamente funcional para seguir cada una de las reglas del libro del Tío Bob. ¿La ironía? El error se introdujo durante la "limpieza".
💡 Conclusiones Clave
- Regla que Sigo #1: Las Funciones Deben Hacer Una Cosa (Pero Defino "Una Cosa" de Forma Diferente)
- Regla que Sigo #2: Nombres Significativos Son No Negociables
- Regla que Sigo #3: Los Comentarios Explican Por Qué, No Qué
- Regla que Sigo #4: Mantén Funciones y Clases Pequeñas (Con Matices)
Aquel noche cambió la forma en que pienso sobre la calidad del código. No estoy diciendo que los principios del código limpio estén mal—lejos de eso. Pero después de revisar más de 10,000 solicitudes de extracción, dirigir a 47 desarrolladores y lanzar 23 versiones importantes de productos, he aprendido que la adherencia dogmática a cualquier conjunto de reglas es solo otra forma de deuda técnica. Algunas reglas de código limpio son un tesoro absoluto. Otras? Son dependientes del contexto en el mejor de los casos y activamente perjudiciales en el peor.
Aquí está lo que realmente hago en el código de producción, y más importante, por qué lo hago.
Regla que Sigo #1: Las Funciones Deben Hacer Una Cosa (Pero Defino "Una Cosa" de Forma Diferente)
El principio de responsabilidad única para funciones es probablemente la regla más valiosa que sigo religiosamente. Pero aquí es donde me desvío del manual: no mido "una cosa" por líneas de código o el número de operaciones. Lo mido por cohesión conceptual.
El trimestre pasado, revisé una función que tenía 8 líneas pero violaba el SRP espectacularmente. Validaba la entrada del usuario Y registraba el resultado de la validación Y actualizaba una caché. Tres responsabilidades distintas apretujadas en 8 líneas. Compara eso con una función de 45 líneas que escribí el mes pasado que orquesta una transacción de base de datos compleja—hace "una cosa" (completar una transacción de pago), pero esa una cosa requiere múltiples pasos que pertenecen juntas.
Aquí está mi prueba de ácido: ¿Puedo describir lo que hace esta función en una sola oración sin usar la palabra "y"? Si necesito decir "esta función valida la entrada Y envía un correo electrónico," está haciendo dos cosas. Pero si digo "esta función procesa una solicitud de reembolso," y eso involucra naturalmente validaciones, actualizaciones en la base de datos, y notificaciones—eso sigue siendo una cosa al nivel correcto de abstracción.
En práctica, esto significa que mis funciones promedian 25-30 líneas en lugar de las 10-15 que los puristas recomiendan. Pero nuestra tasa de errores en estas funciones es un 40% más baja que en el código sobre-extraído que teníamos antes. ¿Por qué? Porque mantener operaciones relacionadas juntas reduce la carga cognitiva de entender el sistema. Cuando todo está dividido en pequeñas funciones, pasas más tiempo saltando entre archivos que entendiendo la lógica de negocio.
La verdadera victoria aquí es la testabilidad. Una función que hace una sola cosa conceptual es fácil de probar, incluso si tiene 40 líneas. Mocas las dependencias, llamas a la función, afirmas el resultado. Listo. Cuando has extraído todo en funciones de 5 líneas, terminas con pruebas de integración de todos modos porque las pruebas unitarias se vuelven sin sentido.
Regla que Sigo #2: Nombres Significativos Son No Negociables
Moriré en esta colina: los nombres de variables y funciones son la documentación más importante que jamás escribirás. He rechazado solicitudes de extracción únicamente debido a nombres deficientes, y lo haré de nuevo.
"La adherencia dogmática a cualquier conjunto de reglas es solo otra forma de deuda técnica. El mejor código no es el más limpio—es el código que se envía de manera confiable y puede ser mantenido por tu equipo."
Hace dos meses, un desarrollador junior envió un código con una función llamada `processData()`. Lo devolví con un video de Loom de 10 minutos explicando por qué. Esa función estaba validando específicamente los números de tarjeta de pago contra el algoritmo de Luhn. El nombre correcto era `validateCardNumberChecksum()`. Sí, es más largo. Sí, es más específico. Ese es exactamente el punto.
Aquí está mi jerarquía de nombres, refinada durante miles de revisiones de código:
- Variables booleanas: Siempre comienza con is/has/can/should. No `active`, sino `isActive`. No `permission`, sino `hasPermission`.
- Funciones: Verbos para acciones, sustantivos para consultas. `calculateTotalPrice()` no `totalPrice()`. `getUserById()` no `user()`.
- Clases: Sustantivos que representan conceptos, no acciones. `PaymentProcessor` no `ProcessPayments`.
- Constantes: SCREAMING_SNAKE_CASE para constantes verdaderas, camelCase para configuraciones que podrían cambiar.
El impacto es medible. Después de implementar estrictas convenciones de nomenclatura en nuestro equipo hace 18 meses, nuestro tiempo promedio de revisión de PR bajó de 3.2 horas a 1.8 horas. ¿Por qué? Porque los revisores pasan menos tiempo descifrando qué hace el código y más tiempo evaluando si lo hace correctamente.
También impongo una regla de "sin abreviaturas" con exactamente tres excepciones: `id`, `url`, y `api`. Todo lo demás se escribe completo. `usr` se convierte en `user`. `btn` se convierte en `button`. `calc` se convierte en `calculate`. Las teclas adicionales valen la pena cuando alguien está depurando a las 11 PM y no tiene que adivinar qué significa `tmpBfr`.
Regla que Sigo #3: Los Comentarios Explican Por Qué, No Qué
He visto dos extremos en mi carrera: bases de código con cero comentarios y bases de código donde cada línea tiene un comentario. Ambos están mal, pero el código sobre-comentado es en realidad peor porque crea una carga de mantenimiento y a menudo miente.
| Regla del Código Limpio | Cuándo Seguir | Cuándo Ignorar | Impacto en el Mundo Real |
|---|---|---|---|
| Las funciones deben ser pequeñas | Caminos de código con alto tráfico, módulos modificados con frecuencia | Lógica de orquestación compleja, manejo de transacciones | Dividir prematuramente crea sobrecarga de navegación |
| Sin comentarios en el código | Lógica de negocio autoexplicativa | Algoritmos complejos, requisitos regulatorios, optimizaciones no obvias | Falta de contexto cuesta horas en depuración |
| DRY (No Te Repitas) | Lógica de negocio central, transformaciones de datos | Código similar pero contextualmente diferente | La sobre-abstracción crea dependencias frágiles |
| Evitar obs esión primitiva | Modelos de dominio, límites de API | Utilidades internas simples, caminos críticos de rendimiento | El envolvimiento excesivo añade carga cognitiva |
Mi regla es simple: si estás explicando qué hace el código, probablemente el código sea malo. Si estás explicando por qué tomaste una decisión específica, ese es un buen comentario. Aquí hay un ejemplo real de o