🏛️ ATIVIDADE 13: ARQUITETURA DE SOFTWARE E PADRÕES

📖 Fundamentação Teórica

Para realizar este laboratório com sucesso, certifique-se de ter compreendido os conceitos apresentados no:
👉 CAPÍTULO 13: HERANÇA E POLIMORFISMO

Bem-vindo a mais uma etapa do seu desenvolvimento técnico! Agora que você domina a modelagem de processos e dados, daremos o passo mais importante para quem quer se tornar um desenvolvedor sênior ou gestor técnico: projetar a arquitetura interna do software. Hoje, aprenderemos a organizar sistemas profissionais em camadas usando o padrão MVC (Model-View-Controller) corporativo com Java 17, Spring Boot 3.5.x, Thymeleaf e HTMX, além de aplicar o padrão de projeto criacional Factory. 🛡️🧩


🎯 Objetivos de Aprendizagem do Laboratório

Ao final deste laboratório prático (estimativa: 4 horas presenciais / autoguiadas), você será capaz de:

  • Diferenciar monólitos, camadas MVC e arquiteturas desacopladas modernas.
  • Projetar o fluxo de dados entre Controller, Service e Repository do Spring Boot.
  • Compreender o uso do Thymeleaf + HTMX para gerar interfaces reativas sem o peso de frameworks complexos de SPA.
  • Aplicar o padrão de projeto Factory para criação desacoplada de objetos de negócio.

🏢 O Cenário Prático (Seu Desafio)

Na TecProExpress, a equipe de desenvolvimento estava sofrendo: toda vez que precisavam mudar o banco de dados de MySQL para PostgreSQL, tinham que reescrever a validação de rotas, o cálculo do frete e as telas do aplicativo! Tudo estava tão bagunçado e misturado (acoplado) que um erro de digitação no botão da tela derrubava o cálculo do financeiro!

"Seu desafio como Arquiteto de Software é reorganizar a plataforma. Você desenhará a estrutura do sistema em camadas estritas e isoladas no Spring Boot. Além disso, os motoristas exigem notificações de novas rotas via SMS, e-mail ou push móvel. Você implementará o padrão Factory para que o sistema escolha o tipo correto de envio de notificação sem acoplar a lógica de entrega."


🧠 Fundamentos: A Teoria Traduzida

Para que um sistema sobreviva a anos de manutenção, ele deve ser desacoplado (cada peça cuida de apenas um assunto).

A Estrutura em Camadas (Spring Boot)

  1. View / Interface (Thymeleaf + HTMX): Renderiza o HTML dinâmico no servidor com Thymeleaf e realiza requisições parciais assíncronas com HTMX, mantendo o carregamento rápido e leve.
  2. Controller (Camada de Apresentação): Recebe os cliques (requisições HTTP), extrai dados do formulário e chama a lógica. Ele nunca calcula regras de negócio!
  3. Service (Camada de Negócio): Onde as regras morrem. É o "cérebro" do sistema (Ex: calcula desconto, valida se o motorista está ativo).
  4. Repository / DAO (Camada de Dados): Onde ocorrem as queries SQL (SELECT, INSERT), salvando e buscando os dados no banco de dados.

📊 Visualizando a Lógica MVC + Camadas

flowchart TD
    Browser["Navegador (HTML + HTMX)"] -->|1. Requisição HTTP| Controller["Controller (Spring MVC)"]
    Controller -->|2. Valida & Encaminha| Service["Service (Regras de Negócio)"]
    Service -->|3. Consulta Dados| Repository["Repository (Acesso ao Banco)"]
    Repository -->|4. Retorna Entidades| Service
    Service -->|5. Retorna Resultados| Controller
    Controller -->|6. Renderiza Thymeleaf| Browser

    style Browser fill:#eceff1,stroke:#607d8b,stroke-width:2px
    style Controller fill:#fffde7,stroke:#fbc02d,stroke-width:2px
    style Service fill:#e1f5fe,stroke:#0288d1,stroke-width:2px
    style Repository fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px

Arquitetura em Camadas MVC (Spring Boot)


📖 Exemplo Guiado: O Padrão Factory (Notificações)

Quando uma nova rota é atribuída, precisamos despachar um alerta ao entregador. Mas não queremos acoplar as classes SmsNotification, EmailNotification e PushNotification no código principal. Usaremos a NotificationFactory.

// 1. Interface comum de Notificação
public interface Notification {
    void send(String message, String target);
}

// 2. Implementações específicas
public class SmsNotification implements Notification {
    public void send(String message, String target) {
        System.out.println("Disparando SMS para " + target + ": " + message);
    }
}

public class EmailNotification implements Notification {
    public void send(String message, String target) {
        System.out.println("Enviando E-mail para " + target + ": " + message);
    }
}

// 3. A Fábrica (Factory) que desacopla a criação
public class NotificationFactory {
    public static Notification createNotification(String type) {
        if (type == null) return null;
        if (type.equalsIgnoreCase("SMS")) return new SmsNotification();
        if (type.equalsIgnoreCase("EMAIL")) return new EmailNotification();
        throw new IllegalArgumentException("Tipo de notificação desconhecido: " + type);
    }
}

🛠️ Código do Service utilizando a Factory no Spring Boot:

@Service
public class DeliveryService {
    
    @Autowired
    private DeliveryRepository repository;

    public void processarEntrega(Long deliveryId, String notificationType) {
        // Busca a entrega no banco
        Delivery delivery = repository.findById(deliveryId)
            .orElseThrow(() -> new RuntimeException("Entrega não encontrada"));

        // Lógica de Negócio: Atualiza status
        delivery.setStatus("EM_ROTA");
        repository.save(delivery);

        // Uso do Padrão Factory para enviar notificação sem acoplamento
        Notification notification = NotificationFactory.createNotification(notificationType);
        notification.send("Sua entrega está em rota!", delivery.getMotoristaContato());
    }
}

🔍 Detalhamento do Processo:

  • Se amanhã o diretor da TecProExpress exigir o envio de notificações por WhatsApp, basta criar a classe WhatsAppNotification e adicioná-la dentro da NotificationFactory. O arquivo DeliveryService continuará intacto, provando que nosso sistema atende ao Princípio do Aberto/Fechado (OCP) do SOLID! 🚀

🛠️ Prática Obrigatória 1: Desenho Arquitetural

Cenário: O projeto semestral da sua equipe.

  1. Desenhe um diagrama flowchart no Mermaid representando a arquitetura em camadas do seu projeto de grupo.
  2. Mapeie e rotule as caixas indicando onde ficará a sua Interface (Thymeleaf/HTMX), seus Controllers, seus Services (Regras de Negócio) e seus Repositories.
  3. Garanta que a camada de interface fale exclusivamente com o Controller, e o Controller fale exclusivamente com o Service.

🏁 Resultado Esperado (Para sua Referência)

Um diagrama de arquitetura de camadas profissional documentado em formato Mermaid no corpo do seu arquivo Markdown de entrega.



💻 Arquitetura em Camadas & Factory Pattern em Python

Para vivenciar o desacoplamento arquitetural (Controller $\rightarrow$ Service $\rightarrow$ Factory $\rightarrow$ Repository):

# arquitetura_factory.py
from abc import ABC, abstractmethod

# 1. Interface de Notificação (Contrato)
class Notificador(ABC):
    @abstractmethod
    def enviar(self, destinatario: str, mensagem: str) -> None:
        pass

# 2. Implementações Concretas
class NotificadorSMS(Notificador):
    def enviar(self, destinatario: str, mensagem: str) -> None:
        print(f"   📲 [SMS] Enviado para {destinatario}: '{mensagem}'")

class NotificadorEmail(Notificador):
    def enviar(self, destinatario: str, mensagem: str) -> None:
        print(f"   📧 [E-MAIL] Enviado para {destinatario}: '{mensagem}'")

# 3. Factory Criacional (OCP - Open/Closed Principle)
class NotificadorFactory:
    @staticmethod
    def obter_notificador(canal: str) -> Notificador:
        canais = {
            "SMS": NotificadorSMS,
            "EMAIL": NotificadorEmail
        }
        classe = canais.get(canal.upper())
        if not classe:
            raise ValueError(f"Canal de notificação '{canal}' não suportado.")
        return classe()

# 4. Camada de Serviço (Service Layer)
class EntregaService:
    def despachar_pacote(self, cod_pacote: str, canal_notificacao: str, contato: str) -> None:
        print(f"⚙️ [SERVICE] Processando despacho do pacote {cod_pacote}...")
        notificador = NotificadorFactory.obter_notificador(canal_notificacao)
        notificador.enviar(contato, f"Seu pacote {cod_pacote} saiu para entrega!")

if __name__ == "__main__":
    print("=" * 65)
    print("🏛️ ARQUITETURA EM CAMADAS & FACTORY PATTERN - TECPROEXPRESS")
    print("=" * 65)

    service = EntregaService()
    service.despachar_pacote("BR-9901", "SMS", "11988887777")
    service.despachar_pacote("BR-9902", "EMAIL", "cliente@empresa.com")
    print("=" * 65)

🖥️ Saída Esperada no Terminal:

=================================================================
🏛️ ARQUITETURA EM CAMADAS & FACTORY PATTERN - TECPROEXPRESS
=================================================================
⚙️ [SERVICE] Processando despacho do pacote BR-9901...
   📲 [SMS] Enviado para 11988887777: 'Seu pacote BR-9901 saiu para entrega!'
⚙️ [SERVICE] Processando despacho do pacote BR-9902...
   📧 [E-MAIL] Enviado para cliente@empresa.com: 'Seu pacote BR-9902 saiu para entrega!'
=================================================================

🌐 Requisição cURL para Notificação Desacoplada (Swagger /docs)

curl -X POST "http://127.0.0.1:5000/api/v1/entregas/notificar" \
     -H "Content-Type: application/json" \
     -d '{
       "cod_pacote": "BR-9901",
       "canal": "SMS",
       "contato": "11988887777"
     }'

🔹 Resposta JSON:

{
  "status": "ENVIADO",
  "canal_utilizado": "SMS",
  "timestamp": "2026-03-10T14:32:00Z"
}

📤 Instruções de Entrega (Microsoft Teams)

Após validar suas especificações arquiteturais:

  1. Salve o arquivo de código e diagramas com o nome Atividade_13.md na pasta es-atv-13-arquitetura/ do seu repositório GitHub.
  2. Certifique-se de fazer o commit e push para o repositório público.
  3. Submeta o link do seu repositório no Microsoft Teams para avaliação do professor.

💡 Checkpoint de Lógica

Importante

Reflexão Profissional: Por que na arquitetura profissional de desenvolvimento em camadas do Spring Boot, a classe de Controller nunca deve conter queries SQL ou lógicas pesadas de IF/ELSE de negócios? (Resposta: Para manter o desacoplamento e a testabilidade do sistema. O Controller deve apenas gerenciar a comunicação com o protocolo HTTP; se regras de negócio forem colocadas ali, o código ficará amarrado ao ambiente Web, impedindo que essa mesma lógica de negócio seja reutilizada em APIs móveis, agendadores automáticos ou testes unitários JUnit). 🧠🛡️

---

📊 Rubrica Formativa de Avaliação

Critério de Avaliação Insuficiente (0% - 40%) Regular (41% - 70%) Excelente (71% - 100%)
Arquitetura em Camadas (Mermaid Flowchart) Diagrama confuso ou misturando responsabilidades de Controller e Repository. Mapeia as camadas mas sem rotular o fluxo estrito (UI ➔ Controller ➔ Service ➔ Repository). Diagrama Mermaid de arquitetura em camadas perfeitamente desacoplado e rotulado.
Design Pattern Factory (Desacoplamento) Modela criacionalmente sem usar interfaces ou abstração. Cria a Factory mas mantendo alto acoplamento na classe chamadora. Modelagem impecável do padrão Factory respeitando o Princípio Aberto/Fechado (OCP) do SOLID.
Entrega no GitHub Entrega fora da pasta `es-atv-13-arquitetura/`. Arquivo entregue mas sem renderização do diagrama Mermaid. Submete `Atividade_13.md` com código limpo e Mermaid renderizado com sucesso.