Neste post
  1. Como se chega em quinze mil linhas
  2. O que efetivamente custou
  3. Doeu: encontrar coisa
  4. Doeu: o editor
  5. Doeu: mudança com raio grande
  6. Não doeu tanto: performance
  7. Não doeu: publicar
  8. Onde a linha realmente fica
  9. O que a gente faz agora
  10. O que a gente faz diferente em projeto novo
  11. O que isso diz sobre estúdio pequeno
  12. Resumo

O Nebulux é um app de tarefas e recompensas com tema espacial: tarefas, carteira com saque, ranking, sistema de indicação, conquistas e painel administrativo.

Ele está publicado, funciona e é usado.

O main.dart dele tem 15.248 linhas.

Este post não é confissão nem defesa. É a análise de como isso acontece, o que efetivamente custou, e qual é o critério que a gente passou a usar.

Como se chega em quinze mil linhas

Ninguém decide isso. É importante começar por aí, porque a explicação mais comum — desleixo — é a menos útil.

O mecanismo é econômico. Em qualquer momento da vida daquele arquivo, a pergunta que aparece é sempre a mesma:

Eu crio um arquivo novo para essas 80 linhas, ou coloco aqui embaixo?

E a resposta honesta, avaliada isoladamente, é coloca aqui embaixo. Criar arquivo custa: importação, decidir nome, decidir pasta, expor o que precisa ser compartilhado. Colar no fim custa zero.

Cada decisão individual está certa. A soma está errada. É dívida técnica no sentido literal do termo: cada parcela é confortável, e o principal cresce sozinho.

Linhas no main.dart100%
Linhas no restante do projeto34%

O que efetivamente custou

Vale separar o que doeu do que só parecia feio.

Doeu: encontrar coisa

Busca textual funciona; navegação estrutural não. Não dá para "abrir o arquivo do ranking" porque não existe arquivo do ranking. Existe a região do ranking, e achar a fronteira dela é trabalho manual toda vez.

O custo real aparece quando você volta depois de meses. A memória de onde as coisas estavam é o índice — e ela expira.

Doeu: o editor

Análise estática, autocompletar e formatação ficam visivelmente mais lentos num arquivo desse tamanho. Não é catastrófico, é atrito constante: meio segundo em cada operação, o dia inteiro.

Doeu: mudança com raio grande

Alterar algo compartilhado — uma constante de cor, um formato de moeda — vira busca e substituição num arquivo onde o mesmo nome aparece em contextos diferentes. Sem fronteira de módulo, não há limite natural para o alcance de uma mudança.

Não doeu tanto: performance

Tamanho de arquivo não afeta o app rodando. Dart compila; o binário não sabe em quantos arquivos você escreveu. Isso é importante dizer porque a intuição de quem vê o número é "deve estar lento", e não está.

Não doeu: publicar

O aplicativo passou nas revisões das lojas, atualiza normalmente e não tem comportamento diferente por causa disso.

O sintoma de monolito não é o app funcionando pior. É você trabalhando pior. Por isso ele demora tanto a ser tratado: não aparece em métrica de produto, só em velocidade de quem mexe.

Onde a linha realmente fica

Depois desta experiência, o critério que a gente passou a usar não é número de linhas. É este:

O arquivo cresceu até o ponto em que duas pessoas não conseguem trabalhar nele ao mesmo tempo?

Enquanto o autor é um só, um arquivo grande é principalmente incômodo. No momento em que entra uma segunda pessoa, ele vira gargalo — todo trabalho passa pelo mesmo arquivo, todo commit conflita, e o custo de coordenação supera qualquer conveniência.

O segundo critério, complementar:

Você consegue explicar onde uma funcionalidade mora sem abrir o editor?

Se a resposta é não, a estrutura parou de comunicar. E estrutura que não comunica é documentação que apodreceu.

O que a gente faz agora

Não foi um mutirão de refatoração, e essa é a parte importante do relato. Reescrever um app publicado que funciona é risco sem receita — o usuário não percebe nada e a chance de regressão é real.

A regra adotada foi outra: extrair na hora de mexer.

precisa alterar o ranking?
   -> extrai o ranking para um arquivo proprio
   -> confere que continua igual
   -> so entao faz a alteracao pedida

Três propriedades boas disso:

  1. 1. O custo da extração é pago pelo trabalho que já ia acontecer.
  2. 2. O que nunca muda nunca é extraído — e tudo bem, porque não incomoda.
  3. 3. Cada extração é pequena o bastante para ser verificada de verdade.

O arquivo encolhe pelo uso. Não vira zero, e não precisa.

O que a gente faz diferente em projeto novo

Uma regra só, e ela é tosca de propósito para ser seguida sem discussão:

Tela nova nasce em arquivo próprio, mesmo com trinta linhas.

O custo é uma importação. O benefício é nunca ter a conversa "onde eu coloco isso" — porque a resposta já está decidida.

E uma segunda, que evita metade dos monolitos que já vimos: estado e apresentação em arquivos separados desde o primeiro dia. A fusão dos dois é o que faz o arquivo crescer nas duas direções ao mesmo tempo.

O que isso diz sobre estúdio pequeno

Vale um parágrafo de contexto, porque a conclusão muda com o tamanho da equipe.

Numa operação com muitas pessoas, esse arquivo teria sido barrado na revisão. E com razão: o custo de coordenação seria imediato.

Numa operação de uma ou duas pessoas, o cálculo é diferente. O aplicativo no ar gerando resultado vale mais que a arquitetura correta de um aplicativo que não saiu. O monolito do Nebulux não é a melhor decisão técnica — é a decisão que permitiu ele existir.

O erro não foi escrever assim no começo. Foi não ter definido, no começo, o gatilho que dispararia a mudança.

Resumo

  • Monolito não é decisão. É acúmulo de decisões locais corretas.
  • O que dói é navegação, atrito de editor e raio de mudança. Performance não é

afetada.

  • O critério útil não é número de linhas: é se duas pessoas conseguem trabalhar

ao mesmo tempo, e se dá para dizer onde algo mora sem abrir o editor.

  • Refatoração grande em app publicado é risco sem receita. Extrair na hora de

mexer paga o custo com trabalho que já ia acontecer.

  • Em projeto novo: tela nova em arquivo próprio, sempre; estado separado de

apresentação desde o primeiro dia.

Perguntas frequentes

Vocês recomendam fazer isso?

Não como padrão. Recomendamos entender por que aconteceu, porque o mecanismo é o mesmo que produz monolito em qualquer base: cada adição isolada é barata, e ninguém decide 'vamos ter quinze mil linhas'. A decisão nunca é tomada; ela é acumulada.

Por que não refatorar de uma vez?

Porque refatoração grande em app publicado é risco sem receita. O caminho que usamos é extrair na hora de mexer: toda vez que uma parte precisa mudar, ela sai antes de mudar. O arquivo encolhe pelo uso, não por mutirão.

Ferramenta de análise não reclamou antes?

Reclamou, e o aviso foi ignorado porque não havia sintoma. Métrica de complexidade sem dor associada é fácil de ignorar — o sintoma só aparece quando alguém novo tenta mexer, ou quando você volta depois de três meses.