Em uma revisão de código, há situações assim: você abre o arquivo e todas as funções têm no máximo cinco linhas.
Este texto dá continuidade ao artigo anterior Code smell #2.
Os nomes são bons e cada classe tem apenas uma responsabilidade. Não há o que apontar.
Mas ninguém consegue responder na hora à pergunta: “O que acontece quando este botão é pressionado?”
Esse tipo de código é chamado de Ravioli Code (Texto original do C2).
Não era apenas uma crítica
Curiosamente, o termo nem sempre é usado de forma negativa. Ravioli é uma massa formada por pequenos pedaços que envolvem bem o recheio.
São pequenos objetos bem encapsulados, exatamente o que a orientação a objetos buscava. De fato, há usos de ravioli como oposto ao código espaguete.
O problema é a quantidade.
Cada pedaço é perfeito, mas há 200 no prato e não está escrito em lugar nenhum em que ordem ou como eles se conectam.
Na prática, é assim.
final class CheckoutCoordinator {
func start() { validator.validate(cart) }
}
final class CartValidator {
func validate(_ cart: Cart) { stockChecker.check(cart.items) }
}
final class StockChecker {
func check(_ items: [Item]) { priceCalculator.calculate(items) }
}
final class PriceCalculator {
func calculate(_ items: [Item]) { paymentPreparer.prepare(items) }
}
// ... Há mais dezesseis classes como esta
Cada classe é impecável. O nome é preciso e ela faz uma única coisa.
Mas não existe um arquivo que conheça todo o fluxo de pagamento.
O fluxo existe apenas nas relações de chamada entre as classes e só pode ser descoberto conectando o depurador, não lendo o código.
Por que a divisão fica excessiva
Quando “quanto menor a função, melhor” é aceito como regra.『Clean Code』chega a dizer que uma função deve ter duas ou três linhas, no máximo quatro.
O objetivo real desse conselho é fazer uma função lidar com apenas um nível de abstração. Quando isso vira um número de linhas, o propósito desaparece.
O resultado são trinta funções de cinco linhas, das quais vinte e oito são chamadas de um único lugar.
Quando o nome não resume o conteúdo., handleUserAction, processData e updateState não dizem o que fazem.
Ao dividir o código em funções com esses nomes, o leitor precisa abrir o corpo, e o número de lugares a consultar aumenta.
Uma boa extração elimina a necessidade de olhar o corpo; aqui acontece o contrário.
Quando níveis de abstração se misturam. Na mesma função convivem uma frase de política, como “validar o pedido”, e uma frase de detalhe, como “incrementar o índice em 1”. O olhar sobe e desce sem parar.
Dividir sem critério nesse estado cria fragmentos com níveis desordenados.
Quando um código usado uma vez é extraído pensando em reutilização. É a mesma mentalidade que cria código lasanha; só muda a direção, de vertical para horizontal.
O custo aparece na quantidade de saltos
O custo do código ravioli pode ser resumido em uma frase: quantos arquivos você abre para responder a uma pergunta?
Ao ler código, mantemos o fluxo na memória de curto prazo. Depois de três ou quatro elementos, essa memória começa a falhar.
Depois de saltar por seis arquivos, você esquece o que procurava no início e volta ao começo.
Quando isso se repete, executar para conferir fica mais rápido do que ler o código.
Também surgem efeitos colaterais.
- Ao adicionar uma funcionalidade, você não encontra o fragmento existente e cria outro parecido. A duplicação cresce silenciosamente.
- Sem encontrar onde corrigir o bug, você adiciona um tratamento temporário na ponta do fluxo, ou seja, na tela.
- Como o fluxo completo não está registrado no código, ele fica apenas na documentação ou na cabeça de alguém. Quando essa pessoa sai da equipe, ele desaparece junto.
Como recuperar o fluxo
Crie um lugar para registrar o fluxo. É a medida mais eficaz.
Tenha uma função que mostre toda a ordem de uma vez e faça com que ela descreva apenas a sequência.
func checkout(_ cart: Cart) async throws -> Receipt {
try validate(cart)
try await reserveStock(cart.items)
let amount = calculateTotal(cart)
let payment = try await charge(amount)
return try await confirm(cart, payment)
}
Os detalhes continuam em seus próprios lugares. A mudança é que o fluxo passa a estar escrito em uma única tela.
Funções assim também são chamadas de orquestradoras. É exatamente esse lugar que falta ao código ravioli.
**Mantenha um único nível por camada.**As cinco linhas da função acima são frases do mesmo nível. Se uma condição detalhada como items.count > 0 entrar ali, o nível se rompe.
Criar o hábito de verificar se as frases estão no mesmo nível ao ler uma função é mais útil do que seguir um critério de divisão.
**Decida a extração pelo nome.**O critério não é o número de linhas, mas esta pergunta: “O nome deste fragmento diz mais do que o corpo?”
Extrair if user.age >= 19 como isAdult(user) revela a intenção e traz benefício. Extrair array.append(item) como addItem não traz nada.
**Mantenha perto o que é próximo.**Código que muda junto deve ficar no mesmo arquivo e na mesma pasta.
Se, para seguir a convenção de um tipo por arquivo, você espalha tipos que sempre são abertos juntos, a proximidade é melhor que a convenção.
**O mesmo critério vale para unidades de serviço.**O estado de dividir microserviços demais é chamado de nanosserviços.
Uma arquitetura que atravessa doze serviços para processar uma requisição é código ravioli estendido para além da rede. Nesse caso, ao custo dos saltos somam-se latência e pontos de falha.
Lasanha, ravioli e espaguete
Colocando os três lado a lado, temos o seguinte resumo.
| Forma | Estado dos fragmentos | Problema |
|---|---|---|
| Espaguete | Grande e emaranhado | Não é possível prever o fluxo de execução |
| Lasanha | Camadas verticais | Uma alteração atravessa várias camadas |
| Ravioli | Pequeno e organizado | O fluxo entre os fragmentos não existe em lugar nenhum |
Nos três, o custo de compreender o todo é alto; só muda a forma.
Se você mede a qualidade do código apenas pela beleza de cada fragmento, não percebe a lasanha nem o ravioli. Ambos são perfeitos no nível dos fragmentos.
Resumo
- Código ravioli é aquele com tantos fragmentos pequenos e organizados que ninguém consegue explicar o fluxo completo.
- O termo também já foi usado positivamente para indicar código bem encapsulado. O problema é a quantidade.
- As principais causas são regras de quantidade de linhas, nomes ambíguos e níveis de abstração misturados.
- O ponto central da solução é ter um lugar para registrar o fluxo.
- O critério de extração não é o tamanho, mas o nome. Extraia apenas quando o nome comunicar mais do que o corpo.
O próximo artigo trata do extremo oposto: não há fragmentos demais, mas apenas um.
Vamos conhecer o God Object que sabe tudo sobre o aplicativo a partir de uma única classe.
Fontes e critérios de verificação
- Ravioli Code — C2 Wiki · texto original do autor · verificado em 2026-08-17 · base: metáfora do código ravioli como objetos pequenos e encapsulados fragmentados em excesso

![Imagem de capa de [Code smell #3] Código ravioli: código cujo fluxo ninguém conhece](/assets/images/posts/6faf8840-1640-4930-a94c-3ed202b71075/ravioli-code-disconnected-objects.jpg)