MAISON CODE .
/ Standards · Refactoring · DX · Philosophy · Mentorship

Código limpio: ingeniería para humanos

El código se lee 10 veces más de lo que se escribe. Una guía técnica sobre denominación, principio de responsabilidad única y por qué el 'código inteligente' es en realidad deuda técnica.

AB
Alex B.
Código limpio: ingeniería para humanos

“Cualquier tonto puede escribir código que una computadora pueda entender. Los buenos programadores escriben código que los humanos pueden entender”. —Martín Fowler.

Esta cita es la base de la cultura de ingeniería específica en Maison Code Paris. No optimizamos para “líneas de código”. No optimizamos la “velocidad de escritura”. Optimizamos para Mantenibilidad.

Al compilador no le importa si le asigna a su variable el nombre x o daysUntilExpiration. La CPU lo ejecuta exactamente en el mismo nanosegundo. Pero el desarrollador junior que se despierta a las 3:00 a. m. para corregir un error crítico se preocupa profundamente. Si tienen que dedicar 10 minutos a descifrar los nombres de las variables, la empresa pierde dinero. Clean Code es un acto de empatía.

Por qué Maison Code habla de esto

En Maison Code Paris, actuamos como la conciencia arquitectónica de nuestros clientes. A menudo heredamos stacks “modernos” construidos sin una comprensión fundamental de la escala.

Discutimos este tema porque representa un punto de inflexión crítico en la madurez de la ingeniería. Implementarlo correctamente diferencia un MVP frágil de una plataforma resistente de nivel empresarial.

1. Denominación: el problema más difícil en informática

Los nombres deben revelar la intención. Un nombre de variable debería indicarle tres cosas:

  1. Qué hace.
  2. Por qué existe.
  3. Cómo se usa.

La regla de “no realizar mapas mentales”

Malo:

constante d = 10; // dias
lista constante = []; // usuarios

El lector tiene que traducir d -> días en su cabeza. Esto utiliza carga cognitiva (RAM).

Bien:

días constSinceLastLogin = 10;
const usuariosactivos = [];

El código se lee como prosa inglesa.

La regla de la longitud del alcance

  • Alcance pequeño (bucle): Los nombres cortos están bien. for (let i = 0; i < 10; i++) está bien.
  • Gran alcance (global/clase): los nombres deben ser explícitos. yo está prohibido. Utilice globalRetryCounter.

2. Funciones: hacer una cosa

El Principio de Responsabilidad Única (SRP) se aplica a funciones, no solo a clases. Una función debe tener un nivel de abstracción.

Malo (La función de Dios):

función asíncrona registrarUsuario(req) {
  // 1. Análisis
  const {correo electrónico, contraseña} = req.body;
  
  // 2. Validación
  if (!email.includes('@')) lanza un nuevo Error('Correo electrónico no válido');
  
  // 3. Lógica de la base de datos
  usuario constante = esperar db.users.create({ 
     correo electrónico, 
     contraseña: bcrypt.hashSync(contraseña) 
  });
  
  // 4. Lógica del correo electrónico
  await mailgun.messages().send({ a: correo electrónico, texto: "¡Bienvenido!" });
  
  // 5. Lógica de respuesta
  devolver {estado: 200, id: usuario.id};
}

Esta función cambia si:

  • La Base de Datos cambia (Postgres a Mongo). *El proveedor de Email cambia (Mailgun a SendGrid).
  • El formato API cambia. Es frágil.

Bien (El Orquestador):

función asíncrona registrarUsuario(req) {
  const accountInfo = parseRequest(req);
  validarCuenta(infocuenta);
  
  usuario constante = espera createUserInDatabase(accountInfo);
  espere enviar correo electrónico de bienvenida (usuario);
  
  devolver formatoRespuesta(usuario);
}

Ahora, “registerUser” es solo un orquestador. Cuenta una historia. Los detalles de implementación están ocultos en funciones pequeñas y enfocadas.

3. Comentarios: El fracaso de la expresión

Los mejores ingenieros escriben menos comentarios, no más. ¿Por qué? Porque Los comentarios son un olor a código. Si tiene que escribir un comentario para explicar qué hace el código, su código es demasiado complejo. Refactorizarlo.

Malo:

// Comprobar si el usuario es elegible para el descuento para personas mayores
if (usuario.edad > 65 && usuario.compras > 10 && usuario.país === 'FR') {
  aplicarDescuento();
}

Bien:

si (usuario.isEligibleForSeniorDiscount()) {
  aplicarDescuento();
}

¿Cuándo comentar?

Comenta el POR QUÉ, no el QUÉ. El código explica lo que sucede. El comentario explica el contexto empresarial o la extraña solución.

// Usamos un retraso de 500 ms aquí porque la API de pago externa
// tiene una condición de carrera si se consulta inmediatamente después de la creación.
// Ver ticket #452.
esperar retraso (500);

Este comentario evita que el próximo desarrollador “optimice” el retraso.

4. Condicionales: Evite el código de flecha

El “código de flecha” ocurre cuando las declaraciones if anidadas crean una forma como una flecha >. Empuja la lógica hacia el lado derecho de la pantalla y dificulta el seguimiento del estado.

Malo:

función procesoPago(pedido) {
  si (orden) {
    si (pedido.estáPagado) {
       if (monto.pedido > 0) {
          // lógica
       }
    }
  }
}

Bueno (Cláusulas de Guardia): Regrese temprano. Elimine la función lo antes posible.

función procesoPago(pedido) {
  si (!pedido) regresa;
  si (!order.isPaid) regresa;
  si (pedido.monto <= 0) retorno;

  // Lógica (sin sangría)
}

5. Obsesión primitiva

No pases cadenas y números sin formato. Pase Objetos que hagan cumplir las reglas.

Malo: función libroVuelo(origen: cadena, destino: cadena) ¿Es válido “NYC”? ¿Es válida “Nueva York”? ¿Es válido “JFK”?

Bien: función libroVuelo(origen: AirportCode, destino: AirportCode) La clase AirportCode garantiza que solo puedan existir en el sistema códigos IATA válidos de 3 letras. Haces que los estados no válidos sean irrepresentables.

7. Pruebas como documentación

La mejor documentación es una prueba unitaria. Los documentos se vuelven obsoletos. Las pruebas no. Si desea saber cómo funciona calculateDiscount(), lea los casos de prueba.

  • it('debería aplicar 10% para nuevos usuarios')
  • it('debería fallar si el carrito está vacío') Escribir pruebas te obliga a escribir código limpio. Si una función es difícil de probar, es un código incorrecto. “No puedo probar esto porque consulta la base de datos dentro de la función”. Refactor: inyecta la dependencia de la base de datos. Ahora es comprobable.

8. La cultura de revisión del código

La revisión de código no sirve para encontrar errores. Para eso está la CI. La revisión del código es para Compartir conocimientos. Es una sesión de tutoría. “¿Por qué elegiste aquí un Conjunto en lugar de un Array?” “Este patrón es interesante, ¿podemos usarlo también en el módulo de Usuario?” Los ingenieros superiores no deberían decir simplemente “LGTM”. Deberían explicar por qué algo es bueno o malo. Requerimos al menos 1 “Quisquilloso” o “Sugerencia” por RP. Obliga al compromiso.

9. La regla de los boy scouts

“Deje siempre el camping más limpio de lo que lo encontró.” Este es el antídoto contra la Deuda Técnica. Estás solucionando un error en el módulo “Precios”. Observa una variable llamada x. Cambiarle el nombre. Observa una función que es demasiado larga. Divídelo. No pidas permiso. No cree un ticket “Refactorización de precios”. Simplemente hazlo como parte de tu trabajo. Si cada ingeniero limpia el 1% del código que toca, la base del código permanecerá impecable para siempre.

7. SECO vs HÚMEDO (La trampa de la abstracción)

Nos enseñan SECO (No te repitas). Es una buena regla. Pero es peligroso. Si ve dos fragmentos de código que parecen similares, los fusiona en una función compartida. El problema: Ahora ambos lugares dependen de esa función. Si la Característica A necesita un ligero cambio en la función, agrega una bandera booleana. función hacerCosa(isFeatureA) Entonces la Característica B necesita un cambio. función hacerCosa(isFeatureA, isFeatureB) Pronto tendrás una función divina con 10 banderas. WET (Write Everything Twice) suele ser mejor. La duplicación es más barata que la abstracción incorrecta. Si dos funciones accidentalmente comparten lógica pero tienen diferentes motivos comerciales para cambiar, copie y pegue el código.

8. La teoría de las “ventanas rotas”

En criminología, si un edificio tiene una ventana rota que no está reparada, los vándalos pronto romperán todas las ventanas. El código es el mismo. Si deja una función desordenada, el próximo desarrollador pensará: “Este archivo es basura de todos modos, simplemente piratearé mi solución”. Si el archivo está impecable, sentirán la presión social para mantenerlo impecable. Sé el jardinero. Elimina el desorden a diario.

9. Conclusión

Clean Code no se trata de estética. Se trata de Economía. El código desordenado se pudre. Se convierte en un “Código heredado” que todos temen tocar. Las funciones tardan más en crearse. Los errores aparecen con más frecuencia. El código limpio es una ventaja. Te permite moverte rápido indefinidamente.


¿El código base es un desastre?

¿Tu velocidad está disminuyendo debido al “Código Espagueti”?

Programar una auditoría de código. Lea sobre Pruebas unitarias y Refactorización.

Clean Code no se trata de estética. Se trata de Economía. El código desordenado se pudre. Se convierte en un “Código heredado” que todos temen tocar. Las funciones tardan más en crearse. Los errores aparecen con más frecuencia. El código limpio es una ventaja. Te permite moverte rápido indefinidamente.

Escribe código para el humano que lo leerá. Porque dentro de 6 meses, ese humano serás tú.

¿El código base es un desastre?

¿Tu velocidad está disminuyendo debido al “Código Espagueti”?

Programar una auditoría de código. Contrate a nuestros arquitectos.