🔀 CAPÍTULO 14: DIAGRAMA DE SEQUÊNCIA E APIS REST
🎯 1. Objetivos de Aprendizagem & Competências
Estimativa de Dedicação: 2 horas de estudo autoguiado.
Ao final deste capítulo, você será capaz de:
- 🔹 Compreender a representação temporal de troca de mensagens entre objetos no Diagrama de Sequência da UML 2.5.
- 🔹 Dominar a sintaxe visual de Linhas de Vida (Lifelines), Barras de Ativação (Execution Occurrences), Mensagens Síncronas (
->>), Assíncronas (-)) e Retornos (-->>). - 🔹 Modelar fluxos completos de requisições HTTP REST (Request-Response Cycle) conectando Cliente, Gateway, Serviços e Banco de Dados.
- 🔹 Implementar rotas Flask integradas com serviços de domínio espelhando rigorosamente a ordem do diagrama de sequência.
🏢 2. Cenário Corporativo & Estudo de Caso (TecProExpress)
Na TecProExpress, a equipe de engenharia identificou uma latência excessiva durante o processo de Checkout e Emissão de Etiqueta. O time de frontend culpava o banco de dados, o DBA culpava a rede e a equipe backend culpava a API externa de CEP.
O Desafio: Como Arquiteto de Software, você deve desenhar o Diagrama de Sequência da UML para rastrear a linha do tempo exata das chamadas de rede e processamento síncrono/assíncrono, identificando gargalos e estabelecendo contratos REST claros e determinísticos em Flask.
🧠 3. Fundamentação Teórica & Modelos Visuais
3.1. Anatomia do Diagrama de Sequência da UML
O tempo flui verticalmente de cima para baixo. Cada participante possui uma linha de vida vertical com barras que indicam períodos em que o objeto está executando operações ativas:
sequenceDiagram
autonumber
actor C as 📱 App do Motorista
participant API as 🌐 Flask (Gateway)
participant SVC as 🧠 FreteService
participant DB as 🛢️ PostgreSQL
C->>+API: POST /api/fretes/calcular (distancia_km, peso_kg, expresso)
API->>+SVC: processar_calculo(distancia, peso, expresso)
SVC->>+DB: SELECT taxa_km FROM tabelas_frete...
DB-->>-SVC: taxa_km = 2.50
SVC-->>-API: { valor_total: 316.25, prazo_horas: 24 }
API-->>-C: 200 OK { valor_total: 316.25, prazo_horas: 24 }
3.2. Notação de Mensagens na UML 2.5
| Notação Mermaid | Tipo de Mensagem UML | Significado de Engenharia |
|---|---|---|
->> (Seta sólida preenchida) | Mensagem Síncrona | O chamador bloqueia a execução aguardando o retorno da resposta. |
-) (Seta fina aberta) | Mensagem Assíncrona | O chamador envia o evento e prossegue sem esperar (ex: disparo de fila RabbitMQ/Kafka). |
-->> (Seta pontilhada) | Mensagem de Retorno | Retorno de dados ou confirmação de conclusão da operação. |
par / and / end | Fragmento Paralelo | Execução concorrente de múltiplos fluxos simultâneos. |
alt / else / end | Fragmento Condicional | Estrutura de desvio if / else na sequência. |
💻 4. Aplicação Prática & Código Executável (Python 3.11+)
📋 Pré-requisitos e Instalação
Instale o micro-framework Flask no seu ambiente virtual:
pip install flask
💻 Código Completo e Autocontido (sequence_api_frete.py)
Implementação do fluxo síncrono de cálculo de frete com Flask 3.x, refletindo a interação modelada no Diagrama de Sequência:
"""
Módulo: sequence_api_frete.py
Domínio: Endpoint REST Flask refletindo a sequência síncrona de cálculo de frete.
"""
from decimal import Decimal
import sys
from flask import Flask, request, jsonify
app = Flask(__name__)
# 1. Camada de Serviço (Service Layer)
class FreteService:
@staticmethod
def processar_calculo(distancia_km: Decimal, peso_kg: Decimal, expresso: bool = False) -> dict:
taxa_base_km = Decimal("2.50")
valor = (distancia_km * taxa_base_km) + (peso_kg * Decimal("3.00"))
prazo = 24
if expresso:
valor *= Decimal("1.25")
prazo = 8
return {
"valor_total": float(valor.quantize(Decimal("0.01"))),
"prazo_horas": prazo,
"status": "CALCULADO_COM_SUCESSO"
}
# 2. Rota REST (Controller / Gateway)
@app.post("/api/fretes/calcular")
def endpoint_calcular_frete():
"""Reflete o Passo 1 do Diagrama de Sequência: POST /api/fretes/calcular."""
dados = request.get_json()
if not dados:
return jsonify({"erro": "Payload JSON ausente ou inválido"}), 400
try:
distancia = Decimal(str(dados.get("distancia_km", 0)))
peso = Decimal(str(dados.get("peso_kg", 0)))
expresso = bool(dados.get("expresso", False))
if distancia <= Decimal("0.00") or peso <= Decimal("0.00"):
return jsonify({"erro": "distancia_km e peso_kg devem ser maiores que zero"}), 400
resultado = FreteService.processar_calculo(distancia, peso, expresso)
return jsonify(resultado), 200
except Exception as ex:
return jsonify({"erro": f"Falha no processamento: {str(ex)}"}), 400
if __name__ == "__main__":
if "--server" in sys.argv:
print("🚀 Iniciando servidor Flask em http://127.0.0.1:5000...")
app.run(port=5000, debug=True)
else:
print("--- Simulação de Requisições HTTP com Flask test_client() ---")
with app.test_client() as client:
# Cenário 1: Frete Padrão (120.5 km, 5 kg) -> (120.5*2.50) + (5*3.00) = 301.25 + 15 = 316.25
res1 = client.post("/api/fretes/calcular", json={
"distancia_km": 120.5,
"peso_kg": 5.0,
"expresso": False
})
print(f"Cenário 1 (Frete Padrão) [Status {res1.status_code}]: {res1.get_json()}")
# Cenário 2: Frete Expresso (120.5 km, 5 kg, expresso) -> 316.25 * 1.25 = 395.31
res2 = client.post("/api/fretes/calcular", json={
"distancia_km": 120.5,
"peso_kg": 5.0,
"expresso": True
})
print(f"Cenário 2 (Frete Expresso) [Status {res2.status_code}]: {res2.get_json()}")
# Cenário 3: Validação de Payload com Erro
res3 = client.post("/api/fretes/calcular", json={
"distancia_km": -10.0,
"peso_kg": 5.0
})
print(f"Cenário 3 (Validação Defensiva) [Status {res3.status_code}]: {res3.get_json()}")
🚀 Como Executar
Execute o script de teste automatizado diretamente no terminal:
python sequence_api_frete.py
Para iniciar o servidor HTTP e testar com ferramentas como Postman, cURL ou VS Code REST Client:
python sequence_api_frete.py --server
🖥️ Saída Esperada no Terminal
--- Simulação de Requisições HTTP com Flask test_client() ---
Cenário 1 (Frete Padrão) [Status 200]: {'prazo_horas': 24, 'status': 'CALCULADO_COM_SUCESSO', 'valor_total': 316.25}
Cenário 2 (Frete Expresso) [Status 200]: {'prazo_horas': 8, 'status': 'CALCULADO_COM_SUCESSO', 'valor_total': 395.31}
Cenário 3 (Validação Defensiva) [Status 400]: {'erro': 'distancia_km e peso_kg devem ser maiores que zero'}
💡 5. Checkpoint de Engenharia & Boas Práticas
- Contratos REST Claros e Validados: Toda API REST deve validar rigorosamente os payloads de entrada e retornar códigos HTTP semânticos (200 para sucesso, 400 para erro de validação do cliente, 500 para falha interna), com payloads JSON estruturados e previsíveis.
- Anti-Pattern Excesso de Chamadas Síncronas (Chatty API): Evite criar sequências onde a API faz múltiplas consultas síncronas sequenciais desnecessárias. Agrupe chamadas ou adote processamento assíncrono para operações de longa duração.
🔗 6. Conexão com os Projetos Integradores
| Projeto Integrador | Como o conceito deste capítulo é aplicado no PI |
|---|---|
| PI-05: ParkFlow | Diagrama de Sequência do checkout do estacionamento (leitura de ticket ➔ tarifação ➔ baixa). |
| PI-10: ImobiFlow | Sequência de geração de fatura de aluguel e cálculo do repasse financeiro líquido ao proprietário. |
🧪 7. Quiz de Fixação e Autoavaliação (Formative Assessment)
🧪 Quiz de Autoavaliação — Capítulo 14
🧪 Quiz de Autoavaliação — Capítulo 14
1. No Diagrama de Sequência da UML, o que representa a 'Linha de Vida' (Lifeline) de um objeto?
- A) O número de bytes que o objeto ocupa na memória RAM.
- B) Uma linha vertical pontilhada que representa a existência e a passagem do tempo daquele participante durante a interação.
- C) O cabo de rede que conecta os servidores.
- D) A chave estrangeira que conecta duas tabelas no banco de dados.
💡 Ver Resposta e Justificativa
Resposta Correta: B
Justificativa: A linha de vida estende-se verticalmente para baixo a partir do retângulo do participante, representando a passagem cronológica do tempo na interação.
2. Qual é a diferença fundamental entre uma 'Mensagem Síncrona' e uma 'Mensagem Assíncrona' no diagrama de sequência?
- A) A síncrona usa JavaScript e a assíncrona usa Python.
- B) Na síncrona, o remetente pausa e aguarda a conclusão da resposta antes de continuar; na assíncrona, o remetente envia a mensagem e continua seu processamento imediatamente sem bloquear.
- C) A mensagem assíncrona não pode conter parâmetros.
- D) Não há diferença; a UML 2.5 unificou as duas mensagens.
💡 Ver Resposta e Justificativa
Resposta Correta: B
Justificativa: Mensagens síncronas bloqueiam o fluxo do chamador até a resposta (ex: chamada de função comum), enquanto mensagens assíncronas disparam eventos em segundo plano (ex: postagem em fila).
3. O que define o fragmento de interação combinado 'alt' (Alternative) no diagrama de sequência?
- A) Um loop que repete a operação infinitamente.
-
B) Uma bifurcação condicional com guardas booleanas (equivalente a uma estrutura
if / else). - C) Uma falha irrecuperável do sistema operacional.
- D) A exclusão física de um registro no banco de dados.
💡 Ver Resposta e Justificativa
Resposta Correta: B
Justificativa: O operador 'alt' modela caminhos mutuamente exclusivos baseados em condições de guarda (ex: [Saldo Suficiente] vs [Saldo Insuficiente]).
🛠️ 8. Ponte para a Ação: Laboratório Prático
Coloque esta teoria em prática executando o roteiro de laboratório autoguiado:
👉 ATIVIDADE 08: DIAGRAMA DE SEQUÊNCIA (UML)
📌 9. Resumo Executivo & Key Takeaways
- Visão Temporal: O Diagrama de Sequência é o modelo comportamental mais utilizado para mapear a ordem cronológica de APIs REST e microsserviços.
- Linhas de Vida & Barras de Ativação: Indicam os participantes e os momentos exatos de processamento ativo.
- Mensagens Síncronas vs Assíncronas: Diferenciam chamadas diretas de eventos desacoplados em filas e mensageria.
- Endpoints em Flask: Implementam de forma limpa e síncrona as transições modeladas no diagrama de sequência, facilitando testes com
test_client().