---
title: "Configuração Hardcoded"
type: "ai-smell"
slug: "hardcoded-configuration"
url: "http://localhost:3000/pt-br/ai-smells/hardcoded-configuration.md"
category: "Manutenção"
description: "Assistentes de IA incorporam valores específicos de ambiente — URLs, portas, caminhos, timeouts, chaves e números mágicos — diretamente na lógica, em vez de lê-los a partir de configuração ou do ambiente, porque um literal é o próximo token mais provável e o modelo desconhece sua camada de configuração existente."
---
# Configuração Hardcoded

> Assistentes de IA incorporam valores específicos de ambiente — URLs, portas, caminhos, timeouts, chaves e números mágicos — diretamente na lógica, em vez de lê-los a partir de configuração ou do ambiente, porque um literal é o próximo token mais provável e o modelo desconhece sua camada de configuração existente.

## Signs and Symptoms

Um assistente de IA tende a emitir um _literal plausível_ exatamente onde deveria haver uma referência. O código roda na demonstração, então o smell sobrevive à revisão a menos que você o procure.

Sinais reveladores:

* **Endpoints, portas, caminhos e timeouts inline** espalhados pela lógica de negócio em vez de um módulo de configuração: `http://localhost:3000`, `/tmp/cache`, `5432`, `setTimeout(..., 30000)`.
* **Números/strings mágicos** sem uma constante nomeada — contagens de retentativa, tamanhos de página, limites de taxa, limiares de funcionalidades.
* **O mesmo literal repetido em vários arquivos** porque o modelo o regenerou em vez de importar uma constante existente (o padrão "copia/cola para cima, refatora para baixo" da GitClear em miniatura).
* **Credenciais / chaves hardcoded** — tokens de API, chaves de criptografia ou strings de autenticação `Basic` coladas dos dados de treinamento.
* **Um `config.ts` / `.env` / objeto de configurações já existente que o novo código ignora** por completo.
* **Valores fixados por ambiente**: uma URL de dev/staging ou ID de conta de teste fixado em um caminho que vai para produção.

```ts
// 🚩 Gerado por IA: cada parâmetro é um literal, valores de dev embutidos
export async function syncOrders() {
  const res = await fetch("https://api.staging.acme.dev/v1/orders", {
    headers: { Authorization: "Bearer sk_test_4eC39HqLyjWDarjtT1zdp7dc" },
    signal: AbortSignal.timeout(30000),
  });
  const orders = (await res.json()).slice(0, 50); // por que 50?
  for (let i = 0; i < 3; i++) { /* tenta novamente 3x... por que 3? */ }
}

```

A linha Authorization é um alerta do gitleaks/Semgrep; a URL, `30000`, `50` e `3` são smells de valores mágicos; e `api.staging.acme.dev` é um valor de dev prestes a chegar à produção.

## Reasons for the Problem

**Por que os modelos produzem isso**

* **Um literal é o token seguinte de maior probabilidade.** Dado `fetch(`, a conclusão mais barata que satisfaz o prompt imediato é uma string de URL concreta, não `config.apiBaseUrl`. Resolver uma _referência_ exige saber que um símbolo existe em outro lugar; emitir um _valor_ não exige nada. Os modelos otimizam para um trecho localmente plausível e executável.
* **O corpus de treinamento é composto de trechos autocontidos.** Tutoriais, exemplos de README e respostas do Stack Overflow embutem seus valores para que rodem de forma independente. O modelo aprendeu que "bom código de exemplo" usa hardcode — o oposto da higiene de produção.
* **Sem contexto do repositório / janela limitada.** Normalmente o modelo não leu seu `config/`, o schema de env ou o arquivo de constantes, então não consegue reutilizá-los. A GitClear associa exatamente isso ao aumento da duplicação: os assistentes têm "menor probabilidade de propor a reutilização de uma função semelhante… em parte por causa do tamanho limitado do contexto", com blocos duplicados de mais de 5 linhas crescendo cerca de 8× em 2024, enquanto as linhas refatoradas ("movidas") caíram de \~24% para \~9,5%.
* **Bajulação / viés de responder ao prompt.** Quando solicitado a "adicionar uma sincronização de pedidos", o modelo entrega algo que funciona _agora_; externalizar a configuração é um esforço adicional que ele não fará por conta própria a menos que seja instruído.
* **Defasagem do corte de treinamento.** Literais embutidos costumam ser literais _desatualizados_ — endpoints antigos, versões de API descontinuadas, portas padrão ou constantes criptográficas fracas (MD5, chaves hardcoded). A OX Security descobriu que 62% do código gerado por IA é entregue com problemas e atribui chaves/segredos/caminhos hardcoded a padrões "aprendidos de bases de código legadas… \[com\] zero consciência de que os padrões de segurança evoluíram."

**Por que isso prejudica**

* **Manutenibilidade — Shotgun Surgery.** Mudar um único timeout ou URL base significa caçar cada literal duplicado por toda a base de código; se esquecer um, o comportamento diverge silenciosamente em cada ponto de chamada.
* **Correção entre ambientes.** Uma URL de staging ou um ID de conta de dev fixado na lógica acaba indo para produção; limiares mágicos sem nome ficam fora de sincronia com os valores que deveriam refletir.
* **Segurança.** Tokens/chaves hardcoded são vazamentos de credenciais — uma vez commitados, vivem para sempre no histórico do git. O estudo de código de build do arXiv (2601.16839) encontrou caminhos/URLs hardcoded e credenciais hardcoded de alta severidade recorrentes em arquivos de build gerados por IA.
* **Carga de revisão & dívida técnica.** Os revisores precisam verificar a procedência de _cada_ literal. O trabalho sobre smells específicos de IA (arXiv 2509.20491) observa que os modelos lidam bem com "literais dentro do escopo", mas têm dificuldade com casos **sensíveis a valores**, em que a correção depende de limiares que se propagam por funções auxiliares — exatamente os valores hardcoded que os humanos agora têm que auditar à mão. Segundo o Q&A do Stack Overflow com Eno Reyes, da Factory, a qualidade de base do código é "o único sinal" para saber se os agentes aceleram ou _desaceleram_ uma equipe — e o espalhamento de valores hardcoded corrói exatamente essa base.

## Treatment

**Táticas de prompting / revisão**

* **Aponte o modelo para sua superfície de configuração:** "Leia `src/config.ts` e `.env.example`; use `config.*` / `process.env` para cada URL, porta, timeout e credencial. Não introduza literais." Os modelos usam literais inline porque não sabem que o símbolo existe — nomeie-o.
* **Proíba valores mágicos explicitamente:** "Sem números ou strings mágicos — extraia constantes nomeadas." Depois, faça-o rodar `eslint --rule no-magic-numbers` e um scanner de segredos (gitleaks/Semgrep) e corrija o que eles sinalizarem. Conforme a orientação da Factory, integre linters/scanners ao loop para que o agente se autocorrija em vez de depender da revisão humana.
* **Forneça o schema de env** (zod/envalid/`.env.example`) para que o modelo tenha onde colocar os valores em vez de adivinhá-los.
* **Faça grep nos novos diffs** em busca de `http`, `localhost`, literais de IP, `Bearer ` e dígitos soltos em argumentos de chamada antes de fazer o merge.

**A refatoração** — nomeie os movimentos clássicos:

* **Substituir Número Mágico por Constante Simbólica** para limiares, contagens, tamanhos.
* **Extrair Função / Extrair Módulo de Configuração** para reunir os parâmetros em um único lugar tipado e validado.
* **Externalizar para o Ambiente** (12-factor) para tudo que difere por ambiente ou é secreto; nunca commite segredos.

```ts
// config.ts — fonte única e validada da verdade
import { z } from "zod";
const env = z.object({
  ORDERS_API_BASE_URL: z.string().url(),
  ORDERS_API_TOKEN: z.string().min(1),
  ORDERS_TIMEOUT_MS: z.coerce.number().default(30_000),
  ORDERS_PAGE_SIZE: z.coerce.number().default(50),
  ORDERS_MAX_RETRIES: z.coerce.number().default(3),
}).parse(process.env);
export const config = env;

```

```ts
// ✅ depois: referências, não literais — um único lugar para alterar, segredo fora do código-fonte
import { config } from "./config";
export async function syncOrders() {
  const res = await fetch(`${config.ORDERS_API_BASE_URL}/v1/orders`, {
    headers: { Authorization: `Bearer ${config.ORDERS_API_TOKEN}` },
    signal: AbortSignal.timeout(config.ORDERS_TIMEOUT_MS),
  });
  const orders = (await res.json()).slice(0, config.ORDERS_PAGE_SIZE);
  for (let i = 0; i < config.ORDERS_MAX_RETRIES; i++) { /* ... */ }
}

```

Se um segredo já foi parar em um commit, rotacione-o — remover a linha não apaga o histórico do git.

## Detected by

- **ESLint** `no-magic-numbers` — Proibir números mágicos (https://eslint.org/docs/latest/rules/no-magic-numbers)
- **SonarSource** `typescript:S109 / java:S109 — "Magic numbers should not be used"` — Números mágicos (https://rules.sonarsource.com/java/RSPEC-109/)
- **SonarSource** `java:S1075 — "URIs should not be hardcoded"` — URIs hardcoded (https://rules.sonarsource.com/java/RSPEC-1075/)
- **SonarSource** `java:S2068 — "Hard-coded credentials are security-sensitive"` — Credenciais hardcoded (https://rules.sonarsource.com/java/RSPEC-2068/)
- **Checkstyle** `MagicNumber` — Verificação de número mágico (https://checkstyle.org/checks/coding/magicnumber.html)
- **PMD** `AvoidUsingHardCodedIP` — Evitar endereços IP hardcoded (https://docs.pmd-code.org/latest/pmd_rules_java_bestpractices.html#avoidusinghardcodedip)
- **Bandit** `B105 hardcoded_password_string / B108 hardcoded_tmp_directory` — Senhas hardcoded / diretórios temporários (Python) (https://bandit.readthedocs.io/en/latest/plugins/b105_hardcoded_password_string.html)
- **gitleaks** `secret detection (e.g. generic-api-key, regex/entropy rules)` — Scanner de segredos hardcoded (https://github.com/gitleaks/gitleaks)
- **Semgrep** `generic.secrets / hardcoded-credentials registry rules` — Regras de segredos/configuração hardcoded (https://semgrep.dev/r?q=hardcoded)
- **eslint-plugin-no-secrets** `no-secrets/no-secrets` — Detecção de strings de alta entropia (segredos) (https://github.com/nickdeis/eslint-plugin-no-secrets)
