Regola
Mantieni le funzioni concise.
Le funzioni lunghesono difficili da comprendere, testare e manutenere.
Linguaggi supportati: 45+Introduzione
Le funzioni che si estendono per centinaia di righe combinano più responsabilità, rendendo difficile capire cosa faccia la funzione senza leggere ogni singola riga. Le funzioni lunghe in genere gestiscono più aspetti come la validazione, la logica di business, la trasformazione dei dati e la gestione degli errori tutti nello stesso posto. Questo viola il principio di responsabilità singola e crea codice difficile da testare, debuggare e modificare senza compromettere il comportamento esistente.
Perché è importante
Manutenibilità del codice: Le funzioni lunghe richiedono agli sviluppatori di mantenere un contesto più ampio in memoria per comprendere il comportamento del codice. Modificare una parte rischia di romperne un'altra perché tutta la logica è interconnessa. La correzione dei bug diventa rischiosa poiché gli effetti collaterali indesiderati sono difficili da prevedere.
Complessità dei test: Testare una funzione di 200 righe significa coprire tutti i possibili percorsi del codice in un unico test, richiedendo una configurazione complessa e numerosi casi di test. Funzioni più piccole possono essere testate in modo indipendente con unit test mirati, rendendo le suite di test più veloci e affidabili.
Esempi di codice
❌ Non 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;
}
Perché è errato: Questa funzione gestisce validazione, calcolo, operazioni di database, invio di email e inventario. Il testing richiede il mocking di tutte le dipendenze. Qualsiasi modifica alla logica fiscale o di validazione richiede la modifica dell'intera funzione.
✅ 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;
}Perché questo è importante: Ogni funzione ha una sola e chiara responsabilità. validateOrder() e calculateTotal() possono essere testati in modo indipendente senza mock. createOrder() isola la logica del database. Le operazioni relative alle email e all'inventario non bloccano la creazione dell'ordine e gli eventuali errori vengono gestiti separatamente.
Conclusione
Evolvi le API attraverso modifiche additive: aggiungi nuovi campi, nuovi endpoint o parametri opzionali. Quando le modifiche che rompono la compatibilità sono inevitabili, utilizza il versionamento delle API per eseguire la vecchia e la nuova versione in parallelo. Depreca i vecchi campi fornendo tempistiche chiare e guide di migrazione prima di rimuoverli.

