Files
SD/main/docs/SERIALIZATION_SPECIFICATION.md
2025-10-23 20:08:26 +01:00

10 KiB

Especificação do Formato de Serialização

1. Visão Geral

Este documento descreve as estratégias de serialização para a comunicação entre processos no sistema de simulação de tráfego distribuído. A serialização é necessária para transmitir objetos Java através de sockets entre diferentes processos (cruzamentos, coordenador, dashboard).

2. Requisitos

2.1 Objetos a Serializar

Os principais objetos que precisam ser serializados são:

  • Vehicle: Contém estado completo do veículo (id, tipo, rota, métricas)
  • Message: Container para todas as mensagens entre processos
  • Estatísticas: Dados agregados dos cruzamentos e semáforos

2.2 Requisitos Funcionais

  • Integridade: Todos os dados devem ser preservados durante a serialização/desserialização
  • Compatibilidade: Suporte para evolução de classes (adicionar campos)
  • Performance: Latência mínima para não impactar a simulação
  • Depuração: Capacidade de inspecionar mensagens facilmente

2.3 Requisitos Não-Funcionais

  • Tamanho da mensagem otimizado
  • Fácil manutenção e extensibilidade
  • Compatibilidade com ferramentas de monitorização

3. Comparação: Java Serialization vs JSON

3.1 Java Serialization

Vantagens

  1. Nativo do Java

    • Sem dependências externas
    • Suporte built-in na JVM
    • Integração direta com Serializable
  2. Preservação de Tipos

    • Mantém tipos Java exatos
    • Serializa grafo completo de objetos
    • Suporte automático para herança
  3. Performance de Escrita

    • Serialização binária mais rápida
    • Menos overhead de conversão
    • ObjectOutputStream otimizado
  4. Facilidade de Implementação

    • Basta implementar Serializable
    • Controle fino com serialVersionUID
    • Métodos customizados: writeObject/readObject

Desvantagens

  1. Acoplamento Java

    • Apenas entre aplicações Java
    • Dificulta interoperabilidade futura
    • Formato proprietário
  2. Tamanho das Mensagens

    • Formato binário verboso
    • Inclui metadata de classes
    • 2-3x maior que JSON compacto
  3. Depuração Difícil

    • Formato binário não legível
    • Necessita ferramentas especiais
    • Difícil inspecionar mensagens
  4. Problemas de Segurança

    • Vulnerabilidades conhecidas (CVEs)
    • Desserialização insegura
    • Necessita validação cuidadosa
  5. Evolução de Classes

    • serialVersionUID requer gestão manual
    • Quebra compatibilidade facilmente
    • Difícil manter versões diferentes

Métricas Estimadas

Tamanho Médio: 400-600 bytes (Vehicle completo)
Latência: 0.5-1ms (serialização + rede local)
Throughput: ~10,000 msgs/s

3.2 JSON (com Gson/Jackson)

Vantagens

  1. Legibilidade Humana

    • Formato texto simples
    • Fácil depuração
    • Inspecionável com ferramentas comuns
  2. Interoperabilidade

    • Padrão universal
    • Facilita integração futura
    • Dashboard web, APIs, etc.
  3. Tamanho Otimizado

    • Formato compacto
    • ~40% menor que Java Serialization
    • Compressão opcional (gzip)
  4. Evolução Flexível

    • Campos opcionais nativos
    • Backward/forward compatibility
    • Versionamento natural
  5. Ferramentas e Ecossistema

    • Bibliotecas maduras (Gson, Jackson)
    • Validação com JSON Schema
    • Suporte a logs estruturados
  6. Segurança

    • Sem execução de código
    • Validação mais simples
    • Menos vetores de ataque

Desvantagens

  1. Dependência Externa

    • Necessita biblioteca (Gson/Jackson)
    • Aumenta tamanho do JAR
    • Possível quebra de dependência
  2. Performance de Conversão

    • Parsing de texto
    • Reflexão Java
    • ~20-30% mais lento que binário
  3. Tipos Perdidos

    • Necessita type hints
    • Problemas com genéricos
    • Enums requerem atenção
  4. Memória

    • String temporárias
    • Maior uso de heap
    • GC mais frequente

Métricas Estimadas

Tamanho Médio: 250-350 bytes (Vehicle completo)
Latência: 0.8-1.5ms (conversão + rede local)
Throughput: ~8,000 msgs/s

4. Decisão e Recomendação

4.1 Análise de Contexto

Características do Projeto:

  • Sistema distribuído Java-only (curto prazo)
  • Comunicação intra-rede local (baixa latência)
  • Volume moderado de mensagens (~100-1000/s)
  • Necessidade de depuração durante desenvolvimento
  • Potencial expansão futura (dashboard web)

4.2 Recomendação: JSON (Gson)

Justificativa

  1. Desenvolvimento e Depuração 🔍

    • A fase atual do projeto requer debugging extensivo
    • JSON facilita inspeção de mensagens
    • Logs legíveis sem ferramentas especiais
  2. Manutenibilidade 🔧

    • Mais fácil para equipe aprender/modificar
    • Evolução de protocolo mais simples
    • Menos problemas de compatibilidade
  3. Extensibilidade 🚀

    • Dashboard web futuramente
    • APIs REST potenciais
    • Integração com ferramentas de monitorização
  4. Performance Aceitável

    • Diferença de latência irrelevante (< 1ms)
    • Volume de mensagens não é crítico
    • Rede local minimiza overhead
  5. Segurança 🔒

    • Evita vulnerabilidades de Java Serialization
    • Validação mais simples e segura

4.3 Quando Usar Java Serialization

Java Serialization seria preferível se:

  • Performance crítica (> 100k msgs/s)
  • Objetos muito complexos com referências circulares
  • Garantia de ambiente Java puro permanente
  • Necessidade de preservar estado exato (locks, transient)

5. Implementação Recomendada

5.1 Arquitetura de Serialização

┌─────────────────────────────────────────┐
│         Application Layer               │
│  (Vehicle, Message, Statistics)         │
└─────────────────┬───────────────────────┘
                  │
┌─────────────────▼───────────────────────┐
│      Serialization Interface            │
│  - serialize(Object): byte[]            │
│  - deserialize(byte[], Class<T>): T     │
└─────────────────┬───────────────────────┘
                  │
        ┌─────────┴─────────┐
        │                   │
┌───────▼──────┐   ┌────────▼─────────┐
│ JsonSerializer│   │JavaSerializer    │
│  (Gson-based) │   │(ObjectStream)    │
└───────────────┘   └──────────────────┘

5.2 Estrutura de Mensagens JSON

Exemplo 1: Transferência de Veículo

{
  "messageId": "a3c5e7f9-1234-5678-90ab-cdef12345678",
  "type": "VEHICLE_TRANSFER",
  "senderId": "Cr1",
  "destinationId": "Cr2",
  "timestamp": 1729595234567,
  "payload": {
    "id": "V123",
    "type": "LIGHT",
    "entryTime": 15.7,
    "route": ["Cr1", "Cr2", "Cr5", "S"],
    "currentRouteIndex": 1,
    "totalWaitingTime": 3.2,
    "totalCrossingTime": 1.8
  }
}

Exemplo 2: Atualização de Estatísticas

{
  "messageId": "b4d6e8f0-2345-6789-01bc-def123456789",
  "type": "STATS_UPDATE",
  "senderId": "Cr3",
  "destinationId": "Dashboard",
  "timestamp": 1729595234789,
  "payload": {
    "intersectionId": "Cr3",
    "queueLengths": {
      "North": 5,
      "South": 3,
      "East": 7,
      "West": 2
    },
    "vehiclesProcessed": 142,
    "averageWaitTime": 4.5
  }
}

5.3 Biblioteca Escolhida: Gson

Por que Gson (não Jackson)?

  • Mais simples e leve
  • Menos configuração necessária
  • API mais intuitiva para iniciantes
  • Melhor para modelos simples (nosso caso)
  • ⚠️ Jackson seria melhor para: streaming, performance extrema, binding complexo

6. Plano de Implementação

Fase 1: Setup

  • Adicionar dependência Gson ao pom.xml
  • Criar interface MessageSerializer
  • Implementar JsonMessageSerializer
  • Implementar JavaMessageSerializer (fallback)

Fase 2: Adapters

  • Criar adaptadores Gson para classes do modelo
  • Configurar serialização customizada se necessário
  • Implementar testes unitários

Fase 3: Integração

  • Integrar serializer nos sockets
  • Adicionar logs de mensagens
  • Implementar mecanismo de versionamento

Fase 4: Otimização (Opcional)

  • Implementar compressão (gzip)
  • Pool de serializers
  • Métricas de performance

7. Estrutura de Arquivos

src/main/java/sd/
├── serialization/
│   ├── MessageSerializer.java          # Interface comum
│   ├── JsonMessageSerializer.java      # Implementação Gson
│   ├── JavaMessageSerializer.java      # Implementação nativa
│   ├── SerializerFactory.java          # Factory pattern
│   └── adapters/                       # Type adapters Gson
│       ├── VehicleAdapter.java
│       └── MessageAdapter.java
└── network/
    ├── MessageSocket.java              # Wrapper para socket
    └── MessageProtocol.java            # Protocolo de comunicação

8. Considerações Finais

8.1 Boas Práticas

  1. Versionamento: Incluir campo version nas mensagens
  2. Validação: Validar mensagens após desserialização
  3. Logging: Logar mensagens em desenvolvimento (desabilitar em produção)
  4. Exceções: Tratar erros de serialização gracefully
  5. Testes: Testar serialização round-trip para todas as classes

8.2 Monitorização

  • Tamanho médio de mensagens
  • Latência de serialização/desserialização
  • Taxa de erros de serialização
  • Throughput de mensagens

8.3 Documentação

Cada tipo de mensagem deve ser documentado com:

  • Propósito
  • Estrutura JSON
  • Exemplo
  • Sender/Receiver esperado
  • Comportamento em caso de erro

9. Referências


Documento criado em: 22 de outubro de 2025
Versão: 1.0
Autor: Equipa SD - Trabalho Prático