Acoplamento e Contratos

Aula 5 — Programação Orientada a Objetos

Marcos M. Raimundo — Instituto de Computação, UNICAMP

2026-08-26

Proposta da Aula

Aula 4 ensinou a conectar objetos. Será que já basta para ter baixo acoplamento?

Não. Passar a dependência certinho pelo construtor não impede a classe de invadir a caixa preta do colaborador por dentro.

Roteiro: Feature Envy → métricas (CBO, Myers) → GRASP → Inversão de Dependência.

O Falso Desacoplamento

Associação Correta, Comportamento Errado

public Pedido(Carrinho carrinho) { this.carrinho = carrinho; } // ok

public double calcularCustoTotal() {
    double total = 0.0;
    for (Produto p : carrinho.getItens()) total += p.precoFinal(); // Feature Envy!
    return total;
}

Pedido extrai os dados do Carrinho para processar por fora — a estrutura está certa, o comportamento não.

A Cura: Move Method

public double calcularCustoTotal() {
    return this.carrinho.getTotal(); // delegacao pura
}

Se a regra de soma mudar, e vários lugares “espreitam” o carrinho, é Cirurgia de Espingarda de novo.

Medindo o Acoplamento: a Métrica CBO

CBO: Contando Dependências

for (Produto p : carrinho.getItens()) { total += p.precoFinal(); } // CBO(Pedido) = 2
return this.carrinho.getTotal(); // CBO(Pedido) = 1

Não é buscar CBO zero — é manter cada conexão o mais fraca possível.

Se o CBO de uma classe é baixo, isso já garante que o acoplamento dela é saudável?

Escreva sua resposta e compare com um colega antes de avançar (2 min).

Feature Envy e CBO

Dica

Julgue V ou F — a questão só conta se acertar os 4 itens:

  1. Passar uma dependência via construtor garante, por si só, o desacoplamento lógico entre as classes.
  2. Feature Envy é o sintoma de um método mais interessado nos dados de outra classe do que nos seus próprios.
  3. Refatorar de Inveja de Recursos para Delegação Pura reduz o CBO da classe orquestradora.
  4. Um CBO baixo, isoladamente, já garante que a qualidade de cada dependência restante é saudável.

Feature Envy e CBO — Resposta

Dica

  1. Falso — é exatamente a “falsa segurança” desta aula: estrutura correta não garante comportamento correto.
  2. Verdadeiro — é a definição de Fowler para o code smell.
  3. Verdadeiro — o exemplo Pedido mostrou CBO caindo de 2 para 1.
  4. Falso — CBO conta quantas dependências existem, não quão saudável cada uma é; é preciso a Escala de Myers para isso.

A Escala de Myers: Qualidade da Dependência

Nível 1 (Pior): Acoplamento de Conteúdo

public List itens = new ArrayList<>(); // publico!
c.itens.clear(); // outra classe mutila o estado por fora

Nível 2: Acoplamento Comum (Global)

Notificacao.enviarEmailConfirmacao(this.cliente, this.rastreio); // estatico, oculto

Impossível testar sem disparar o e-mail de verdade.

Nível 3: Acoplamento de Estampa

public void enviarConfirmacao(Cliente cliente) { // so precisa do email!
    String email = cliente.getEmail();
}

Nível 4 (Ideal): Acoplamento de Dados

public static void enviarEmailConfirmacao(String emailDestino, String rastreio) { ... }

Notificacao não sabe mais que Cliente existe — reutilizável em qualquer contexto.

Por que o Acoplamento de Estampa é considerado “médio” — pior que Dados, mas melhor que Comum ou Conteúdo?

Escreva sua resposta e compare com um colega antes de avançar (2 min).

A Escala de Myers

Dica

Julgue V ou F — a questão só conta se acertar os 4 itens:

  1. O Acoplamento de Conteúdo, o pior nível, ocorre quando uma classe modifica diretamente atributos de outra.
  2. O Acoplamento Comum via métodos estáticos é fácil de testar, pois não exige instanciar objetos.
  3. O Acoplamento de Estampa cria dependências transitivas: quem recebe o objeto herda tudo que ele conhece.
  4. O Acoplamento de Dados é o nível ideal, pois módulos comunicam-se só com o estritamente necessário.

A Escala de Myers — Resposta

Dica

  1. Verdadeiro — é a definição do “pecado original”.
  2. Falso — pelo contrário, é o mais difícil de testar, pois a dependência fica oculta e não pode ser substituída por um mock.
  3. Verdadeiro — é o risco central do Acoplamento de Estampa.
  4. Verdadeiro — é a definição do nível ideal.

GRASP: o Especialista na Informação

O Princípio (GRASP, Larman)

A responsabilidade pertence a quem tem a informação necessária para cumpri-la.

“Calcular o total” precisa da lista de itens → mora no CarrinhoCarrinho é o Especialista.

Comportamento segue dados: resolve Feature Envy e mantém a lógica de negócio centralizada.

O Limite da Composição e o Muro de Fronteira (DIP)

O Limite: Acoplamento a Classes Concretas

public class Cliente {
    private Cartao cartao; // alto nivel depende de baixo nivel
}

O Pesadelo da Expansão

public void pagar(double valor) {
    if (this.cartao != null) this.cartao.processar(valor);
    else if (this.pix != null) this.pix.transferir(valor);
    else if (this.boleto != null) this.boleto.gerarCodigoBarra(valor);
}

Cada novo meio de pagamento reabre Cliente — viola o Princípio Aberto/Fechado.

DIP: o Muro de Fronteira

private Pagavel formaDePagamento; // abstracao, nao implementacao
public void pagar(double valor) { this.formaDePagamento.pagamentoConfirmado(valor); }

Inversão: Cartao/Pix se adaptam ao contrato — Cliente fica imune a novidades.

O Gancho: Múltiplas Identidades

Como a mesma variável Pagavel aceita ora um Pix, ora um Cartao? Resposta: Polimorfismo — próxima aula.

O que exatamente “se inverteu” no Princípio da Inversão de Dependência — o que dependia de quê antes, e o que passa a depender de quê depois?

Escreva sua resposta e compare com um colega antes de avançar (2 min).

Inversão de Dependência

Dica

Julgue V ou F — a questão só conta se acertar os 4 itens:

  1. No DIP, tanto o módulo de alto nível quanto o de baixo nível devem depender de uma abstração comum.
  2. Antes do DIP, Cliente (alto nível) dependia diretamente de Cartao (baixo nível).
  3. Depois do DIP, é Cliente que precisa se adaptar às mudanças em Cartao e Pix.
  4. A cadeia de if/else para escolher entre Cartao, Pix e Boleto é um sintoma de violação do Princípio Aberto/Fechado.

Inversão de Dependência — Resposta

Dica

  1. Verdadeiro — é a essência do DIP.
  2. Verdadeiro — é o problema de design descrito no início do bloco.
  3. Falso — é o oposto: depois da inversão, são Cartao e Pix que se adaptam ao contrato de Cliente.
  4. Verdadeiro — cada novo meio de pagamento reabre o código existente, violando OCP.

Conclusão

O que Aprendemos

  1. Associação correta não garante desacoplamento lógico (Feature Envy)
  2. CBO mede quanto; a Escala de Myers mede quão tóxico
  3. GRASP: responsabilidade pertence a quem tem a informação
  4. DIP: alto e baixo nível dependem de abstrações, nunca um do outro

Próxima aula: Interfaces e Herança — os mecanismos que tornam Pagavel real.