19 de set. de 2025·7 min de leitura

Prompts para código mantenível: restrições para pastas e nomeação

Escreva prompts para código mantenível adicionando regras claras para estrutura de pastas, nomeação e configuração, para que a saída da IA seja fácil de depurar e colocar em produção.

Prompts para código mantenível: restrições para pastas e nomeação

Por que a saída da IA fica difícil de manter

Código gerado por IA parece ótimo no primeiro dia porque roda rápido e mostra resultado. O problema começa alguns dias depois, quando você precisa adicionar uma feature, consertar um bug ou passar o projeto para outra pessoa. Sem regras claras, o modelo otimiza por “funcionar agora”, não por “ser fácil de mudar depois”.

O causador mais comum são prompts vagos. Se você não especifica regras de estrutura de pastas, nomeação e configuração, o modelo preenche as lacunas de forma diferente a cada vez. É assim que você acaba com arquivos espalhados por diretórios aleatórios, três formas de nomear a mesma coisa e configurações escondidas em lugares que ninguém pensa em checar. O código ainda pode rodar, mas fica frágil.

Sinais comuns de que você está caminhando para uma bagunça de manutenção incluem estilos inconsistentes para features semelhantes, localização de arquivos imprevisível, nomes divergentes (userService, users_service, UserSvc) e configuração misturada no código com defaults pouco claros. Pequenas mudanças começam a causar quebras surpreendentes em outros pontos.

Para um fundador solo ou uma equipe pequena, “mantenível” normalmente significa que você encontra coisas rápido, muda um comportamento sem quebrar cinco outros, e incorpora uma pessoa nova sem tour guiado. Também significa menos surpresas noturnas como autenticação quebrada, segredos expostos ou um emaranhado confuso de arquivos.

Adicione restrições sempre que o projeto viver mais que um demo, ou quando você espera mais de uma iteração. Deixe o modelo improvisar apenas em experimentos descartáveis, testes rápidos ou scripts pontuais. Se você pode enviá-lo, manter ou pagar alguém para consertar depois, defina restrições desde o início.

As três restrições que mais importam

Se quer prompts para código mantenível, não comece pedindo mais features. Comece adicionando três restrições que decidem como o código é organizado, nomeado e configurado. Essas são dolorosas de mudar depois.

1) Estrutura de pastas (onde as coisas ficam)

Uma regra de pastas torna a saída previsível e previne a bagunça de “tudo na raiz”.

Defina regras como: manter um único ponto de entrada, agrupar código por responsabilidade e separar código da app de config, scripts e testes. Diga também o que nunca deve acontecer (por exemplo, nada de lógica de negócio em componentes de UI, nada de código de banco dentro de rotas).

2) Nomeação (como você vai reconhecer as coisas depois)

Regras de nomeação reduzem trabalho duplicado e confusão. Sem elas, você tem dois arquivos fazendo a mesma coisa ou um utils.ts que vira uma gaveta de lixo.

Seja específico: nomes de arquivos, componentes, funções, rotas e tabelas de banco devem seguir um estilo e refletir seu propósito. Use verbos consistentes para ações (create, update, delete) e evite nomes vagos como data, helper ou thing.

3) Configuração (como settings e segredos são tratados)

A maioria dos protótipos gerados por IA quebra quando você sai do local e vai para um deploy real. Restrições claras de configuração evitam isso.

Defina essas regras desde o começo:

  • Um local de config (env vars + um módulo de config), não constantes espalhadas
  • Defaults separados para dev e prod, com fallbacks seguros
  • Nunca hardcode segredos, tokens ou chaves de API no código ou em arquivos de exemplo
  • Fornecer um .env.example mínimo contendo apenas placeholders
  • Falhar rápido quando faltar uma configuração obrigatória com um erro claro

Se você herdou um app gerado por IA que ignora essas restrições, essa limpeza geralmente vem primeiro porque torna todo conserto posterior mais simples.

Um template de prompt reutilizável que você pode copiar

O ganho mais rápido é um pequeno bloco de restrições reutilizável. Cole-o em qualquer requisição e ajuste só o que importa para o projeto.

Aqui está um template que você pode copiar como está:

CONSTRAINTS
1) Before coding, output a brief file tree (max 15 lines). Ask 2-4 questions only if needed.
2) Folder structure:
   - Keep source in /src
   - Keep shared utilities in /src/lib
   - Keep UI components in /src/components
   - Keep config in /config
3) Naming:
   - Files: kebab-case (user-profile.ts)
   - React components: PascalCase
   - Functions/vars: camelCase
   - No single-letter names (except i/j in loops)
4) Configuration and secrets:
   - Read all secrets from environment variables
   - Provide a sample .env.example (no real secrets)
   - Safe defaults for dev, strict checks for prod
5) If a rule conflicts with the framework:
   - Follow the framework default
   - Explain the conflict in 2-3 sentences
   - Suggest the closest alternative that keeps the spirit of the rule
6) Output:
   - Generate code file-by-file with clear filenames
   - Add short comments only where the intent is not obvious

Mantenha as regras específicas, mas não excessivamente detalhadas. Boas restrições descrevem resultados que você pode verificar (onde os arquivos vivem, como os nomes devem ser), e evitam regras minúsculas que geram trabalho extra.

Um hábito que evita saída bagunçada: peça a árvore de arquivos primeiro. Isso força o modelo a planejar e te dá uma chance rápida de dizer “mova auth para /src/lib” antes que ele escreva 10 arquivos.

Se você estiver consertando código gerado por IA depois, restrições também aceleram a correção. Quando tudo tem um lar previsível, fica mais fácil identificar o que falta e consertar sem quebrar partes não relacionadas.

Passo a passo: como escrever suas restrições

Bons prompts para código mantenível começam pela clareza e então adicionam só as regras que você realmente vai fazer cumprir. Se colocar regras demais, o modelo vai ignorá-las ou produzir enfeite.

Um fluxo simples que funciona

Escreva seu prompt em cinco partes, nesta ordem:

  • Comece com uma frase que declara o trabalho a ser feito (para quem e ação principal).
  • Trave o essencial da stack (framework, linguagem e qualquer versão que afete sintaxe ou config). Pule o resto.
  • Defina regras do projeto: como pastas são organizadas e como arquivos, componentes e funções são nomeados.
  • Defina como a configuração funciona: o que vai em env vars, quais defaults são seguros e o que nunca deve ser comitado.
  • Exija uma sequência de saída: primeiro um plano de arquivos, depois o código, depois uma rápida auto-checagem do que foi verificado.

Essa ordem importa. Se você começar por pastas e nomes antes do objetivo, frequentemente obtém uma estrutura arrumada que resolve o problema errado.

Exemplo pequeno (mesma ideia, palavras mais simples)

Imagine que você quer um rastreador de faturas simples para um freelancer. Se você fixar React + TypeScript e disser “mantenha server code em /api, UI em /web, tipos compartilhados em /shared”, você impede muita confusão. Adicione nomeação como “componentes em PascalCase, hooks começam com use” e evita o mistério de onde a lógica mora.

Seja rígido sobre config: “leia segredos de env vars apenas, forneça .env.example e falhe rápido com erro claro se faltar uma variável”. Essa única linha evita os problemas clássicos de auth quebrada e segredos expostos.

Termine com um resumo de auto-checagem. Isso incentiva o modelo a detectar arquivos faltantes, nomes desencontrados e defaults inseguros antes de você.

Restrições de estrutura de pastas que mantêm projetos organizados

Obter Ajuda com Seu Protótipo
Traga seu repositório e objetivos; diremos o que está quebrado e o que é necessário para enviar.

Uma árvore de pastas limpa é uma das restrições mais fáceis de adicionar. O objetivo não é perfeição, é previsibilidade, para que você (ou outra pessoa) encontre coisas rápido e corrija sem quebrar partes não relacionadas.

Uma estrutura simples que cabe na maioria dos apps web pequenos é:

  • src/ui/ para telas e componentes reutilizáveis
  • src/domain/ para regras de negócio (o que o app faz)
  • src/data/ para banco e APIs externas (como os dados são armazenados/buscados)
  • src/shared/ para helpers realmente compartilhados (pequenos, entediantes, reutilizados)
  • src/config/ para defaults de app (não segredos)

Adicione mais uma regra: separe UI, lógica de negócio e acesso a dados. Em termos simples, a UI não deve falar diretamente com o banco, e o código de banco não deve decidir o que o usuário pode fazer.

Para evitar arquivos com 800 linhas, defina “uma responsabilidade por arquivo” de forma prática. Um arquivo deve ter um propósito principal (um componente, um serviço, um repositório). Se precisar de duas seções diferentes, separe. Se for reutilizado em três lugares, mova para shared/. Se for reutilizado dentro de uma única feature, mantenha na pasta da feature. Evite um utils/ genérico: exija nomes específicos como shared/date/ ou shared/format/.

Uma regra útil sobre quando criar um novo módulo vs adicionar ao existente: crie uma nova pasta só quando houver um novo conceito no app. Um app de billing pode adicionar domain/invoices/ e ui/invoices/ quando invoices virar uma feature real, não só uma tela isolada.

Se você herdou saída bagunçada da IA, essas restrições aceleram a remediação. Muito do trabalho é mover código para limites claros antes de consertar lógica, auth ou questões de segurança com segurança.

Regras de nomeação que evitam confusão depois

Nomeação é onde o código gerado por IA muitas vezes escorrega. Se seu prompt for rigoroso aqui, você gastará menos tempo caçando imports, adivinhando o que uma função faz ou desembaraçando modelos “quase iguais”.

Escolha um estilo por categoria e não misture. Um mapeamento simples que você pode colar em prompts é:

  • Arquivos e pastas: kebab-case (ex.: user-profile.ts)
  • Componentes React / classes: PascalCase (ex.: UserProfile)
  • Funções e variáveis: camelCase (ex.: fetchUserProfile)
  • Constantes: SCREAMING_SNAKE_CASE (ex.: MAX_RETRIES)
  • Rotas de API: kebab-case (ex.: /user-profile)

O nome do arquivo deve corresponder ao que ele exporta. Se um arquivo exporta UserService, nomeie-o user-service.ts (ou UserService.ts se esse for o seu padrão). Não exporte cinco coisas não relacionadas de um único arquivo. Um export principal por arquivo mantém imports previsíveis e torna refatorações mais seguras.

Para funções, use nomes verbo-primeiro que digam o que acontece: getUserById, validateSignupForm, saveInvoice, sendPasswordResetEmail. Evite nomes vagos como process, handleThing ou doWork. Se for async, seja consistente: ou adicione sufixo Async em toda parte ou confie no contexto, mas não misture estilos.

Modelos de dados devem usar substantivos no singular (User, Invoice). Campos de banco devem seguir uma convenção (snake_case é comum em SQL; camelCase é comum no código da app). Escolha uma e mantenha. Alinhe nomes relacionados para que createdAt mapeie claramente para created_at, não para create_date em um lugar e created em outro.

Uma pequena lista de “não usar” economiza tempo depois: temp, misc, helper2, final_v3, newNew. Se você herdou uma base cheia desses nomes, renomear e reorganizar geralmente compensa porque nomes confusos escondem bugs.

Restrições de configuração: ambientes, segredos e defaults

Seja rígido sobre o que é configuração e o que é código. Configuração é qualquer coisa que muda entre dev, staging e prod: URL do banco, chaves de API, origens permitidas, settings de cookie, feature flags. Código é lógica que permanece igual: rotas, validação, regras de negócio.

Uma boa restrição é separar config em tempo de execução de config em tempo de build. Config de runtime deve vir de variáveis de ambiente, porque pode mudar sem rebuild. Config de build pode ficar em arquivos comitados ao repo, como um módulo tipado de config com defaults seguros, ou config/*.json usado apenas para valores não secretos.

Segredos precisam de regras explícitas porque apps gerados por IA frequentemente os vazam por acidente:

  • Nunca hardcodear segredos em código ou arquivos de config
  • Nunca logar segredos (incluindo logs de debug)
  • Nunca commitar segredos (commit somente arquivo de exemplo)
  • Falhar rápido se um segredo obrigatório estiver ausente
  • Usar nomes claros como DATABASE_URL e JWT_SECRET

Defaults também importam. Peça defaults seguros e sem surpresas para que o app se comporte de forma previsível mesmo antes de você afiná-los. Por exemplo: CORS deve ser restrito (permitir só uma lista conhecida), cookies de auth devem ser HttpOnly e Secure em produção, e sessões devem ter timeout curto com max age claro.

Exija também um único lugar onde a configuração é documentada. O padrão mais simples é um .env.example com comentários, mais uma seção “Configuração” no README listando cada variável, o que faz e um valor de exemplo. Essa restrição economiza horas depois, especialmente quando um protótipo rodou em uma máquina mas quebrou no deploy.

Restrições de qualidade: erros, validação e testes pequenos

Tornar Pronto para Produção
Configuramos envs, variáveis e verificações de produção para que o deploy pare de falhar.

A maioria dos apps gerados por IA falha em produção por motivos chatos: erros pouco claros, validação ausente e falta de testes nas partes arriscadas. Algumas restrições de qualidade tornam a saída mais fácil de debugar agora e de consertar depois.

Comece forçando tratamento de erro consistente. Peça um padrão único em toda parte, não uma mistura de strings lançadas, respostas ad hoc e falhas silenciosas. Exija erros explícitos, com formato consistente e seguros para exibir ao usuário.

Depois, exija validação de entrada nas fronteiras, onde dados ruins entram: rotas de API, formulários, webhooks, jobs em background. Sem validação, você tem bugs como “funciona na minha máquina” ou “falha só para alguns usuários”.

Restrições copiáveis:

  • Use um formato de erro único (por exemplo: { code, message, details? }) e nunca lance strings simples.
  • Valide todas as entradas externas na fronteira, retorne erros de validação claros e nunca confie em dados do cliente.
  • Mantenha funções pequenas (cerca de 20–40 linhas) e faça retornos previsíveis (sem tipos mistos).
  • Logue falhas inesperadas com contexto suficiente para reproduzir (request id, user id se disponível, ação).

Testes não precisam ser grandes para ajudar. Peça um conjunto mínimo que cubra o risco. Se há login, pagamento ou um fluxo de criar/atualizar, comece por aí. Um mínimo leve pode incluir rejeição de auth para credenciais inválidas, um caminho de sucesso do fluxo principal + uma falha comum, e um teste de validação provando que entrada ruim retorna erro claro.

Por fim, exija uma seção curta “como rodar localmente” na saída, incluindo as env vars necessárias e defaults seguros. Isso evita muitos projetos que “não iniciam”.

Exemplo de prompt: construir um app pequeno que permanece mantenível

Imagine que você quer um app web pequeno com login, página de perfil e um formulário de configurações. Sem restrições, uma IA costuma espalhar lógica de auth entre páginas, misturar chamadas de banco no código da UI e inventar nomes de arquivo sobre a marcha. Com regras claras, você obtém limites limpos e um plano de arquivos que pode debugar depois.

Aqui vai um prompt copiável que você pode usar e ajustar:

Build a small app with:
- Login page
- Profile page (shows name + email)
- Settings page (update display name, toggle a feature flag)

Hard constraints (do not violate):
1) Folder structure:
- /src/routes = route definitions only
- /src/handlers = request/response logic only (no database queries)
- /src/services = business rules (auth, profile, settings)
- /src/data = database access only (queries, repositories)
- /src/config = configuration loader and typed config

2) Naming:
- Files: kebab-case (profile-handler.ts)
- Exports: camelCase functions, PascalCase types
- One main export per file

3) Code boundaries:
- Routes call handlers
- Handlers call services
- Services call data layer
- Data layer is the only place allowed to import the DB client

4) Config constraints:
- Read DATABASE_URL and AUTH_SECRET from environment variables
- Never hardcode secrets or sample keys
- Add FEATURE_SETTINGS_ENABLED default=false when missing
- Provide a single config object from /src/config

Deliverables:
- Start with a file tree
- Then output code file-by-file
- Finish with a summary table: file created/changed + 1 sentence why

Se quiser saída ainda mais restrita, adicione: “Se precisar criar um novo arquivo, explique por que ele pertence àquela pasta.” Isso empurra o modelo a respeitar limites em vez de despejar tudo num único lugar.

Erros comuns ao adicionar restrições

Padronizar Nomes e Layout
Alinhamos nomes, exports e localização de arquivos para que sua equipe encontre e altere coisas rápido.

Restrições servem para tornar a saída mais fácil de ler, mudar e consertar. A maioria dos problemas aparece quando as regras são vagas demais para guiar o modelo ou tão rígidas que colidem com o framework.

Erro 1: Sobre-restringir o projeto

É fácil escrever regras que soam limpas mas forçam escolhas não naturais. Por exemplo, exigir um layout customizado que luta contra as convenções do Next.js, ou proibir um arquivo de configuração padrão do framework porque parece bagunçado. O modelo então gasta energia contornando suas regras em vez de construir código correto.

Uma abordagem mais segura: mantenha defaults do framework a menos que tenha razão real para mudá-los. Adicione restrições só onde você vê confusão recorrente (como onde as rotas de API ficam ou onde tipos compartilhados moram).

Erro 2: Sub-restringir com palavras vagas

“Código limpo”, “melhores práticas” e “pronto para empresa” não dizem ao modelo o que fazer. Substitua por checagens que ele possa seguir.

Exemplos de restrições que realmente funcionam:

  • “Output a file tree first, then code files in that order.”
  • “Use one naming style: camelCase for variables, PascalCase for components.”
  • “Put env vars in .env.example and read them only via a config module.”
  • “No new libraries unless you ask first and explain why.”
  • “If you move files, include migration steps.”

Outro problema comum é deixar o modelo inventar bibliotecas ou arquivos de configuração que você não pediu. Você pede auth, ele adiciona três pacotes, duas configs e uma nova ferramenta de build.

Não pule passos de migração ao mudar estrutura. Um pequeno rename pode quebrar imports, testes e deploy. Peça uma seção curta “o que mudou” e quaisquer comandos necessários para atualizar caminhos. E sempre exija a árvore de arquivos; sem ela, a saída vira dispersa e difícil de montar.

Checklist rápido e próximos passos

Antes de aceitar código gerado por IA (ou fazer merge), faça uma checagem de 5 minutos. Esses itens pegam a maioria dos problemas “parece bom agora, doloroso depois”:

  • A árvore de arquivos bate com suas regras (pastas, camadas, código compartilhado) e não há diretórios aleatórios.
  • Nomes são consistentes: o mesmo conceito não é chamado de três coisas diferentes entre arquivos, rotas e variáveis.
  • Não há segredos no código: nenhuma chave de API, tokens, URLs privadas ou credenciais reais em arquivos, comentários ou configs de exemplo.
  • Configuração está clara: existe um lugar documentado para setar env vars, defaults são seguros e o comportamento não muda silenciosamente entre dev e prod.
  • Ele roda com passos de copiar/colar: alguém novo pode instalar, configurar e rodar sem adivinhar.

Se você não consegue responder sim para a maioria, pare. Uma limpeza pequena agora é mais barata que debugar daqui a um mês, especialmente quando problemas se escondem em confusão de nomes, config espalhada ou estrutura de pastas que incentiva crescimento espaguete.

Se já tem uma base de código bagunçada gerada por IA, torne-a compreensível antes de adicionar features. Uma ordem prática é: congele o escopo por 24 horas, mapeie a estrutura atual (pastas, pontos de entrada, onde config e segredos vivem), escolha um padrão de nomes e aplique ao caminho quente primeiro, puxe configuração para um lugar só com um .env.example seguro e passos claros de startup, e então adicione pequenas checagens (validação, tratamento básico de erro, um ou dois testes de fumaça) para prevenir regressões.

Se estiver preso com um protótipo de ferramentas como Lovable, Bolt, v0, Cursor ou Replit que não se comporta em produção, o FixMyMess (fixmymess.ai) pode rodar uma auditoria gratuita de código para sinalizar problemas de estrutura, nomeação, configuração e segurança antes de quaisquer correções. Assim você recebe um plano claro, não mais tentativas às cegas.

Perguntas Frequentes

Por que o código gerado por IA fica bagunçado tão rápido?

A IA costuma otimizar por “funcionar agora”, então pode tomar atalhos que parecem aceitáveis até você precisar mudar algo. Sem regras claras para estrutura, nomes e configuração, cada novo prompt pode gerar um padrão diferente, o que torna o código frágil a alterações.

Quais são os sinais mais fáceis de perceber que meu projeto está ficando difícil de manter?

Procure nomes inconsistentes para o mesmo conceito, arquivos em pastas aleatórias e valores de configuração hardcoded em vários lugares. Outro sinal comum é que uma pequena mudança causa quebras não relacionadas — isso geralmente indica responsabilidades misturadas.

Quando devo adicionar restrições em vez de deixar a IA improvisar?

Adicione restrições sempre que o projeto for ser enviado, iterado mais de uma vez ou entregue a outra pessoa. Se for realmente um demo descartável ou um script único, você pode ser mais flexível e aceitar alguma bagunça.

Por que estrutura, nomes e configuração são as três restrições principais?

A estrutura de pastas define onde o código futuro vai morar, os nomes determinam como você encontrará e reutilizará coisas, e a configuração determina se o app sobrevive ao deploy. Essas três coisas são difíceis de consertar depois porque afetam cada arquivo e cada alteração.

Qual a maneira mais rápida de manter a saída da IA organizada desde o início?

Peça primeiro uma árvore de arquivos curta (por exemplo, até 15 linhas). Em seguida, exija que o código seja entregue arquivo por arquivo com nomes, assim você vê rapidamente se algo foi para o lugar errado antes que dezenas de arquivos sejam gerados.

Quais regras de nomeação evitam arquivos duplicados ou confusos?

Escolha uma convenção por categoria e mantenha-a: arquivos em kebab-case, componentes em PascalCase, funções em camelCase e nomes de rotas consistentes. Exija que o nome do arquivo combine com seu export principal e evite gavetas "utils" vagas substituindo por pastas específicas.

Quais regras de configuração evitam as quebras de deploy mais comuns?

Exija um carregador/modulo de configuração único, leia segredos apenas de variáveis de ambiente e inclua um .env.example apenas com placeholders. Também solicite checagens que falhem rápido quando um valor obrigatório estiver ausente — fallback silencioso é motivo comum de quebra em produção.

Como evito sobrecarregar o projeto com regras demais?

Evite regras que entrem em conflito com as convenções do framework — isso força soluções estranhas. Regra prática: siga o padrão do framework quando houver conflito e só adicione restrições onde você constantemente vê confusão (por exemplo, limites entre UI, serviços e acesso a dados).

Quais restrições de qualidade ajudam sem desacelerar tudo?

Peça um formato consistente de erro pelo app, validação nas fronteiras (rotas/formulários/webhooks) e um conjunto mínimo de testes para fluxos arriscados como autenticação e operações de criar/atualizar. Essas medidas adicionam pouco código, mas facilitam debugar e evitam regressões.

Herdei uma base de código gerada por IA bagunçada — o que fazer primeiro?

Comece mapeando a árvore atual e identificando onde ficam a configuração e os segredos. Depois escolha um padrão de nomes e aplique ao caminho crítico primeiro. Se você está preso com um protótipo problemático vindo de Lovable, Bolt, v0, Cursor ou Replit, o FixMyMess (fixmymess.ai) pode fazer uma auditoria gratuita e entregar um plano claro de remediação, muitas vezes com correções em 48–72 horas.