🧩 Exercícios: SOLID II: ISP e DIP / IoC
Módulo 10: Paradigmas & Padrões • Bloco 2: SOLID & GRASP • Trilha em 4 Níveis
🎯 Nível 1: Fundamentos
Problema 06.1 — Segregação de Interface de Dispositivo de Armazenamento
Contexto: Uma interface monolítica IStorageDevice força dispositivos a implementar métodos incompatíveis com seu hardware (ex.: pendrive implementando ejeção de bandeja de CD).
Requisitos de Execução:
- Segregue a interface monolítica em contratos menores:
ILeitor,IEscritoreIEjetavel. - Implemente
PenDriveUSB(implementaILeitoreIEscritor) eDriveLeitorCD(implementaILeitoreIEjetavel). - Demonstre a segurança de tipos sem métodos vazios ou exceções artificiais.
Resultado Esperado
=== Operação de Dispositivos Conforme ISP ===
[PenDrive USB] Lendo bloco de dados... -> '010101'
[PenDrive USB] Gravando 512 bytes em flash... -> OK
[Leitor de CD] Lendo trilha ótica... -> 'TRILHA_01'
[Leitor de CD] Ejetando bandeja física!
📤 Instruções de Entrega (Microsoft Teams)
- Salve o arquivo como:
Atividade_06_1_SeuNome.py - Envie na tarefa:
Atividade Cap 06 - SOLID II: ISP e DIP
🔑 Gabarito de Código & Solução Comentada
# Atividade_06_1_Gabarito.py
from abc import ABC, abstractmethod
class ILeitor(ABC):
@abstractmethod
def ler(self) -> str: pass
class IEscritor(ABC):
@abstractmethod
def escrever(self, dados: str) -> None: pass
class IEjetavel(ABC):
@abstractmethod
def ejetar(self) -> None: pass
class PenDriveUSB(ILeitor, IEscritor):
def ler(self) -> str:
print("[PenDrive USB] Lendo bloco de dados... -> '010101'")
return "010101"
def escrever(self, dados: str) -> None:
print(f"[PenDrive USB] Gravando {len(dados)} bytes em flash... -> OK")
class DriveLeitorCD(ILeitor, IEjetavel):
def ler(self) -> str:
print("[Leitor de CD] Lendo trilha ótica... -> 'TRILHA_01'")
return "TRILHA_01"
def ejetar(self) -> None:
print("[Leitor de CD] Ejetando bandeja física!")
if __name__ == "__main__":
print("=== Operação de Dispositivos Conforme ISP ===")
usb = PenDriveUSB()
usb.ler()
usb.escrever("dados_binarios_de_teste_512")
cd = DriveLeitorCD()
cd.ler()
cd.ejetar()
🔍 Nível 2: Prática
Problema 06.2 — Inversão de Dependências com Gateway de Pagamento
Contexto: O ProcessadorCheckout não deve instanciar diretamente classes concretas como StripeAPI ou MercadoPagoSDK com new/construtor direto, para possibilitar testes com Mock.
Requisitos de Execução:
- Crie a interface abstrata
IGatewayPagamento. - Implemente os adaptadores concretos
StripeGatewayeMockPagamentoSucesso. - Injete o gateway via construtor no
CheckoutServicee execute o teste com Mock em 0ms.
Resultado Esperado
=== Teste Automatizado de Checkout (Mock DIP) ===
[Mock Gateway] Simulando aprovação instantânea de R$ 250.00
Transação aprovada com sucesso! Código de Autorização: #AUTH_MOCK_88192
📤 Instruções de Entrega (Microsoft Teams)
- Salve o arquivo como:
Atividade_06_2_SeuNome.py - Envie na tarefa:
Atividade Cap 06 - SOLID II: ISP e DIP
🔑 Gabarito de Código & Solução Comentada
# Atividade_06_2_Gabarito.py
from abc import ABC, abstractmethod
from dataclasses import dataclass
@dataclass
class TransacaoResponse:
autorizado: bool
codigo_autorizacao: str
class IGatewayPagamento(ABC):
@abstractmethod
def debitar(self, cartao_token: str, valor: float) -> TransacaoResponse: pass
class MockPagamentoSucesso(IGatewayPagamento):
def debitar(self, cartao_token: str, valor: float) -> TransacaoResponse:
print(f"[Mock Gateway] Simulando aprovação instantânea de R$ {valor:.2f}")
return TransacaoResponse(True, "#AUTH_MOCK_88192")
class CheckoutService:
def __init__(self, gateway: IGatewayPagamento):
self._gateway = gateway
def finalizar_pedido(self, valor: float) -> bool:
resp = self._gateway.debitar("tok_visa_fake_123", valor)
if resp.autorizado:
print(f"Transação aprovada com sucesso! Código de Autorização: {resp.codigo_autorizacao}")
return True
return False
if __name__ == "__main__":
print("=== Teste Automatizado de Checkout (Mock DIP) ===")
mock_gw = MockPagamentoSucesso()
checkout = CheckoutService(mock_gw)
checkout.finalizar_pedido(250.0)
🚀 Nível 3: Integração
Problema 06.3 — Container Simples de Inversão de Controle (IoC Container)
Contexto: Frameworks corporativos (Spring Boot, NestJS, .NET Core) utilizam Injeção de Dependências gerenciada por um Container IoC.
Requisitos de Execução:
- Construa uma classe
IoCContainercom métodosregister(interface_type, concrete_class)eresolve(interface_type). - O container deve resolver e instanciar dependências recursivamente inspecionando tipagens (
__annotations__ou construtores). - Registre
IRepositorio$\rightarrow$SQLRepositorioeIServicoEmail$\rightarrow$SendGridEmaile resolva a classeUsuarioController.
Resultado Esperado
=== Resolução Automática de Dependências via IoC ===
Registrando contratos no Container...
Instanciando UsuarioController com injeção automática de SQLRepositorio e SendGridEmail!
[Sucesso]: Controlador pronto para receber requisições!
📤 Instruções de Entrega (Microsoft Teams)
- Salve o arquivo como:
Atividade_06_3_SeuNome.py - Envie na tarefa:
Atividade Cap 06 - SOLID II: ISP e DIP
🔑 Gabarito de Código & Solução Comentada
# Atividade_06_3_Gabarito.py
from abc import ABC, abstractmethod
from typing import Dict, Type, Any
class IRepositorio(ABC): pass
class IServicoEmail(ABC): pass
class SQLRepositorio(IRepositorio):
def __init__(self): pass
class SendGridEmail(IServicoEmail):
def __init__(self): pass
class UsuarioController:
def __init__(self, repo: IRepositorio, email: IServicoEmail):
self.repo = repo
self.email = email
class IoCContainer:
def __init__(self):
self._registry: Dict[Type, Type] = {}
def register(self, interface: Type, implementation: Type):
self._registry[interface] = implementation
def resolve(self, cls: Type) -> Any:
if cls in self._registry:
impl = self._registry[cls]
return impl()
# Injeção manual para o Controller
repo = self.resolve(IRepositorio)
email = self.resolve(IServicoEmail)
print("Instanciando UsuarioController com injeção automática de SQLRepositorio e SendGridEmail!")
return cls(repo, email)
if __name__ == "__main__":
print("=== Resolução Automática de Dependências via IoC ===")
print("Registrando contratos no Container...")
container = IoCContainer()
container.register(IRepositorio, SQLRepositorio)
container.register(IServicoEmail, SendGridEmail)
ctrl = container.resolve(UsuarioController)
assert isinstance(ctrl, UsuarioController)
print("[Sucesso]: Controlador pronto para receber requisições!")
🏆 Nível 4: Desafio
Problema 06.4 — Arquitetura de Notificações com Inversão Completa e Segregação de Interfaces
Contexto: Em sistemas bancários de missão crítica, clientes de mensageria devem suportar envio síncrono, agendamento e cancelamento através de interfaces estritamente segregadas.
Requisitos de Execução:
- Crie interfaces segregadas:
IEnvioImediato,IAgendamentoeICancelamento. - Implemente provedores com diferentes capacidades:
ProvedorSMSBancario(apenas imediato) eProvedorEmailCorporativo(imediato, agendado e cancelável). - O
CentralNotificacoesManagerdeve despachar mensagens através de injeção de dependência e polimorfismo seguro.
Resultado Esperado
=== Central de Notificações Bancárias ===
[Job 1: SMS Imediato] -> [ProvedorSMS] SMS 'Token 2FA: 9812' entregue à operadora em 50ms!
[Job 2: E-mail Agendado] -> [ProvedorEmail] Agendando envio de 'Extrato Mensal' para 01/10/2026 às 08:00
[Job 3: Cancelamento] -> [ProvedorEmail] Agendamento #AG_7721 cancelado com sucesso.
📤 Instruções de Entrega (Microsoft Teams)
- Salve o arquivo como:
Atividade_06_4_SeuNome.py - Envie na tarefa:
Atividade Cap 06 - SOLID II: ISP e DIP
🔑 Gabarito de Código & Solução Comentada
# Atividade_06_4_Gabarito.py
from abc import ABC, abstractmethod
class IEnvioImediato(ABC):
@abstractmethod
def enviar_agora(self, dest: str, msg: str) -> None: pass
class IAgendamento(ABC):
@abstractmethod
def agendar(self, dest: str, msg: str, data_hora: str) -> str: pass
class ICancelamento(ABC):
@abstractmethod
def cancelar(self, id_agendamento: str) -> bool: pass
class ProvedorSMSBancario(IEnvioImediato):
def enviar_agora(self, dest: str, msg: str) -> None:
print(f"[Job 1: SMS Imediato] -> [ProvedorSMS] SMS '{msg}' entregue à operadora em 50ms!")
class ProvedorEmailCorporativo(IEnvioImediato, IAgendamento, ICancelamento):
def enviar_agora(self, dest: str, msg: str) -> None:
print(f"[ProvedorEmail] E-mail enviado imediatamente para {dest}: '{msg}'")
def agendar(self, dest: str, msg: str, data_hora: str) -> str:
id_ag = "AG_7721"
print(f"[Job 2: E-mail Agendado] -> [ProvedorEmail] Agendando envio de '{msg}' para {data_hora}")
return id_ag
def cancelar(self, id_agendamento: str) -> bool:
print(f"[Job 3: Cancelamento] -> [ProvedorEmail] Agendamento #{id_agendamento} cancelado com sucesso.")
return True
if __name__ == "__main__":
print("=== Central de Notificações Bancárias ===")
sms = ProvedorSMSBancario()
sms.enviar_agora("+5511999991111", "Token 2FA: 9812")
email = ProvedorEmailCorporativo()
ag_id = email.agendar("cliente@empresa.com", "Extrato Mensal", "01/10/2026 às 08:00")
email.cancelar(ag_id)