🔄 CAPÍTULO 15: DIAGRAMAS DINÂMICOS (ESTADOS E ATIVIDADES)


🎯 1. Objetivos de Aprendizagem & Competências

Estimativa de Dedicação: 2 horas de estudo autoguiado.
Ao final deste capítulo, você será capaz de:

  • 🔹 Modelar o ciclo de vida completo de entidades reativas utilizando o Diagrama de Máquina de Estados da UML (David Harel).
  • 🔹 Dominar a sintaxe formal de transições: Evento [Condição de Guarda] / Ação Executada.
  • 🔹 Construir Diagramas de Atividades com particionamento em Raias (Swimlanes), bifurcações de decisão e nós de sincronização paralela (Fork e Join).
  • 🔹 Implementar o padrão comportamental State Pattern e máquinas de estados finitos (FSM) em Python 3.11+.

🏢 2. Cenário Corporativo & Estudo de Caso (TecProExpress)

Na TecProExpress, os motoristas estavam conseguindo alterar o status de um pacote diretamente de "Aguardando Coleta" para "Entregue ao Destinatário", pulando a etapa obrigatória de "Em Rota de Entrega" e sem coletar a assinatura digital do cliente.

O Desafio: Como Engenheiro de Software, você deve modelar formalmente a Máquina de Estados Finita do pacote e o Diagrama de Atividades com Raias do processo de entrega, garantindo que o backend bloqueie qualquer transição de status ilegal ou desordenada.


🧠 3. Fundamentação Teórica & Modelos Visuais

3.1. Diagrama de Máquina de Estados da UML

Mapeia os estados discretos pelos quais um objeto passa durante sua existência em resposta a eventos:

stateDiagram-v2
    [*] --> CRIADO : Criação do Pacote
    CRIADO --> COLETADO : Motorista Coleta no Hub
    COLETADO --> EM_TRANSITO : Saída para Entrega [Veículo Alocado]
    EM_TRANSITO --> TENTATIVA_FALHA : Cliente Ausente / Notificar SAC
    TENTATIVA_FALHA --> EM_TRANSITO : Nova Tentativa [Tentativas < 3]
    TENTATIVA_FALHA --> DEVOLVIDO_HUB : Excedeu Limite [Tentativas >= 3]
    EM_TRANSITO --> ENTREGUE : Assinatura Coletada / Enviar Recibo
    ENTREGUE --> [*]
    DEVOLVIDO_HUB --> [*]

3.2. Diagrama de Atividades com Raias (Swimlanes) e Fork / Join

Organiza o fluxo de trabalho distribuindo as responsabilidades entre os diferentes departamentos/atores:

flowchart TD
    subgraph CLIENTE ["👤 Cliente"]
        A1["Fazer Pedido"] --> A2["Efetuar Pagamento"]
    end
    
    subgraph GATEWAY ["🏛️ Gateway Pagamento"]
        A2 --> B1{"Pagamento Aprovado?"}
    end
    
    subgraph LOGISTICA ["🚚 Centro Logístico"]
        B1 -- Sim --> FORK["Barra Fork (Paralelo)"]
        FORK --> C1["Separar Estoque"]
        FORK --> C2["Emitir Nota Fiscal"]
        C1 --> JOIN["Barra Join (Sincronização)"]
        C2 --> JOIN
        JOIN --> C3["Despachar Encomenda"]
    end
    
    B1 -- Não --> A3["Notificar Erro Pagamento"]
    
    style FORK fill:#fef3c7,stroke:#d97706
    style JOIN fill:#fef3c7,stroke:#d97706
    style C3 fill:#dcfce7,stroke:#16a34a

💻 4. Aplicação Prática & Código Executável (Python 3.11+)

📋 Pré-requisitos e Instalação

Este exemplo utiliza os módulos padrão enum do Python, sem necessidade de pacotes externos:

python --version  # Requer Python 3.11 ou superior

💻 Código Completo e Autocontido (maquina_estados_pacote.py)

Implementação de uma Máquina de Estados Finitos (FSM) com validação estrita de transições de ciclo de vida:

"""
Módulo: maquina_estados_pacote.py
Domínio: Validação de transições de ciclo de vida de encomendas com FSM.
"""
from enum import Enum, auto

class EstadoPacote(Enum):
    CRIADO = auto()
    COLETADO = auto()
    EM_TRANSITO = auto()
    ENTREGUE = auto()
    CANCELADO = auto()

class PacoteFSM:
    # Tabela de transições permitidas: EstadoAtual -> Lista de Próximos Estados Legais
    TRANSIÇÕES_VALIDAS = {
        EstadoPacote.CRIADO: {EstadoPacote.COLETADO, EstadoPacote.CANCELADO},
        EstadoPacote.COLETADO: {EstadoPacote.EM_TRANSITO, EstadoPacote.CANCELADO},
        EstadoPacote.EM_TRANSITO: {EstadoPacote.ENTREGUE, EstadoPacote.COLETADO},
        EstadoPacote.ENTREGUE: set(), # Estado Final
        EstadoPacote.CANCELADO: set()  # Estado Final
    }

    def __init__(self, codigo_rastreio: str):
        self.codigo_rastreio = codigo_rastreio
        self.estado_atual = EstadoPacote.CRIADO

    def transicionar_para(self, novo_estado: EstadoPacote):
        permitidos = self.TRANSIÇÕES_VALIDAS.get(self.estado_atual, set())
        if novo_estado not in permitidos:
            raise ValueError(
                f"❌ Transição Ilegal: Não é permitido mudar de {self.estado_atual.name} para {novo_estado.name}."
            )
        self.estado_atual = novo_estado
        print(f"📦 Pacote [{self.codigo_rastreio}] transicionou com sucesso para: {self.estado_atual.name}")

if __name__ == "__main__":
    print("--- Simulação da Máquina de Estados (FSM) de Logística ---")
    pacote = PacoteFSM("BR-2026-99")
    pacote.transicionar_para(EstadoPacote.COLETADO)
    pacote.transicionar_para(EstadoPacote.EM_TRANSITO)
    pacote.transicionar_para(EstadoPacote.ENTREGUE)
    
    # Tentativa ilegal de transição a partir de um estado final
    try:
        pacote.transicionar_para(EstadoPacote.CRIADO)
    except ValueError as err:
        print(err)

🚀 Como Executar

Execute o script diretamente no terminal:

python maquina_estados_pacote.py

🖥️ Saída Esperada no Terminal

--- Simulação da Máquina de Estados (FSM) de Logística ---
📦 Pacote [BR-2026-99] transicionou com sucesso para: COLETADO
📦 Pacote [BR-2026-99] transicionou com sucesso para: EM_TRANSITO
📦 Pacote [BR-2026-99] transicionou com sucesso para: ENTREGUE
❌ Transição Ilegal: Não é permitido mudar de ENTREGUE para CRIADO.

💡 5. Checkpoint de Engenharia & Boas Práticas

Boas Práticas & Anti-Patterns

  • Condições de Guarda Robustas: Em transições de estado, use guardas booleanas inequívocas (ex: [Saldo >= Valor]) para impedir que objetos entrem em estados inválidos em produção.
  • Anti-Pattern Deadlocks em Fork/Join: No Diagrama de Atividades, todo fluxo aberto por um nó de Fork (bifurcação paralela) deve convergir para um nó de Join (sincronização) compatível para evitar travamentos de processos concorrentes.

🔗 6. Conexão com os Projetos Integradores

Projeto IntegradorComo o conceito deste capítulo é aplicado no PI
PI-06: ServiceFlowMáquina de Estados da Ordem de Serviço (ABERTAEM_ANALISEAPROVADACONCLUIDA).
PI-07: AgroSafeDiagrama de Atividades do fluxo de receituário agronômico (Emissão ART ➔ Separação ➔ Aplicação).

🧪 7. Quiz de Fixação e Autoavaliação (Formative Assessment)

🧪 Quiz de Autoavaliação — Capítulo 15

1. No Diagrama de Transição de Estados da UML, o que representa a sintaxe Evento [Guarda] / Ação?

  • A) O nome do banco de dados, a tabela e o registro excluído.
  • B) O gatilho que dispara a transição (Evento), a condição booleana que deve ser verdadeira para permitir a passagem ([Guarda]) e a operação executada durante a mudança (/ Ação).
  • C) O caminho da URL da API REST.
  • D) Um comentário de código descartável.
💡 Ver Resposta e Justificativa

Resposta Correta: B
Justificativa: Essa é a notação formal da UML: a transição só ocorre se o Evento acontecer E a Condição de Guarda for satisfeita, disparando a Ação associada.


2. No Diagrama de Atividades da UML, qual é a função das 'Barras de Sincronização' (Fork e Join)?

  • A) Desenhar botões de login na tela.
  • B) O nó 'Fork' divide um fluxo sequencial em múltiplos fluxos executados em paralelo; o nó 'Join' sincroniza e aguarda a conclusão de todos os fluxos paralelos antes de prosseguir.
  • C) Excluir arquivos temporários do servidor.
  • D) Cancelar a execução do programa em caso de erro.
💡 Ver Resposta e Justificativa

Resposta Correta: B
Justificativa: Fork e Join modelam concorrência e paralelismo: Fork bifurca o fluxo em threads simultâneas e Join aguarda todas terminarem para unificar o fluxo.


3. O que são as 'Raias' (Swimlanes) em um Diagrama de Atividades?

  • A) Linhas de código escritas em HTML.
  • B) Divisões visuais (colunas ou faixas horizontais) que particionam as atividades indicando qual ator, departamento ou sistema é responsável por executá-las.
  • C) Tipos primitivos de variáveis float.
  • D) Erros de compilação da IDE.
💡 Ver Resposta e Justificativa

Resposta Correta: B
Justificativa: As raias organizam o fluxo de trabalho atribuindo cada atividade ao seu responsável direto (ex: Cliente, Financeiro, Logística), facilitando a auditoria de processos.


🛠️ 8. Ponte para a Ação: Laboratório Prático

🎯 Próximo Passo Prático

Coloque esta teoria em prática executando o roteiro de laboratório autoguiado:
👉 ATIVIDADE 11: DIAGRAMA DE ATIVIDADES (UML)


📌 9. Resumo Executivo & Key Takeaways

  • Diagrama de Estados: Foca nas mudanças de situação interna de uma única entidade ao longo do tempo.
  • Sintaxe de Transição: Evento [Guarda Booleana] / Ação Executada.
  • Diagrama de Atividades: Modela o fluxo de trabalho global, decisões lógicas e sincronização paralela (Fork/Join).
  • Raias (Swimlanes): Atribuem responsabilidades claras para cada etapa do processo corporativo.