Pular para conteúdo

Projeto 07: Refatoração Orientada aos Princípios SOLID 🧱

Escopo do Projeto

Objetivo: Refatorar um código legado monolítico repleto de violações arquiteturais aplicando os cinco princípios SOLID (Single Responsibility, Open-Closed, Liskov Substitution, Interface Segregation e Dependency Inversion).


🎯 1. Contexto & Desafio Prático

Você recebeu uma 'God Class' de faturamento de 500 linhas que conecta no banco, calcula impostos em cascata de ifs, envia e-mails e imprime relatórios. Sua missão é refatorar o sistema aplicando rigorosamente os cinco princípios SOLID.


📋 2. Requisitos Técnicos Obrigatórios

  • R1 (Single Responsibility Principle - SRP): Separar a classe monolítica em classes coesas: repositório de dados, motor de cálculo fiscal e serviço de notificação.
  • R2 (Open/Closed Principle - OCP): Implementar interface de cálculo tributário permitindo adicionar novos impostos sem modificar classes existentes.
  • R3 (Liskov Substitution Principle - LSP): Garantir que todas as subclasses de pagamento possam substituir a classe base sem quebrar o comportamento.
  • R4 (Dependency Inversion Principle - DIP): Injetar dependências via construtor utilizando interfaces e abstrações em vez de instanciar classes concretas internamente.

📐 3. Diagrama Conceitual & Arquitetura

graph TD
    GodClass["Monólito Violando SOLID (God Class)"] --> Refactor["Refatoração com SOLID"]
    Refactor --> SRP["SRP: InvoiceRepository, TaxCalculator, Notifier"]
    Refactor --> OCP["OCP: Interface TaxStrategy (Novos impostos sem mudar código)"]
    Refactor --> DIP["DIP: Injeção de Dependências por Interfaces"]
    style GodClass fill:#ffebee,stroke:#c62828
    style Refactor fill:#fff3e0,stroke:#e65100
    style SRP fill:#e1f5fe,stroke:#01579b
    style OCP fill:#e8f5e9,stroke:#2e7d32
    style DIP fill:#f3e5f5,stroke:#7b1fa2

💻 4. Especificação Técnica & Código de Referência

// solid_refactoring.py
from abc import ABC, abstractmethod

# OCP & DIP: Contrato abstrato para impostos
class TaxStrategy(ABC):
    @abstractmethod
    def calculate(self, amount: float) -> float:
        pass

class ICMS(TaxStrategy):
    def calculate(self, amount: float) -> float:
        return amount * 0.18

# DIP: Serviço depende de abstração de notificação
class NotificationService(ABC):
    @abstractmethod
    def send(self, recipient: str, message: str) -> None:
        pass

class OrderProcessor:
    def __init__(self, tax_strategy: TaxStrategy, notifier: NotificationService):
        self.tax_strategy = tax_strategy
        self.notifier = notifier

    def process(self, amount: float, customer_email: str) -> float:
        tax = self.tax_strategy.calculate(amount)
        total = amount + tax
        self.notifier.send(customer_email, f"Total do Pedido: {total}")
        return total

📦 5. Critérios de Avaliação e Entrega

  1. Código refatorado com 100% de desacoplamento comprovado.
  2. Demonstração da adição de um novo imposto (ex: ISS) sem alterar OrderProcessor.
  3. Suíte de testes unitários com mocks comprovando o isolamento das dependências.