English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

un

visitante
1 / ?

Como o Sedimento de Código se Forma

Rochas sedimentares se formam por deposição, não por explosão. Cada camada: correta para sua época. Cada camada: mais antiga que a de cima. As camadas mais antigas calcificaram antes de o ecossistema amadurecer ao redor delas. Nenhum erro as causou. O tempo as causou.

MOAD-0001 funciona da mesma forma.

Camadas de Sedimento MOAD-0001: código copiado ao longo de décadas conforme N cresce

A História da Formação

Um grafo percorrido escrito em 1993:

List<Node> visited = new ArrayList<>();
Stack<Node> stack = new Stack<>();
stack.push(start);
while (!stack.isEmpty()) {
Node n = stack.pop();
if (!visited.contains(n)) {  // varredura linear O(N)
visited.add(n);
for (Node neighbor : n.getNeighbors())
stack.push(neighbor);
}
}

Este código: correto. Testes: passando. Em 1993, os grafos tinham 50 nós.

50 nós: 50 × 25 média escaneada = 1.250 operações. Invisível.

O código entrou no controle de versão. Foi copiado para tutoriais. Foi encapsulado em bibliotecas. Foi distribuído em ferramentas de build, gerenciadores de pacotes e resolvedores de dependências. Em 2024, o mesmo padrão rodava em grafos de dependência com 50.000 nós.

50.000 nós: 50.000 × 25.000 média escaneada = 1.250.000.000 operações.
Um build de 1 segundo vira 17 minutos.

O código não mudou. O mundo ao seu redor cresceu. Cada camada do sedimento: correta no momento da deposição. Cara na hora da escavação.

Seu Sedimento

O código sedimentar não contém um erro de lógica. Ele contém uma suposição de desempenho que deixou de valer à medida que a escala mudou. O código produz resultados corretos; apenas o custo mudou.

Essa distinção importa para o diagnóstico. Um erro de lógica produz respostas erradas. Um defeito sedimentar produz respostas corretas a um custo inaceitável.

Código sedimentar: código correto que se torna caro à medida que a escala ao seu redor muda. Dê um exemplo concreto de software que você já usou ou escreveu em que algo funcionava em pequena escala e se tornou um gargalo em grande escala. O que mudou: o código, o tamanho dos dados ou o padrão de uso?

Cinco Formas de MOAD-0001

MOAD-0001 aparece em cinco formas documentadas em mais de 60 ecossistemas de software. A estrutura: um teste de pertinência usando um container sequencial, aninhado dentro de um loop sobre a mesma coleção ou uma relacionada.

As Cinco Formas

DomínioPadrãoContainer SequencialContainer Correto
Travessia de grafoif (!stack.contains(n)) em DFS/TarjanArrayListHashSet
Deduplicação de rota/eventoTAILQ_FOREACH strcmp por requisiçãolista encadeadaHashMap
Rastreamento de colisãofindLinearSearch() por tick de físicaarrayunordered_set
Filtro de alocação de recursosList.contains() no filtro de streamArrayListHashSet
Lista aberta de pathfinding A*LocalVector::find() por vizinhovectoríndice armazenado no heap

Todos os cinco compartilham a mesma estrutura: uma verificação de pertinência aninhada em um loop, usando um container que exige uma varredura linear para responder à pergunta de pertinência.

A Lista de Palavras-chave de Varredura

Auditar para MOAD-0001 significa procurar palavras-chave de teste de pertinência dentro de loops:

- Python: in com uma variável list, .count(), list.index()

- Java: ArrayList.contains(), List.contains(), LinkedList.contains()

- JavaScript: Array.includes(), Array.indexOf(), Array.find()

- C++: std::vector::find(), loop manual com comparação ==

- Go: slices.Contains(), loop manual sobre um slice

A correção em todos os casos: substitua o container sequencial por um container hash. listset. ArrayListHashSet. ArraySet. vectorunordered_set. slicemap[T]struct{}.

Uma palavra-chave. Uma substituição. Nenhuma mudança de comportamento. Aceleração de 1.000× em N=1.000.

Auditar um Fragmento de Código

Aplique o reconhecimento de padrão MOAD-0001 a um fragmento de código real.

Você audita uma base de código JavaScript e encontra isto dentro de um loop que percorre todos os vizinhos de um grafo: `if (!openSet.includes(neighbor)) openSet.push(neighbor)`. Isso é MOAD-0001? O que você substituiria `openSet` e qual seria a mudança de complexidade de O(?) para O(?)?

Uma Linha, Quatro Linguagens [BLOCK_TYPE CONTENT fix_and_limits/the_fix]

A correção para MOAD-0001 em quatro linguagens: [BLOCK_TYPE CONTENT fix_and_limits/the_fix]

```python [BLOCK_TYPE CONTENT fix_and_limits/the_fix]

Python

[BLOCK_TYPE CONTENT fix_and_limits/the_fix]

visited = [] # ANTES: O(N) membership

visited = set() # DEPOIS: O(1) membership

```java
// Java
List<Node> visited = new ArrayList<>();    // ANTES
Set<Node> visited = new HashSet<>();       // DEPOIS
// JavaScript
const visited = [];      // ANTES: Array.includes() O(N)
const visited = new Set(); // DEPOIS: Set.has() O(1)
// visited.push(n) → visited.add(n)
// visited.includes(n) → visited.has(n)
// Go
visited := []NodeID{}              // ANTES: slices.Contains() O(N)
visited := make(map[NodeID]struct{}) // DEPOIS: map lookup O(1)
// _, ok := visited[n]  para verificação de pertinência
// visited[n] = struct{}{}  para inserção

Em todos os casos: mesmo comportamento, mesma saída, mesmos testes passando. Apenas a taxa de crescimento muda.

O Que a Correção NÃO Altera

- O comportamento lógico do algoritmo: busca em profundidade continua visitando em profundidade

- Correção de saída: os mesmos nós são visitados na mesma ordem (dentro do DFS)

- Resultados dos testes: qualquer teste que verifica a correção continua a passar

O Que a Correção MUDA

- Teste de pertinência: O(N) → O(1)

- Total do loop: O(N²) → O(N)

- Em N=1.000: 1.000× mais rápido

- Em N=10.000: 10.000× mais rápido

Um Limite: Ordem

Contêineres hash (set, HashSet, unordered_set) não preservam a ordem de inserção. Em Python 3.7+, dict preserva a ordem de inserção; set simples não. Em Java, HashSet não preserva ordem; LinkedHashSet preserva.

Se a ordem importa junto com a verificação de pertinência: mantenha duas estruturas. Um set (ou HashSet) para testes de pertinência O(1). Uma list (ou ArrayList) separada para travessia ordenada. Ou use LinkedHashSet em Java, que oferece ambos.

Para MOAD-0001 em travessia de grafos: visited responde a uma pergunta binária (este nó já foi visto?). A ordem não importa para a pergunta de pertinência. A ordem da travessia vem da pilha ou fila, não de visited.

Pertinência vs Ordenação

No algoritmo de Tarjan para componentes fortemente conectados, onStack rastreia quais nós permanecem na pilha de chamadas DFS atual. Ele deve responder a duas perguntas: (1) pertinência — este nó está atualmente na pilha? (2) no final de um caminho DFS, remover nós em ordem até que este nó apareça.

Uma implementação ingênua usa uma List para onStack, respondendo à pergunta de pertinência com contains() — O(N) por verificação, O(N²) no total para grafos grandes.

Você corrige uma implementação de Tarjan SCC substituindo `onStack = []` por `onStack = set()`. Os testes passam. Um revisor de código pergunta: 'mas e se a ordem importar para onStack?' Como você responde?

Por que Isso é uma Divulgação, Não um Patch

MOAD-0001 existe em mais de 1.000 sites verificados em mais de 60 ecossistemas de software. Travessia de grafos em ferramentas de build, deduplicação de rotas em daemons de roteamento de rede, detecção de colisão em motores de jogos, alocação de recursos em escalonadores de sistemas operacionais.

Cada site: código correto. Cada site: crescimento O(N²) esperando N cruzar um limite.

O Pipeline de Divulgação

Um patch sem divulgação upstream corrige apenas um site. O padrão reaparece na próxima versão, na próxima biblioteca, na próxima portabilidade de linguagem. Divulgação: nomeie o padrão, documente-o como CWE-407 (Complexidade Algorítmica: Complexidade Algorítmica Ineficiente), publique as heurísticas de reconhecimento e a correção de uma linha. Assim, todo desenvolvedor que ler a divulgação poderá reconhecer e corrigir sua própria instância.

Hamming chamou isso de 'dar um peixe vs ensinar a pescar'. O patch dá um peixe. A divulgação — MOAD-0001 nomeado, padrão documentado, correção generalizada — ensina a heurística.

A Extensão do Permacomputador

Hamming trabalhava em soluções pontuais: corrigir este filtro, melhorar este código. O Unhamming adiciona a camada de divulgação: nomear o padrão, publicar a heurística e entregá-la ao comum.

O princípio do conhecimento composto aplica-se aqui em escala de ecossistema. Um pesquisador nomeia um padrão. Cem desenvolvedores o reconhecem em seus próprios códigos. Mil linhas de código O(N²) tornam-se O(N). A infraestrutura fica mais rápida para todos que constroem sobre ela.

Este é o dragão crescendo: mesmo fogo (trabalhar em problemas importantes, conhecimento composto, pensamento sistêmico), voo diferente (divulgação aberta, propriedade comum, sem patrono necessário).