Regola
Rispetta le funzioni concise.
Le funzioni sono difficili da comprendere, verificare, e manutenere.
Lingue supportate: 45+Introduzione
Le funzioni che si estendono su centinaia di righe combinano più responsabilità, rendendo difficile comprendere il loro funzionamento senza leggere ogni singola riga. Le funzioni lunghe, in genere, gestiscono più aspetti contemporaneamente, quali la convalida, la logica di business, la trasformazione dei dati e la gestione degli errori, il tutto in un unico punto. Ciò viola il principio della responsabilità singola e genera codice difficile da testare, da debuggare e da modificare senza compromettere il comportamento esistente.
Perché è importante
Manutenibilità del codice: le funzioni lunghe richiedono agli sviluppatori di tenere a mente un contesto più ampio per comprenderne il comportamento. Modificare una parte comporta il rischio di comprometterne un’altra, poiché tutta la logica è strettamente interconnessa. La correzione dei bug diventa rischiosa, poiché è difficile prevedere effetti collaterali indesiderati.
Complessità dei test: testare una funzione di 200 righe significa coprire tutti i possibili percorsi di esecuzione del codice in un unico test, il che richiede una configurazione complessa e numerosi casi di test. Le funzioni più piccole possono essere testate in modo indipendente con test unitari 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é è sbagliato: questa funzione gestisce la convalida, i calcoli, le operazioni sul database, le e-mail e l'inventario. Per eseguire i test è necessario simulare tutte le dipendenze. Qualsiasi modifica alla logica fiscale o alla convalida 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é è importante: Ogni funzione ha una responsabilità ben definita. validateOrder() e calculateTotal() può essere testato in modo indipendente senza simulazioni. createOrder() isola la logica del database. Le operazioni relative alle e-mail e all'inventario non bloccano la creazione degli ordini e gli errori vengono gestiti separatamente.
Conclusione
Fai evolvere le API attraverso modifiche incrementali: aggiungi nuovi campi, nuovi endpoint e parametri opzionali. Quando le modifiche che comportano incompatibilità sono inevitabili, ricorri al versioning delle API per far funzionare contemporaneamente la versione precedente e quella nuova. Indica chiaramente i tempi e fornisci guide alla migrazione prima di rimuovere i campi obsoleti.

