Soluções — Síntese Arquitetural: Núcleo Estável, Periferia Volátil e o Encerramento do Curso
Aula 14 — Programação Orientada a Objetos (Aula de Encerramento)
Dica(Resposta) Teste 1 — Núcleo Estável vs. Periferia Volátil
- ✔ Verdadeiro — A classificação núcleo/periferia é uma questão de frequência e origem da mudança, não de localização física no código-fonte. Uma regra de comissão alterada trimestralmente por pressão de marketing tem exatamente o perfil de mudança da periferia volátil, ainda que resida no mesmo pacote (ou até na mesma classe) que uma regra de faturamento estável — os dois merecem tratamento arquitetural diferente independentemente de onde estão fisicamente.
- ✗ Falso — A existência de um núcleo estável é uma propriedade de frequência real de mudança de um conjunto de regras, não uma propriedade que depende de haver interfaces formais já desenhadas. Um sistema mal arquitetado (sem nenhuma interface) ainda pode ter partes que mudam raramente — elas simplesmente não estão isoladas da periferia por uma abstração, o que é justamente o problema a corrigir, não uma prova de que “núcleo estável” não existe ali.
- ✔ Verdadeiro — A aula define o núcleo estável por dois critérios conjuntos: baixa frequência de mudança e conter contratos/regras de negócio abstratas do domínio. Um framework de testes satisfaz apenas o primeiro critério — pode ser extremamente estável sem, no entanto, expressar nenhuma regra de negócio. “Estável” é condição necessária, não suficiente, para ser núcleo; confundir os dois é o erro que este item testa.
- ✔ Verdadeiro — A intuição comum equipara “regra de negócio” a “núcleo estável” e “banco de dados” a “periferia volátil” só pela categoria técnica vs. de domínio. Este caso-limite mostra que essa equiparação automática pode falhar: se a lógica de pré-requisitos muda com alta frequência (a cada reforma curricular), ela se comporta como periferia volátil mesmo sendo, em espécie, uma regra de domínio — a classificação correta depende da frequência real observada, não do rótulo “técnico” ou “de negócio”.
Dica(Resposta) Teste 2 — A Regra de Ouro da Dependência
- ✔ Verdadeiro — A Regra de Ouro fala da direção da dependência de compilação/instanciação, não apenas de “existir uma interface em algum lugar do sistema”. Se o núcleo usa
newdiretamente sobre um tipo concreto volátil, o núcleo passa a depender fisicamente dessa classe (precisa recompilar se ela mudar de pacote, por exemplo) — mesmo que uma interface exista e não seja usada nesse ponto específico, a violação já ocorreu ali. - ✔ Verdadeiro — A Regra de Ouro é sobre a direção da dependência (sempre em direção à abstração, nunca do núcleo diretamente para uma implementação concreta), não sobre a proporção de código em cada lado. Um sistema pode ter uma periferia enorme em volume de código e ainda respeitar plenamente a regra, desde que todas as dependências apontem corretamente para as interfaces do núcleo.
- ✗ Falso — A Regra de Ouro protege especificamente o núcleo estável contra a volatilidade da periferia — ela não proíbe que duas peças de infraestrutura conversem diretamente entre si (por exemplo, um driver de banco de dados chamando uma biblioteca de rede). O risco arquitetural que a regra endereça é o núcleo depender do que muda, não qualquer dependência concreta que exista nos bastidores do sistema.
- ✔ Verdadeiro — O benefício estrutural da Regra de Ouro (a mudança na periferia não se propaga ao núcleo) não depende de a troca efetivamente já ter acontecido — depende apenas de a dependência apontar corretamente para a abstração. Mesmo com uma única implementação histórica, o sistema já está protegido caso essa implementação precise mudar no futuro; a ausência de troca até agora não invalida a proteção estrutural já existente.
Dica(Resposta) Teste 3 — Strategy vs. Adapter na Matriz de Decisão
- ✗ Falso — Strategy resolve a variação entre algoritmos que já falam a mesma língua (a mesma interface); ele não resolve incompatibilidade de assinatura. Se o novo serviço de terceiros tem uma API com assinatura diferente da interface
CalculadoraDeFrete, é necessário um Adapter para traduzir essa assinatura antes que o serviço possa, então, ser usado como mais uma implementação deCalculadoraDeFretedentro do Strategy já existente — os dois padrões se combinam, não se substituem. - ✔ Verdadeiro — Um Adapter cuja tradução é trivial (repasse puro, sem nenhuma conversão real) ainda é estruturalmente válido — é o caso degenerado do padrão, análogo ao Decorator com zero camadas ainda sendo uma aplicação válida da recursão. A validade estrutural do padrão não depende de a tradução ser complexa, só de a topologia (interface esperada, classe adaptada, adaptador entre as duas) estar presente.
- ✔ Verdadeiro — Como todos os algoritmos já compartilham a mesma interface própria do sistema, não há nenhuma incompatibilidade de assinatura a resolver — o problema é puramente de qual algoritmo escolher em cada contexto, a definição exata do acoplamento condicional que o Strategy ataca.
- ✗ Falso — Injeção de dependência via construtor é uma técnica geral, usada por praticamente todo o repertório de padrões deste curso (State, Decorator, Observer também a usam) e até fora de qualquer padrão nomeado. Nem toda classe que recebe uma dependência pelo construtor está aplicando Strategy ou Adapter — é preciso que exista, especificamente, variação de algoritmo (Strategy) ou incompatibilidade de interface a traduzir (Adapter) para que o nome do padrão se aplique.
Dica(Resposta) Teste 4 — Decorator vs. Observer na Matriz de Decisão
- ✔ Verdadeiro — Responsabilidades opcionais, cumulativas e combináveis livremente sobre um único objeto são exatamente a assinatura do Decorator (a mesma estrutura da cafeteria e da cadeia de notificadores) — não há aqui nenhum cenário de “um evento dispara reações em múltiplos subsistemas”, que é o que o Observer resolve.
- ✗ Falso — Mesmo com um único assinante fixo, o Observer ainda garante que o núcleo não conheça o tipo concreto do observador — o
Pedidocontinua dependendo só de uma interface abstrata, não da classeLogServiceespecificamente. Esse desacoplamento de identidade tem valor estrutural (testabilidade, possibilidade de substituição por um mock, por exemplo) independentemente de o número de assinantes nunca mudar na prática. - ✗ Falso — Operar em tempo de execução é uma característica que os dois padrões compartilham, mas o tipo de problema que cada um resolve é ortogonal (acumular responsabilidades sobre um único objeto vs. notificar múltiplos objetos independentes) — exatamente como Decorator para a cadeia de notificadores e Observer para o acoplamento de notificação em cascata coexistiram sobre o mesmo
Pedido, sem conflito. - ✔ Verdadeiro — O documento (Sujeito) notificando um número variável de cursores (Observadores) sem conhecê-los por nome é exatamente a topologia Subject/Observer — mesma estrutura, domínio diferente.
Dica(Resposta) Teste 5 — Aplicando a Matriz a um Cenário Novo
- ✔ Verdadeiro — O problema central é a incompatibilidade sintática entre formatos externos (exigidos por terceiros, as prefeituras) e o contrato interno do sistema — exatamente a coluna “Quando utilizar” do Adapter na matriz, não a de Strategy (que pressupõe algoritmos já compatíveis entre si).
- ✗ Falso — “Mudar em tempo de execução” não é, por si só, sinônimo de Adapter — é uma característica que Strategy também tem. Como todos os comportamentos já implementam a mesma interface própria do jogo (sem nenhuma incompatibilidade de assinatura a traduzir), o problema é de variação de algoritmo por contexto, a intenção principal do Strategy, não do Adapter.
- ✔ Verdadeiro — Responsabilidades (aqui, encargos financeiros) opcionais e cumulativas sobre um único objeto, evitando a explosão combinatória de subclasses, é exatamente a definição de intenção do Decorator na matriz.
- ✔ Verdadeiro — Um vínculo um-para-muitos, em que a mudança de estado (produto disponível novamente) aciona dependentes de forma anônima, é a definição de intenção principal do Observer na matriz.
Dica(Resposta) Teste 6 — Síntese do Curso: TRUE e o Custo de Mudança
- ✔ Verdadeiro — Reasonable é definida, na Aula 1, exatamente como “o custo de qualquer mudança deve ser proporcional ao benefício que ela traz” — o cenário descrito (uma classe nova, um benefício novo, nenhuma reescrita) é o exemplo direto dessa propriedade. Transparent fala de consequências óbvias, não de proporcionalidade de custo, então o mapeamento com Reasonable é o mais direto entre os dois.
- ✗ Falso — Isolar a incompatibilidade sintática do núcleo é, de fato, um ganho — mas é um ganho de Transparent (consequências contidas) e de proteção do núcleo, não de Usable, que é sobre o próprio código poder ser reaproveitado em contextos novos e inesperados. Um Adapter amarrado a um único SDK específico, sem nenhum potencial de reaproveitamento, não satisfaz Usable só por cumprir bem seu papel de isolamento — as duas propriedades do TRUE não são a mesma coisa.
- ✗ Falso — A matriz desta aula cobre quatro tipos específicos de acoplamento (condicional, sintático, taxonômico, temporal/identidade) — mas não afirma que são os únicos tipos de acoplamento nocivo possíveis em qualquer sistema. Persistência de fragilidade depois de aplicar os quatro padrões corretamente é evidência mais forte de uma quinta fonte de acoplamento ainda não mapeada do que de erro de implementação nos quatro já aplicados.
- ✗ Falso — A conclusão da aula é justamente o oposto: cada padrão ataca um sintoma/tipo de acoplamento específico e parcial; é a combinação complementar dos quatro — não a suficiência isolada de qualquer um deles — que responde ao problema mais amplo do custo de mudança. Exigir que um único padrão resolva sozinho todos os três sintomas contradiz a própria lógica da matriz apresentada nesta aula.