Regra
Manter funções concisa.
Funções funções longas são difíceis de compreender, testar, e manter.
Idiomas suportados: 45+Introdução
Funções que se estendem por centenas de linhas misturam múltiplas responsabilidades, tornando difícil entender o que a função faz sem ler cada linha. Funções longas geralmente lidam com múltiplas preocupações, como validação, lógica de negócios, transformação de dados e tratamento de erros, tudo em um só lugar. Isso viola o princípio da responsabilidade única e cria um código difícil de testar, depurar e modificar sem quebrar o comportamento existente.
Por que isso importa
Manutenibilidade do código: Funções longas exigem que os desenvolvedores mantenham mais contexto em suas mentes para entender o comportamento. Modificar uma parte corre o risco de quebrar outra porque toda a lógica está interligada. Correções de bugs se tornam arriscadas, pois efeitos colaterais não intencionais são difíceis de prever.
Complexidade de teste: Testar uma função de 200 linhas significa cobrir todos os possíveis caminhos de código em um único teste, exigindo uma configuração complexa e inúmeros casos de teste. Funções menores podem ser testadas independentemente com testes unitários focados, tornando as suítes de teste mais rápidas e confiáveis.
Exemplos de código
❌ Não-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 que está errado: Esta função lida com validação, cálculo, operações de banco de dados, e-mail e inventário. Testar exige a simulação de todas as dependências. Qualquer alteração na lógica de impostos ou validação requer a modificação de toda esta função.
✅ Compatível:
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 que isso importa: Cada função tem uma responsabilidade clara. validateOrder() e calculateTotal() pode ser testado independentemente sem mocks. createOrder() isola a lógica do banco de dados. Operações de e-mail e inventário não bloqueiam a criação de pedidos, e as falhas são tratadas separadamente.
Conclusão
Evolua APIs através de mudanças aditivas: adicione novos campos, adicione novos endpoints, adicione parâmetros opcionais. Quando mudanças disruptivas forem inevitáveis, use o versionamento de API para executar versões antigas e novas simultaneamente. Deprecie campos antigos com cronogramas claros e guias de migração antes de removê-los.
.avif)
