Regla
Mantenga funciones concisas.
Las funciones largas funciones son difíciles de entender, prueba, y mantener.
Idiomas compatibles: 45+Introducción
Las funciones que abarcan cientos de líneas mezclan múltiples responsabilidades, lo que dificulta entender qué hace la función sin leer cada línea. Las funciones largas suelen manejar múltiples preocupaciones como la validación, la lógica de negocio, la transformación de datos y el manejo de errores, todo en un solo lugar. Esto viola el principio de responsabilidad única y crea código difícil de probar, depurar y modificar sin romper el comportamiento existente.
Por qué es importante
Mantenibilidad del código: Las funciones largas requieren que los desarrolladores retengan más contexto en su mente para entender el comportamiento. Modificar una parte conlleva el riesgo de romper otra porque toda la lógica está entrelazada. Las correcciones de errores se vuelven arriesgadas ya que los efectos secundarios no deseados son difíciles de predecir.
Complejidad de las pruebas: Probar una función de 200 líneas implica cubrir todas las posibles rutas de código en una sola prueba, lo que requiere una configuración compleja y numerosos casos de prueba. Las funciones más pequeñas pueden probarse de forma independiente con pruebas unitarias específicas, lo que hace que las suites de pruebas sean más rápidas y fiables.
Ejemplos de código
❌ No conforme:
async function processOrder(orderData) {
if (!orderData.items?.length) throw new Error('Items required');
if (!orderData.customer?.email) throw new Error('Email required');
const subtotal = orderData.items.reduce((sum, item) =>
sum + (item.price * item.quantity), 0);
const tax = subtotal * 0.08;
const total = subtotal + tax + (subtotal > 50 ? 0 : 9.99);
const order = await db.orders.create({
customerId: orderData.customer.id,
total: total
});
await emailService.send(orderData.customer.email, `Order #${order.id}`);
await inventory.reserve(orderData.items);
return order;
}
Por qué está mal: Esta función gestiona la validación, el cálculo, las operaciones de base de datos, el correo electrónico y el inventario. Las pruebas requieren simular todas las dependencias. Cualquier cambio en la lógica fiscal o la validación requiere modificar toda esta función.
✅ Conforme:
function validateOrder(orderData) {
if (!orderData.items?.length) throw new Error('Items required');
if (!orderData.customer?.email) throw new Error('Email required');
}
function calculateTotal(items) {
const subtotal = items.reduce((sum, item) =>
sum + (item.price * item.quantity), 0);
return subtotal + (subtotal * 0.08) + (subtotal > 50 ? 0 : 9.99);
}
async function createOrder(customerId, total) {
return await db.orders.create({ customerId, total });
}
async function processOrder(orderData) {
validateOrder(orderData);
const total = calculateTotal(orderData.items);
const order = await createOrder(orderData.customer.id, total);
// Non-critical operations in background
emailService.send(orderData.customer.email, `Order #${order.id}`).catch(console.error);
return order;
}¿Por qué esto importa? Cada función tiene una responsabilidad clara. validateOrder() y calcularTotal() se puede probar de forma independiente sin mocks. createOrder() aísla la lógica de la base de datos. Las operaciones de correo electrónico y de inventario no bloquean la creación de pedidos, y los fallos se gestionan por separado.
Conclusión
Evolucione las APIs mediante cambios aditivos: añada nuevos campos, nuevos endpoints, añada parámetros opcionales. Cuando los cambios disruptivos sean inevitables, utilice el versionado de API para ejecutar versiones antiguas y nuevas de forma concurrente. Depreque campos antiguos con plazos claros y guías de migración antes de eliminarlos.
.avif)
