Clean Code en JavaScript: principios y ejemplos para Node.js
El código limpio no es solo un término de moda, sino un principio fundamental del desarrollo profesional. En el mundo de JavaScript, especialmente en el ecosistema de Node.js, donde el código a menudo se escribe rápido y en grandes volúmenes, seguir los principios de Clean Code se vuelve críticamente importante. En este artículo, analizaremos los conceptos principales que te ayudarán a escribir código que sea fácil de leer, mantener y escalar.
¿Por qué es importante el código limpio para JavaScript y Node.js?
JavaScript es un lenguaje dinámico con tipado flexible. Esto es tanto su fortaleza como su debilidad. Sin reglas estrictas, es fácil crear "código espagueti" que funciona, pero que es imposible de entender después de un mes. En Node.js, donde el código a menudo maneja solicitudes asíncronas y lógica de negocio compleja, la limpieza del código afecta directamente la velocidad de depuración y el costo de mantenimiento del proyecto.
El código limpio es una inversión en el futuro de tu proyecto. Reduce la cantidad de errores, simplifica la incorporación de nuevos desarrolladores y hace que la refactorización sea menos dolorosa.
Principio 1: Nombramiento de variables y funciones
La regla más simple y más importante: da nombres con significado. El nombre debe responder a las preguntas "¿qué es esto?" o "¿qué hace?". Evita las variables de una sola letra (excepto para índices de bucles) y las abreviaturas.
Mal ejemplo:
const d = new Date(); // ¿qué es d?const fn = (a, b) => a + b; // ¿qué estamos sumando?Buen ejemplo:
const currentDate = new Date();const sumPrices = (price1, price2) => price1 + price2;Para funciones, usa verbos (get, set, calculate, fetch, validate). Para variables, usa sustantivos (user, orderList, config). Para valores booleanos, usa prefijos is, has, should.
const isUserActive = user.status === 'active';const hasPermission = user.role === 'admin';Principio 2: Las funciones deben ser pequeñas y hacer una sola cosa
El Principio de Responsabilidad Única (Single Responsibility Principle) se aplica no solo a las clases, sino también a las funciones. Si una función hace más de una acción, divídela.
Mal ejemplo (la función lo hace todo):
function processUserData(user) { // Validación if (!user.email || !user.name) throw new Error('Invalid user'); // Formateo const formattedName = user.name.trim().toUpperCase(); // Guardar en la BD db.save({ ...user, name: formattedName }); // Enviar email emailService.sendWelcome(user.email); return true;}Buen ejemplo (separación de responsabilidades):
function validateUser(user) { if (!user.email || !user.name) throw new Error('Invalid user');}
function formatUserName(name) { return name.trim().toUpperCase();}
async function saveUser(user) { await db.save(user);}
async function sendWelcomeEmail(email) { await emailService.send(email);}
async function processUserData(user) { validateUser(user); const formattedName = formatUserName(user.name); await saveUser({ ...user, name: formattedName }); await sendWelcomeEmail(user.email);}Esta estructura permite probar fácilmente cada parte por separado y cambiar la lógica sin riesgo de romper todo a la vez.
Principio 3: Evita el anidamiento profundo y los números mágicos
El anidamiento profundo (callback hell o múltiples if/else anidados) hace que el código sea ilegible. Usa retorno temprano (early return) y cláusulas de guarda (guard clauses).
Mal ejemplo (anidamiento profundo):
function getDiscount(price, user) { if (user.isLoggedIn) { if (user.isPremium) { if (price > 100) { return price * 0.8; } else { return price * 0.9; } } else { return price; } } else { return price; }}