🏛️ ATIVIDADE 13: ARQUITETURA DE SOFTWARE E PADRÕES
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)
- 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.
- 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!
- Service (Camada de Negócio): Onde as regras morrem. É o "cérebro" do sistema (Ex: calcula desconto, valida se o motorista está ativo).
- 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
📖 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
WhatsAppNotificatione adicioná-la dentro daNotificationFactory. O arquivoDeliveryServicecontinuará 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.
- Desenhe um diagrama
flowchartno Mermaid representando a arquitetura em camadas do seu projeto de grupo. - Mapeie e rotule as caixas indicando onde ficará a sua Interface (Thymeleaf/HTMX), seus Controllers, seus Services (Regras de Negócio) e seus Repositories.
- 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:
- Salve o arquivo de código e diagramas com o nome
Atividade_13.mdna pastaes-atv-13-arquitetura/do seu repositório GitHub. - Certifique-se de fazer o commit e push para o repositório público.
- Submeta o link do seu repositório no Microsoft Teams para avaliação do professor.
💡 Checkpoint de Lógica
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. |