Soluções — Acoplamento e Contratos
Aula 5 — Programação Orientada a Objetos
Dica(Resposta) Teste 1 — Falso Desacoplamento
- ✗ Falso — É exatamente a distinção central do bloco. Acoplamento físico é sobre como as classes se instanciam/referenciam (construtor, arquivos separados); acoplamento lógico é sobre o que um método faz com a referência que recebeu.
PedidorecebiaCarrinhode forma fisicamente correta e ainda cometia Feature Envy processando os dados por fora. - ✔ Verdadeiro — O mecanismo do Feature Envy não depende do nome da classe orquestradora — depende de extrair os dados internos de um colaborador e processá-los por fora, em vez de pedir ao colaborador que faça o processamento.
RelatorioFinanceirocomete exatamente o mesmo erro estrutural quePedidocometia antes do Move Method. - ✗ Falso — É o oposto do que a Caixa Preta exige. Usar um getter para extrair a estrutura interna e processá-la por fora é justamente o mecanismo de Feature Envy — o getter não “legitima” o acesso, só disfarça a violação de encapsulamento atrás de uma chamada de método.
- ✔ Verdadeiro — É a mesma distinção do item (a), na direção afirmativa: possuir uma referência resolve só o acoplamento físico. Processar os dados obtidos por essa referência em vez de delegar o processamento ao próprio objeto é a violação lógica (Feature Envy/Tell-Don’t-Ask) que a aula ataca.
Dica(Resposta) Teste 2 — Feature Envy (Inveja de Recursos)
- ✗ Falso — A gravidade do Feature Envy está ligada a processar dados extraídos de outro objeto (iterar, somar, decidir com base neles) — não ao simples ato de chamar um getter uma vez. Uma leitura isolada e pontual não reproduz o padrão de
calcularCustoTotal(), que itera a lista inteira doCarrinhoe recalcula por fora. - ✔ Verdadeiro — É o sintoma descrito por Fowler e retomado nesta aula: a obsessão por getters para extrair e processar dados de fora é o sinal mais visível de que um método deveria pertencer à classe que detém os dados.
- ✗ Falso — Renomear não muda a mecânica:
Pedidocontinuaria extraindo a lista de itens doCarrinhoe somando por fora, exatamente a violação original. Move Method resolve o problema porque move o comportamento para onde os dados estão — um nome novo no método antigo não move nada. - ✗ Falso — Feature Envy É a violação de Tell-Don’t-Ask em ação: em vez de “mandar” o
Carrinhocalcular seu próprio total (Tell),Pedido“pergunta” pelos itens e calcula por conta própria (Ask). As duas ideias descrevem o mesmo problema de ângulos diferentes.
Dica(Resposta) Teste 3 — A Métrica CBO
- ✔ Verdadeiro — CBO conta classes externas distintas, não chamadas de método. Uma classe pode chamar 50 métodos diferentes de uma única classe externa e ainda ter CBO=1 — o número de chamadas afeta outras métricas (como acoplamento de mensagens), não o CBO.
- ✔ Verdadeiro — É a generalização do resultado numérico visto na aula (CBO de
Pedidocaindo de 2 para 1 ao remover a dependência direta deProduto): sempre que a delegação elimina uma dependência transitiva que só existia para o processamento manual, o CBO da classe que delega tende a cair. - ✔ Verdadeiro — É a mesma lógica do exemplo isolado (2 classes) escalada para um sistema real com centenas de classes: menos dependências por classe significa menos superfície afetada quando uma dependência muda, e menos colaboradores reais para simular/mockar em um teste unitário.
- ✗ Falso — CBO=0 significa nenhuma conexão com nenhuma outra classe — um objeto assim não colabora com nada e não pode cumprir nenhum papel útil no sistema. A meta não é eliminar conexões, é manter cada conexão o mais fraca possível (assunto do próximo bloco, a Escala de Myers).
Dica(Resposta) Teste 4 — Acoplamento de Conteúdo e Comum
- ✗ Falso — Com
itensprivado,c.itenssimplesmente não compila fora da classeCarrinho— o próprio compilador Java bloqueia o Acoplamento de Conteúdo nesse caso. A visibilidade do atributo é exatamente o que decide se essa violação é possível ou não. - ✔ Verdadeiro — Um atributo público remove a barreira que impediria outra classe de alterar o estado interno diretamente — é a pré-condição estrutural para o “pecado original” da Escala de Myers.
- ✗ Falso — É o oposto: uma chamada estática (como
Notificacao.enviarEmailConfirmacao(...)) está embutida diretamente no corpo do método, sem nenhum ponto de injeção — não há como substituí-la por um mock sem alterar o próprio código de produção, tornando o teste isolado muito mais difícil, não mais fácil. - ✔ Verdadeiro — Uma dependência recebida pelo construtor aparece na assinatura da classe, visível para qualquer leitor. Uma chamada estática enterrada dentro do corpo de um método só aparece para quem lê o código-fonte inteiro — daí o acoplamento comum ser mais “invisível” que o acoplamento por associação.
Dica(Resposta) Teste 5 — Acoplamento de Estampa e de Dados
- ✔ Verdadeiro — O mecanismo é idêntico: um método recebe um objeto inteiro (
Funcionario) mas usa só uma fração dele (o salário), herdando uma dependência transitiva a toda a estrutura deFuncionariosem necessidade — exatamente comoNotificacaoEmaildependia deClienteinteiro só para ler o e-mail. - ✔ Verdadeiro — Como o receptor depende do tipo inteiro (não só do dado que usa), qualquer mudança estrutural nesse tipo — inclusive um simples
rename— quebra a compilação do receptor, mesmo que a lógica de e-mail em si não tenha mudado uma linha. - ✔ Verdadeiro — O Acoplamento de Dados continua sendo o nível ideal em termos de desacoplamento, mas tem um custo real quando levado ao extremo: uma lista longa de parâmetros primitivos posicionais é difícil de ler e propensa a erro (trocar a ordem de dois
String, por exemplo) — um trade-off que a aula não nega, só não aprofunda. - ✗ Falso — É o oposto do observado no exemplo: ao deixar de exigir um
Clienteinteiro e passar a aceitar só o e-mail (String),Notificacaoganha reutilização — pode notificar clientes, fornecedores ou administradores sem carregar a bagagem de nenhum tipo específico.
Dica(Resposta) Teste 6 — GRASP: Especialista na Informação
- ✗ Falso — O Especialista na Informação é definido por quem possui (ou, aqui, originalmente recebe) os dados necessários — nesse cenário,
Cliente. Ter “acesso igual” não muda quem é o especialista; GRASP recomendaria manter a validação emCliente, não movê-la paraPedido. - ✗ Falso — Conter (associação) não é o mesmo que ser o Especialista na Informação. O critério do GRASP é quem possui os dados necessários para a tarefa — no caso,
Carrinho, que tem a lista de itens e preços, nãoPedido, que só tem uma referência a ele. - ✔ Verdadeiro — É a mesma lógica de
Carrinho/calcularCustoTotal()aplicada a um cenário novo: se as três classes só extraem o preço via getter para calcular o imposto por fora, isso é Feature Envy em relação aProduto; o Especialista na Informação (quem tem o preço) deveria assumir o cálculo. - ✗ Falso — Esse cenário-limite é exatamente a Classe Deus discutida na Aula 4 — o GRASP não anula os critérios de coesão e SRP; “ter os dados” não é licença para acumular responsabilidades de domínios completamente diferentes. O Especialista na Informação pressupõe um design já razoavelmente coeso, não justifica concentração ilimitada.
Dica(Resposta) Teste 7 — O Limite da Composição
- ✔ Verdadeiro — É exatamente o código de abertura do bloco: mesmo com composição bem-feita (atributo privado, associação correta),
Clientecontinua acoplado à implementação concretaCartao, o limite que o bloco se propõe a resolver. - ✗ Falso — É precisamente o “pesadelo da expansão” descrito na aula: cada novo meio de pagamento exige reabrir e recompilar
Cliente, violando o Princípio Aberto/Fechado (fechado para modificação). - ✔ Verdadeiro — A cadeia de
if/elsesó existe porqueClienteprecisa distinguir manualmente entreCartao,PixeBoleto— tipos concretos. SeClientedependesse de uma abstração comum, não haveria necessidade de checar qual implementação está em uso. - ✔ Verdadeiro — Retoma o conceito de Plug-and-Play da Aula 3: um sistema só aceita novos componentes “no encaixe” quando depende de contratos/abstrações, não de classes concretas específicas — exatamente o que o DIP, no bloco seguinte, resolve.
Dica(Resposta) Teste 8 — Inversão de Dependência (DIP)
- ✔ Verdadeiro — O DIP exige que módulos de alto e baixo nível dependam de uma abstração — não especifica que essa abstração precise ser uma interface. Uma classe abstrata bem desenhada, sem referências diretas a implementações concretas de pagamento, cumpre o mesmo papel estrutural.
- ✗ Falso — É o inverso exato do DIP: são os detalhes concretos (
Cartao,Pix) que devem se adequar e depender da abstração (Pagavel); a abstração nunca deve conhecer ou depender de nenhuma implementação específica. - ✔ Verdadeiro — É a metáfora usada nesta aula para descrever o resultado prático do DIP: o núcleo de negócio (
Cliente) fica isolado por trás da abstração, e a infraestrutura (Cartao,Pix, futuros meios de pagamento) muda livremente sem atravessar esse muro. - ✗ Falso — Tratamento de exceção não resolve acoplamento estrutural.
Clientecontinuaria fisicamente amarrado à classe concretaCartao; qualquer novo meio de pagamento ainda exigiria reabrirCliente. O DIP exige trocar a dependência concreta por uma abstração, não envolvê-la emtry/catch.
Dica(Resposta) Teste 9 — O Princípio Aberto/Fechado (OCP) e o DIP
- ✔ Verdadeiro — O custo do OCP só se manifesta quando o sistema precisa crescer — é aí que reabrir classes antigas se torna um problema. Num sistema hipotético congelado para sempre, violar o OCP nunca geraria retrabalho, porque nunca haveria extensão a ser feita.
- ✗ Falso — É exatamente o exemplo de violação do OCP usado nesta aula: cada novo meio de pagamento força a reabertura e recompilação de
Cliente, o oposto de “fechado para modificação”. - ✔ Verdadeiro — Ao depender da abstração, novos meios de pagamento podem ser adicionados implementando
Pagavel, sem tocar emCliente— extensão sem modificação, exatamente o que o OCP exige. - ✔ Verdadeiro — É a síntese dos dois princípios apresentada no fim do bloco: o DIP fornece o mecanismo (dependência de abstrações), e o OCP é o benefício resultante (extensão sem modificação do núcleo).
Dica(Resposta) Teste 10 — Barreira da Tipagem e o Gancho para Polimorfismo
- ✔ Verdadeiro — É exatamente o mecanismo que o gancho da aula anuncia: o compilador aceita a substituição porque ambas as classes concretas cumprem o mesmo contrato de tipo (
Pagavel), ainda que o mecanismo exato (Polimorfismo) só seja explicado na Aula 6. - ✗ Falso — Sem um contrato compartilhado (interface ou superclasse comum), o compilador Java rejeitaria uma variável que ora recebe
Pix, oraCartao— são tipos incompatíveis do ponto de vista do sistema de tipos sem esse elo formal. - ✔ Verdadeiro — Em linguagens dinamicamente tipadas, qualquer objeto que responda aos métodos esperados pode ser usado no lugar de outro, sem nenhuma verificação prévia de contrato — a flexibilidade existe, mas sem a garantia estática que Java oferece via interfaces.
- ✔ Verdadeiro — O Polimorfismo resolve o problema de uma mesma variável precisar aceitar tipos concretos diferentes. Se só existisse um único tipo concreto possível, não haveria “múltiplas identidades” a conciliar, e o problema que motiva o gancho para a Aula 6 nunca teria surgido.
Dica(Resposta) Teste 11 — Cirurgia de Espingarda e Efeito Cascata
- ✗ Falso — É exatamente o oposto do que a centralização promete: com a lógica de soma/desconto morando num único lugar, uma mudança de regra é feita uma vez só, ali — não há mais “quatro classes” para caçar, porque a duplicação que causava a Cirurgia de Espingarda já foi eliminada.
- ✔ Verdadeiro — Cirurgia de Espingarda é sobre ter que alterar vários lugares para uma única mudança de regra; sem duplicação nenhuma, não existem “vários lugares”. CBO é uma métrica diferente (quantas classes externas uma classe conhece), independente de haver ou não duplicação de lógica de negócio — os dois problemas não se implicam.
- ✔ Verdadeiro — É o mesmo padrão estrutural do exemplo de soma do carrinho (lógica espalhada em
Pedido,Fatura,Checkout,RelatorioFinanceiro), só transportado para o domínio de cálculo de frete — a duplicação, não o domínio, é o que causa a Cirurgia de Espingarda. - ✗ Falso — CBO mede quantas classes externas uma classe conhece — não diz nada sobre se a mesma regra de negócio foi implementada de forma independente em outras classes do sistema. É perfeitamente possível ter CBO=1 em várias classes que, cada uma, reimplementa a mesma lógica de desconto por conta própria.
Dica(Resposta) Teste 12 — Síntese: do Acoplamento ao Contrato
- ✔ Verdadeiro — Cada ferramenta ataca um ângulo diferente do mesmo problema: coesão (Aula 4) mede o quão unificada é uma classe por dentro; CBO conta quantas dependências existem; a Escala de Myers julga a qualidade de cada uma; GRASP decide onde colocar cada responsabilidade. Nenhuma substitui as outras.
- ✗ Falso — São dois problemas independentes. Feature Envy é sobre extrair e processar dados de um colaborador por fora (resolvido por Move Method); o acoplamento a classes concretas é sobre depender de uma implementação específica em vez de uma abstração (resolvido pelo DIP). Um
Pedidosem Feature Envy ainda pode estar rigidamente acoplado aCartao. - ✔ Verdadeiro — É a síntese apresentada na conclusão da aula: as quatro ideias (CBO, Escala de Myers, GRASP, DIP) não competem entre si — um design maduro busca as quatro propriedades simultaneamente.
- ✔ Verdadeiro — É o gancho explícito da conclusão: o DIP introduz a ideia de depender de uma abstração (
Pagavel), mas deixa em aberto o mecanismo de linguagem que torna essa abstração real e exigível pelo compilador — o assunto da Aula 6 (Interfaces).