🔄 ATIVIDADE 12: DIAGRAMA DE MÁQUINA DE ESTADOS (UML)

📖 Fundamentação Teórica

Para realizar este laboratório com sucesso, certifique-se de ter compreendido os conceitos apresentados no:
👉 CAPÍTULO 12: DIAGRAMA DE CLASSES (CONCEITOS)

Bem-vindo a mais uma etapa prática do seu treinamento em Engenharia de Software. Na atividade anterior, você aprendeu sobre processos e fluxos lógicos. Hoje, nosso foco muda para o ciclo de vida de uma entidade do sistema. Você aprenderá como modelar os Estados pelos quais um dado transiciona, garantindo que o software nunca entre em inconsistência lógica. 🛡️🧩


🎯 Objetivos de Aprendizagem do Laboratório

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

  • Identificar entidades de negócio com ciclos de vida complexos.
  • Modelar os Estados estáveis de um objeto no sistema.
  • Mapear Eventos Gatilho (Triggers) que provocam a transição entre estados.
  • Aplicar Condições de Guarda (Guards) para proteção lógica contra transições inválidas.

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

Na TecProExpress, tivemos um incidente grave de banco de dados: um cliente de suporte ligou reclamando que a sua entrega apareceu no sistema como "Entregue com Sucesso", mas o motorista ainda nem havia saído com o caminhão do centro de distribuição!

Ao analisar o código, a equipe técnica descobriu que não havia validação de regras de negócios. Um motorista distraído clicou no botão "Confirmar Entrega" na tela errada de um pacote que ainda estava no estado de triagem físico!

"Seu desafio como Arquiteto de Software é desenhar o Diagrama de Máquina de Estados para a entidade Entrega. Você deve blindar o sistema, definindo as regras exatas de como um pacote muda de estado (ex: de Pendente para Em Rota) e quais validações (guardas) impedem que um pacote seja marcado como Entregue antes de ser despachado."


🧠 Fundamentos: A Teoria Traduzida

Enquanto o Diagrama de Atividades mostra o fluxo das ações de um processo, o Diagrama de Máquina de Estados foca em um único objeto do início ao fim da sua existência.

Elementos Chave:

  1. Estado Inicial (Círculo Preto): O ponto de criação do objeto.
  2. Estado (Retângulo Arredondado): Uma condição estável na vida do objeto onde ele aguarda um evento (Ex: PENDENTE, EM_ROTA, ENTREGUE).
  3. Transição (Seta Direcionada): A mudança de um estado para o outro.
  4. Evento Gatilho (Trigger): A ação que dispara a transição (Ex: despacharPacote()).
  5. Condição de Guarda (Guard - entre colchetes [...]): Uma regra que precisa ser verdadeira para a transição acontecer. (Ex: [motorista_no_local == true]).

📊 Visualizando a Lógica

Dica

Condição Guarda: Pense na guarda como um segurança de boate. A transição quer acontecer, mas o segurança impede se a condição não for atendida!

```mermaid stateDiagram-v2 [*] --> PENDENTE : cadastrarPedido() PENDENTE --> EM_ROTA : despachar() [caminhao_carregado == true] EM_ROTA --> ENTREGUE : finalizar() [foto_comprovante_anexada == true] EM_ROTA --> TENTATIVA_FALHA : motoristaAusente() TENTATIVA_FALHA --> EM_ROTA : redirecionar() ENTREGUE --> [*] ```

Diagrama de Transição de Estados TecProExpress (UML)


📖 Exemplo Guiado

Abaixo, veja o mapeamento de transição para o ciclo de vida do pacote da TecProExpress.

Estado OrigemEvento GatilhoCondição GuardaEstado Destino
PENDENTEdespachar()[motorista_associado != null]EM_ROTA
EM_ROTAconfirmarEntrega()[distancia_gps_cliente < 100m]ENTREGUE
EM_ROTAcancelarPedido()[motivo != null]CANCELADO

🛠️ Regra UML em Sintaxe Padrão:

A sintaxe formal gravada na seta da transição segue o padrão: Evento [Guarda] / Ação executada

  • Exemplo: confirmarEntrega [comprovanteAnexado] / notificarCliente()
stateDiagram-v2
    state "Pendente de Coleta" as P
    state "Em Rota de Entrega" as ER
    state "Cancelado" as C
    state "Entregue" as E

    [*] --> P
    P --> ER : atribuirMotorista [motorista_ativo == true]
    ER --> E : confirmarEntrega [gps_ok == true] / enviarSMS()
    ER --> C : cancelar [cliente_solicitou] / estornarCartao()
    C --> [*]
    E --> [*]

🔍 Detalhamento do Processo:

  • Note a guarda [gps_ok == true]. Se o aplicativo do motorista não coletar a coordenada geográfica a menos de 100 metros da casa do cliente, o sistema bloqueia a mudança para o estado Entregue, evitando fraudes ou cliques acidentais!

🛠️ Prática Obrigatória 1: A Máquina de Estados

Cenário: O projeto semestral da sua equipe.

  1. Selecione a entidade mais crítica do seu sistema que possui vários status (Ex: Pedido em um e-commerce, Agendamento em uma clínica, Vaga em um estacionamento).
  2. Mapeie pelo menos 4 estados distintos para essa entidade.
  3. Defina claramente os Eventos Gatilho em cada seta de transição.
  4. Adicione pelo menos 2 Condições de Guarda entre colchetes [...] para blindar transições perigosas.

🏁 Resultado Esperado (Para sua Referência)

Uma imagem (PNG/JPG) do diagrama de máquina de estados UML modelado de forma organizada, exibindo a trajetória completa da entidade do estado inicial ao final.


💻 Máquina de Estados Finita (State Pattern) em Python

Para validar as transições de ciclo de vida com condições de guarda blindadas:

# maquina_estados.py
from enum import Enum

class StatusEntrega(Enum):
    PENDENTE = "PENDENTE"
    EM_ROTA = "EM_ROTA"
    ENTREGUE = "ENTREGUE"
    CANCELADO = "CANCELADO"

class PacoteFSM:
    def __init__(self, cod_rastreio: str) -> None:
        self.cod_rastreio = cod_rastreio
        self.estado_atual = StatusEntrega.PENDENTE

    def despachar(self, motorista_ativo: bool) -> None:
        if self.estado_atual != StatusEntrega.PENDENTE:
            raise ValueError(f"Não é possível despachar pacote no estado {self.estado_atual.value}")
        if not motorista_ativo: # Condição de Guarda [motorista_ativo == true]
            raise PermissionError("Guarda Violada: Nenhum motorista ativo atribuído.")
        
        self.estado_atual = StatusEntrega.EM_ROTA
        print(f"🚚 [{self.cod_rastreio}] Transição de Estado: PENDENTE -> EM_ROTA")

    def confirmar_entrega(self, distancia_metros: float) -> None:
        if self.estado_atual != StatusEntrega.EM_ROTA:
            raise ValueError("Apenas pacotes em rota podem ser confirmados como entregues.")
        if distancia_metros > 100.0: # Condição de Guarda [gps_ok == true]
            raise ValueError(f"Guarda Violada: Motorista está a {distancia_metros}m do local (máximo permitido: 100m).")
        
        self.estado_atual = StatusEntrega.ENTREGUE
        print(f"✅ [{self.cod_rastreio}] Transição de Estado: EM_ROTA -> ENTREGUE (GPS Validado a {distancia_metros}m)")

if __name__ == "__main__":
    print("=" * 65)
    print("🚦 MÁQUINA DE ESTADOS FINITA (FSM / STATE PATTERN) - TECPROEXPRESS")
    print("=" * 65)

    fsm = PacoteFSM("BR-4401")
    print(f"Estado Inicial: {fsm.estado_atual.value}")

    fsm.despachar(motorista_ativo=True)
    fsm.confirmar_entrega(distancia_metros=25.0)

    print(f"Estado Final Consolidado: {fsm.estado_atual.value}")
    print("=" * 65)

🖥️ Saída Esperada no Terminal:

=================================================================
🚦 MÁQUINA DE ESTADOS FINITA (FSM / STATE PATTERN) - TECPROEXPRESS
=================================================================
Estado Inicial: PENDENTE
🚚 [BR-4401] Transição de Estado: PENDENTE -> EM_ROTA
✅ [BR-4401] Transição de Estado: EM_ROTA -> ENTREGUE (GPS Validado a 25.0m)
Estado Final Consolidado: ENTREGUE
=================================================================

🌐 Exemplo de Payload JSON para Transição de Estado (Swagger /docs)

{
  "codigo_rastreio": "BR-4401",
  "transicao_solicitada": "CONFIRMAR_ENTREGA",
  "dados_guarda": {
    "latitude_atual": -23.55052,
    "longitude_atual": -46.63331,
    "distancia_calculada_metros": 25.0
  }
}

📤 Instruções de Entrega (Microsoft Teams)

Após validar suas documentações técnicas de estados:

  1. Salve o arquivo de tabela com o nome Atividade_12.md e a imagem do seu diagrama com o nome Atividade_12.png na pasta es-atv-12-estados/ 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: O que diferencia, na modelagem profissional, um Estado de uma Atividade? (Resposta: Um Estado representa uma situação de estabilidade temporária onde o objeto está aguardando passivamente um evento externo para mudar. Uma Atividade é uma ação ativa, de execução procedural contínua e computacional direta, que transiciona automaticamente para o próximo passo assim que termina). 🧠🛡️

---

📊 Rubrica Formativa de Avaliação

Critério de Avaliação Insuficiente (0% - 40%) Regular (41% - 70%) Excelente (71% - 100%)
Máquina de Estados & Condições de Guarda Menos de 4 estados ou transições sem eventos gatilho claros. Mapeia os 4 estados mas sem declarar as condições de guarda `[...]`. Diagrama de máquina de estados impecável com ao menos 4 estados, eventos gatilho e guardas `[...]` de proteção.
Tabela de Transições Lógicas Omite a tabela de transições lógicas. Preenche a tabela com colunas incompletas. Tabela detalhada de transições de estado cobrindo Estado Origem, Gatilho, Guarda e Estado Destino.
Entrega no GitHub Entrega fora da pasta `es-atv-12-estados/`. Entrega apenas o arquivo markdown sem a imagem `.png`. Submete `Atividade_12.md` e `Atividade_12.png` no repositório com validação de padrão.