filefunc × Hono — o código que um agente lê de uma vez: de 60 para 18 linhas

Se o seu agente de codificação continua corrigindo coisas erradas numa base de código grande, se ao fazer um agente ler um único arquivo ele traz 19 funções desnecessárias que contaminam o context, se você duvida que convenções como “1 arquivo 1 conceito” realmente funcionam — aqui estão os resultados medidos num framework real com 23k estrelas.

“Não vai criar arquivos demais?”

Essa é a pergunta mais frequente sobre filefunc. Dividir 186 arquivos em 626 não vai tornar o gerenciamento impossível?

A resposta está no Hono. Um framework web ultraleve que roda no Cloudflare Workers, Deno, Bun e Node.js. 23k+ estrelas, 1 milhão+ de downloads semanais no npm. Código real validado em produção. Refatoramos esse código com filefunc. 4419 testes, todos passaram. (Verificável diretamente no fork park-jun-woo/hono)

Os números

MétricaOriginalApós refatoração
Arquivos fonte186626
Total de linhas24.65330.244
Violações filefunc3970
vitest aprovados44194419
vitest reprovados44 (defeitos preexistentes)
vitest ignorados3333

Os arquivos aumentaram 3,4x. As linhas cresceram 23%. As violações foram de 397 para 0. Nenhum teste quebrou — mais precisamente, exatamente os mesmos 4 testes falharam (defeitos já presentes no original). O aumento de 23% nas linhas veio das anotações (//ff:func, //ff:what) e dos re-export hubs. Nenhuma linha de lógica foi alterada. Refatoração puramente estrutural.

O que importa não é a quantidade de arquivos, mas o ‘comprimento do que se lê’

“0 violações, 626 arquivos” é, na verdade, um proxy. O verdadeiro objetivo do filefunc não é dividir arquivos em pedaços menores — é fazer com que um agente, ao ler um conceito, leia apenas aquele conceito, sem que seja excessivamente longo. Por isso, o número real a ser provado não é a contagem de violações, mas o comprimento lido por arquivo. Medimos.

Linhas por arquivoOriginalApós refatoração
Mediana60,017,5 (−71%)
p90305119 (−61%)
Máximo2.7781.051 (−62%)
Proporção de arquivos ≤20 linhas26%54%

Antes, quando um agente abria um conceito, consumia em média 60 linhas; agora consome 18. Mesmo no pior caso (p90), caiu de 305 para 120 linhas. O tamanho das próprias funções permanece igual (mediana 11→12 linhas) — faz sentido. Não reescrevemos as funções, apenas as reorganizamos. O que diminuiu foi “o código ao redor que inevitavelmente se lê junto para chegar a um conceito”.

Por que isso importa? Context longo não é gratuito. LLMs perdem sistematicamente informações enterradas no meio de entradas longas (Liu et al., Lost in the Middle, TACL 2023, arXiv:2307.03172). Em tarefas de codificação, o desempenho despenca à medida que o contexto cresce — num benchmark, a precisão do Claude 3.5 Sonnet caiu de 29% para 3% (Rando et al., LongCodeBench, 2025, arXiv:2505.07897). E fornecer apenas a parte exata necessária em granularidade de conceito produz melhor qualidade de completação de código do que dar o arquivo inteiro (Yusuf et al., 2025, arXiv:2510.06606). Reduzir o comprimento lido não é uma questão de gosto — é uma defesa da precisão.

O problema do types.ts

Vejamos com concreto, não com abstração. O src/types.ts original do Hono tinha mais de 20 interfaces e tipos.

Quando um agente de IA faz um read desse arquivo para encontrar um único tipo HonoRequest? 19 tipos desnecessários vêm junto. Contaminação de context.

Após a refatoração, cada tipo é um arquivo independente. Se só é necessário HonoRequest, basta ler apenas hono_request.ts. O types.ts original permanece como re-export hub, preservando os caminhos de importação existentes.

# Original
import { HonoRequest } from './types'  // mais de 20 tipos vêm junto

# Após refatoração
import { HonoRequest } from './types'  // mesmo caminho, mesmo comportamento
// internamente: types.ts → re-export de hono_request.ts

Visto de fora, nada mudou. Visto por um agente de IA, tudo mudou.

De profundidade 6 para 2

O algoritmo de roteamento do Hono é complexo. O Node.search do trie-router tinha nesting depth de 6.

for → if → if → for → if → if   // depth 6

Depth 6 é código ruim? Não. Busca em trie naturalmente tem aninhamento profundo. Mas para um agente de IA entender essa função, precisa colocar 6 níveis de aninhamento na cabeça de uma vez. O mesmo vale para humanos. O filefunc extraiu a lógica interna para métodos privados e arrow functions no nível do módulo. Depth 6 → 2. Cada peça tem apenas um fluxo de controle. O algoritmo geral é idêntico.

# Original: search monolítico
Node.search()   // depth 6, 100+ linhas

# Refatorado: decomposto em partes
Node.search()           // depth 2, responsável apenas pela composição
  → matchParam()        // depth 1, correspondência de parâmetros
  → matchWildcard()     // depth 1, tratamento de wildcards
  → mergeHandlers()     // depth 1, mesclagem de handlers

A regra F1 do TypeScript, e a cauda honesta

A regra central do filefunc, F1, é “um arquivo, uma função”. Em Go é intuitivo. Mas em TypeScript, dividir em arquivos quebra o sistema de módulos. Tirar métodos de classe para arquivos externos elimina o binding do this. Por isso, o parser TypeScript do filefunc (ts_ast.js) conta apenas declarações function e não conta const arrow functions. O princípio é “um arquivo, um conceito” — não “exatamente uma function sintática”.

Aqui devemos ser honestos. Essa abordagem separou bem os casos fáceis (tipos, helpers simples), mas não separou tudo. Ao medir novamente após a refatoração:

  • 90% (566 de 626 arquivos) têm ≤1 função — satisfazem “1 arquivo 1 conceito”. (No original eram 70%.)
  • Mas 60 arquivos (9,6%) ainda coabitam 2 ou mais funções. E por coincidência são justamente os mais longos — a mediana de linhas nesses 60 é 151. Por exemplo, src/utils/url.ts tem 14 funções em 319 linhas.

Ou seja, a técnica da const arrow passa no contador mas atinge o objetivo apenas parcialmente. Quando vários arrow functions permanecem num arquivo, um agente que abre esse arquivo ainda lê múltiplos conceitos. No momento em que a métrica se torna o objetivo, a métrica se corrompe (Goodhart). filefunc não é exceção — a maior parte do risco residual de read-length está concentrada nessa cauda de 10%. Não elevar o número de “0 violações” ao status de resposta definitiva, mas medir também o que ainda não foi resolvido — isso é verificação.

“Então o que melhora?”

Quando os arquivos chegam a 626, humanos podem se desconfortar. Abrir um diretório e ver uma enxurrada de arquivos. Mas agentes de IA não abrem diretórios. Usam grep.

rg '//ff:func' --glob '*.ts' -l | head -20    # extrair arquivos candidatos
rg '//ff:what.*router' --glob '*.ts'            # apenas funções relacionadas ao roteador

Com 186 arquivos tendo em média 3-4 funções cada, mesmo quando grep encontra o arquivo, ao lê-lo funções desnecessárias vêm junto. Com 626 arquivos tendo 1 conceito cada, o arquivo que grep encontrou = o conceito necessário. O passo intermediário desaparece. Na exploração de código por agentes, “encontrar a localização relevante (localização)” é o gargalo da resolução de problemas downstream (Chen et al., LocAgent, 2025, arXiv:2503.09089), e filefunc torna essa busca determinística ao alinhar conceitos com fronteiras de arquivo.

Granularidade de função é sempre a resposta certa?

Vejamos também as evidências contrárias com honestidade. Um experimento controlado relata que “chunking por unidade de função é 3,6–5,6pp mais baixo que outras estratégias em autocompletação de código via RAG e não é Pareto-ótimo” (Wu et al., 2026, arXiv:2605.04763). Unidade de função não é uma panaceia.

No entanto, isso é uma discussão em camada diferente. Aquele experimento trata do contexto de autocompletação onde um sistema de recuperação corta código e empacota no prompt. filefunc lida com a unidade operacional em que um agente seleciona e lê arquivos diretamente — não onde um sistema de recuperação cria chunks. Estratégia de chunking (retrieval chunk) e unidade operacional (arquivo que um agente abre) são camadas distintas. Mesmo assim, tornar essa distinção explícita é importante — “quanto mais granular, melhor sem exceção” não é a afirmação do filefunc. A afirmação é “quando a unidade que um agente lê se alinha ao conceito, o comprimento lido diminui”, e os números acima mostram exatamente isso.

Restrição é liberdade

O que confirmamos ao refatorar o Hono com filefunc é uma coisa só.

Restrições estruturais não limitam o código. Liberam a exploração.

Ter mais arquivos é um custo. Mas quando cada arquivo contém apenas um conceito, o agente lê exatamente o que precisa e não se contamina com context desnecessário — a medição de que o comprimento lido caiu de 60 para 18 linhas é a prova disso. O mesmo vale para humanos. Quando o nome da função é o nome do arquivo, o diretório é um índice.

397 violações chegando a 0, e 4419 testes passando de forma idêntica ao original. E o fato de que o relatório de refatoração no README pode ser re-executado por qualquer um. Essa é a prova de que “1 arquivo 1 conceito” não é teoria, mas prática real. Incluindo a cauda de 9,6% que ainda resta.

Artigos relacionados

Leitura adicional (externa)

  • Effective context engineering for AI agents — Anthropic. Aponta “context rot” e o orçamento finito de atenção como problemas centrais — a mesma base pela qual filefunc reduz context desnecessário.
  • Strategies and Tactics for working with Coding Agents — Brian Kihoon Lee. Defende que exploração baseada em grep e arquitetura de informação devem ser projetadas manualmente — diretamente ligado a convenções de estrutura de arquivo que fazem agentes “lerem apenas o alvo”.
  • The Vibes Don’t Scale — Paul Stack. O mecanismo pelo qual vibe coding colapsa em drift arquitetural em escala — o problema de “grandes bases de código quebrando agentes” que filefunc busca resolver.
  • Agentic Engineering Patterns — Simon Willison. Padrões de gerenciamento de contexto como Context Quarantine/Pruning — estende as afirmações agent-operable do filefunc para a linguagem de padrões práticos.
  • Agent Harness Engineering — Addy Osmani. O desempenho de agentes é determinado mais pela infraestrutura ao redor do que pelo modelo — recontextualiza convenções de estrutura de código como um eixo do harness.

Fontes

  • Liu et al. “Lost in the Middle: How Language Models Use Long Contexts” (TACL 2023, arXiv:2307.03172)
  • Rando et al. “LongCodeBench: Evaluating Coding LLMs at 1M Context Windows” (2025, arXiv:2505.07897)
  • Yusuf et al. “Beyond More Context: How Granularity and Order Drive Code Completion Quality” (2025, arXiv:2510.06606)
  • Chen et al. “LocAgent: Graph-Guided LLM Agents for Code Localization” (2025, arXiv:2503.09089)
  • Wu et al. “How Does Chunking Affect Retrieval-Augmented Code Completion? A Controlled Empirical Study” (2026, arXiv:2605.04763)
  • Verificação dos resultados da refatoração: park-jun-woo/hono (filefunc Refactoring Report no README) · Convenção: filefunc
  • Imagem principal: gerada por IA (Google Gemini)