Règle
Conserver fonctions concis.
Les fonctions fonctions sont difficiles difficiles difficiles à comprendre, test, et de maintenance.
Langues prises en charge : 45+Introduction
Les fonctions s'étendant sur des centaines de lignes mélangent plusieurs responsabilités, ce qui rend difficile de comprendre ce que fait la fonction sans lire chaque ligne. Les fonctions longues gèrent généralement plusieurs préoccupations comme la validation, la logique métier, la transformation des données et la gestion des erreurs, le tout au même endroit. Cela viole le principe de responsabilité unique et crée un code difficile à tester, à déboguer et à modifier sans altérer le comportement existant.
Pourquoi c'est important
Maintenabilité du code : Les fonctions longues exigent des développeurs qu'ils retiennent plus de contexte pour comprendre le comportement. Modifier une partie risque d'en casser une autre car toute la logique est entrelacée. Les corrections de bugs deviennent risquées car les effets secondaires imprévus sont difficiles à prédire.
Complexité des tests : Tester une fonction de 200 lignes signifie couvrir tous les chemins de code possibles en un seul test, nécessitant une configuration complexe et de nombreux cas de test. Les fonctions plus petites peuvent être testées indépendamment avec des tests unitaires ciblés, rendant les suites de tests plus rapides et plus fiables.
Exemples de code
❌ 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;
}
Pourquoi c'est incorrect : Cette fonction gère la validation, le calcul, les opérations de base de données, les e-mails et l'inventaire. Les tests nécessitent de simuler toutes les dépendances. Toute modification de la logique fiscale ou de la validation nécessite de modifier l'intégralité de cette fonction.
✅ 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;
}Pourquoi c'est important : Chaque fonction a une responsabilité claire. validateOrder() et calculateTotal() peut être testé indépendamment sans mocks. createOrder() isole la logique de la base de données. Les opérations d'e-mail et d'inventaire ne bloquent pas la création de commandes, et les échecs sont gérés séparément.
Conclusion
Faire évoluer les API par des modifications additives : ajouter de nouveaux champs, de nouveaux endpoints, des paramètres optionnels. Lorsque des changements cassants (breaking changes) sont inévitables, utilisez le versioning d'API pour exécuter simultanément les anciennes et les nouvelles versions. Dépréciez les anciens champs avec des échéanciers clairs et des guides de migration avant de les supprimer.
.avif)
