Todo projeto tem um desses arquivos. Você o abre e a barra de rolagem fica fina como um fio.
Este conteúdo continua o artigo anterior Code smell #3.
O nome pode ser AppManager, MainViewController ou DataStore. Também é o arquivo que mais muda e mais gera conflitos na equipe.
É um God Object.
Em 『AntiPatterns』, publicado em 1998, isso é chamado de The Blob (Informações da publicação). O termo descreve uma massa que cresce absorvendo continuamente responsabilidades e dados ao redor.
O que é um God Object
Não é definido apenas pelo número de linhas. Mesmo um tipo de 2.000 linhas, se faz uma única coisa, é apenas um tipo grande (Estudo para identificar God Class).
O que define um God Object é o alcance do que ele conhece. Se os três pontos se sobrepõem, quase certamente é um.
- **Ele sabe demais.**Rede, banco de dados, estado da tela, informações de login e pagamentos ficam em um único tipo.
importA lista já revela isso. - **Coisas demais sabem sobre ele.**O tipo é referenciado em todo o projeto. Se for um singleton, os caminhos de referência ficam ocultos no código e o problema piora.
- **O estado está espalhado.**Há trinta propriedades, mas ninguém sabe quais combinações são válidas.
Ninguém consegue mais responder se é possível isLoading ser true enquanto error também não for nil.
No iOS, esse papel geralmente é claro: o view controller.
O layout de uma tela, as chamadas de rede, a fonte de dados da tabela, as transições e o gerenciamento de estado ficam todos em um arquivo.
Essa estrutura é chamada de Massive View Controller. Tipos com AppDelegate e Manager no nome também são comuns.
Por que continua crescendo
Ninguém decidiu criá-lo assim. Esse é o ponto.
Um God Object não é uma decisão de design, mas o resultado da gravidade.
Suponha que seja preciso adicionar uma funcionalidade. Todos os dados necessários já estão nessa classe.
| Escolha | Custo |
|---|---|
| Adicionar um método à classe existente | 20 minutos |
| Criar um novo tipo | Passar dependências, preparar a inicialização e cuidar do ciclo de vida: meio dia |
Cada escolha é razoável, mas sempre aponta na mesma direção. Assim, um arquivo de 200 linhas vira um arquivo de 4.000 linhas três anos depois.
Cada etapa desse crescimento tem uma justificativa legítima, por isso é difícil voltar atrás.
Além disso, surge o efeito das janelas quebradas. Ninguém se opõe a adicionar mais 50 linhas a um arquivo que já tem 3.000.
A resistência psicológica é diferente quando se adicionam 50 linhas a um arquivo de 200.
Onde dói
O dano aparece de quatro formas.
- **Os testes se tornam impossíveis.**Para criar esse tipo, são necessários rede, banco de dados e sessão do usuário. Você quer validar uma lógica de cálculo pura, mas o servidor precisa estar rodando.
- **O trabalho paralelo fica bloqueado.**Três pessoas desenvolvem funcionalidades diferentes, mas todas alteram o mesmo arquivo. Os conflitos são constantes e as mudanças se misturam na revisão.
- **Não dá para saber o impacto de uma alteração.**Para prever o que quebrará ao mudar uma propriedade, é preciso conhecer as 4.000 linhas. Na prática, ninguém conhece, então outra propriedade é adicionada e o arquivo cresce de novo.
- **Não é reutilizável.**Outra tela também precisa da lógica de formatação de datas, mas extraí-la arrasta a classe inteira. Então ela é copiada e colada.
A primeira consequência é especialmente grave. Sem testes, não dá para dividir; sem dividir, ele continua crescendo.
Esse ciclo é o verdadeiro motivo de um God Object sobreviver por tanto tempo.
Como perceber que está crescendo
Use sinais, não sensações.
Sinal 1 · Frequência de mudanças no Git
É o indicador mais prático. Ao listar os arquivos mais alterados no último ano, o God Object costuma aparecer no topo.
git log --format=format: --name-only --since=1.year.ago \
| grep '\.swift$' | sort | uniq -c | sort -rn | head -20
Mudanças frequentes indicam que o arquivo muda por motivos diferentes: uma medição real da violação do princípio da responsabilidade única.
Sinal 2 · Coesão
Se os métodos tocam apenas conjuntos diferentes de propriedades, esse tipo provavelmente é, na verdade, dois tipos.
Cinco métodos que usam apenas A e B e seis que usam apenas C e D já mostram um possível limite.
Sinal 3 · Regra de tamanho do tipo
Se você usa SwiftLint, type_body_length e file_length vêm ativados por padrão.
O aviso padrão é de 250 linhas para o corpo do tipo e 400 para o arquivo, ajustável ao projeto. Os números são arbitrários, mas ultrapassar o limite inicia uma conversa, e isso já tem valor.
Ordem de desmontagem
Reescrever tudo de uma vez quase sempre falha. Existe uma ordem.
| # | Etapa | O que fazer |
|---|---|---|
| 1 | Criar uma rede | Se não houver testes, comece criando testes de caracterização |
| 2 | Separar lógica sem estado | Extraia primeiro formatação de datas, validação de strings e cálculo de valores |
| 3 | Separar grupos de estado | Agrupe em um tipo as propriedades que mudam juntas |
| 4 | Separar por função | Divida em fonte de dados, coordenador, view model e view controllers filhos |
| 5 | Bloquear o caminho de absorção | Defina o lugar do código novo e estabeleça um limite |
Um teste de caracterização não registra se o código está correto, mas como ele funciona agora. É uma técnica descrita por Michael Feathers em 『Working Effectively with Legacy Code』.
O objetivo é mover preservando o comportamento, então o comportamento atual é a linha de base.
A segunda etapa é a mais fácil: separar lógica que não usa o estado da instância. Nessa etapa, o arquivo costuma diminuir bastante.
Na terceira etapa, enum é útil no Swift. Se três estados de tela sempre mudam juntos, eles formam um único objeto de estado.
// Antes: combinações inválidas podem ser representadas
var isLoading = false
var items: [Item] = []
var error: Error?
// Depois: apenas um dos três existe
enum ViewState {
case loading
case loaded([Item])
case failed(Error)
}
Agrupá-los com enum elimina as combinações impossíveis.
No iOS, o caminho da quarta etapa é claro: fonte de dados da tabela em um tipo separado, transições em um coordenador, estado da tela e regras de apresentação em um view model, e telas grandes em view controllers filhos.
Sem a quinta etapa, tudo volta ao estado original em seis meses. Defina o lugar do código novo e crie um limite, com regras de tamanho ou acordos de revisão, para impedir que a próxima funcionalidade volte ao arquivo.
Duas formas de falhar ao dividir
| Forma de falha | O que acontece |
|---|---|
| Mudar apenas os nomes | Você dividiu AppManager em UserManager, DataManager e NetworkManager, mas os três referenciam uns aos outros por completo. O God Object só virou um God Cluster. |
| Dividir demais | Se uma classe de 4.000 linhas for dividida em 40 tipos, desta vez o fluxo desaparece. É o código ravioli do artigo anterior. |
Ao dividir, verifique também se as dependências fluem em apenas uma direção.
O objetivo não é criar fragmentos, mas fazer cada fragmento mudar apenas pelo próprio motivo. A quantidade de fragmentos é apenas o resultado.
Resumo
- Um God Object é identificado pelo alcance do que conhece, não pelo tamanho. Se conhece muito, é muito conhecido e tem estado espalhado, ele se enquadra.
- Ele cresce não por ser um design ruim, mas porque cada vez se escolhe a opção mais barata.
- O maior dano é a impossibilidade de testar. Sem testes, não dá para dividir; sem dividir, ele continua crescendo.
- A lista dos arquivos com maior frequência de mudanças no Git é um indicador prático.
- A ordem é teste de caracterização → lógica sem estado → grupos de estado → separação por funções; por fim, bloqueie o caminho que faria tudo crescer novamente.
O próximo artigo trata do problema encontrado depois de dividir um God Object: precisar alterar doze arquivos para mudar uma funcionalidade, a cirurgia de espingarda.
Fontes e critérios de verificação
- AntiPatterns — Wiley · dados oficiais · verificado em 2026-08-17 · base: informações de publicação de AntiPatterns de 1998 e contexto de The Blob
- Human Perception on God Class Detection — Springer Nature · artigo original · verificado em 2026-08-17 · base: experimento controlado sobre diferenças entre pessoas e ferramentas na identificação de God Class

![Imagem de capa de [Code smell #4] Guia completo sobre God Object](/assets/images/posts/c44a316d-1d8c-4de3-8558-2b5452bdbcfe/god-object-dependency-overload.jpg)