Modelo conceptual em UML

Classes, associações, multiplicidades e restrições a partir dos requisitos, com o diagrama da Loja de Bilhetes.

TLDR

Perguntar sobre esta página

ChatGPTClaudePerplexityGrokGeminiCopiar e abrirDeepSeekCopiar e abrir

O bilhete B1 pertence à Ana e refere a sessão S12 da Noite de Fado. Para guardar esta compra precisamos de distinguir quatro tipos de objetos: Utilizador, Evento, Sessão e Bilhete. O modelo conceptual descreve os seus atributos, associações e restrições em UML, sem escolher ainda tabelas ou tipos PostgreSQL.

Classes e atributos

Uma classe é um tipo de coisa que o sistema regista, com atributos que guardam os seus dados. Na Loja de Bilhetes precisamos de quatro:

  • Utilizador: nome, email (único) e credencial de autenticação. O hash é a representação usada na implementação.
  • Evento: título, descrição e categoria.
  • Sessão: data e hora, preço não negativo e lotação positiva. Cada sessão pertence a um evento.
  • Bilhete: código e estado (reservado, pago ou cancelado). Cada bilhete liga um utilizador a uma sessão.

Escolhemos atributos que suportam as interações e as regras do domínio. O email é único porque o registo com email duplicado é uma exceção tratada nos requisitos. O estado do bilhete existe porque a compra tem confirmação e pode ser cancelada. Se não consegues justificar um atributo, revê o seu propósito antes de o incluir.

Associações e multiplicidades

Uma associação liga duas classes, e a multiplicidade diz quantos objetos de um lado se ligam a cada objeto do outro. Lê-se nos dois sentidos.

  • Um Evento tem uma ou mais Sessões (1 a 1..*). Uma sessão pertence a exatamente um evento. Sem esta associação, a pesquisa de eventos por data não teria onde ir buscar as datas.
  • Um Utilizador compra zero ou mais Bilhetes (0..*), e cada bilhete pertence a exatamente um utilizador.
  • Uma Sessão tem zero ou mais Bilhetes, e cada bilhete refere exatamente uma sessão.

As linhas são associações, e a multiplicidade junto a uma classe conta objetos dessa classe para um objeto do lado oposto; as setas de navegabilidade UML são outra informação, não o sentido de uma chave estrangeira. Por isso, dizer “uma sessão tem muitos bilhetes” não chega, pois também é preciso dizer que “cada bilhete é de uma só sessão”: as duas leituras juntas é que fecham a regra, e é dessa regra que nascem as chaves estrangeiras no esquema relacional.

Resolver o muitos para muitos

Um utilizador compra bilhetes para várias sessões e cada sessão recebe bilhetes de vários utilizadores: entre Utilizador e Sessão há uma relação de muitos para muitos. Uma associação UML pode ter uma classe de associação para guardar dados próprios. Neste domínio precisamos de algo diferente, porque o mesmo par utilizador-sessão pode ter vários bilhetes. O Bilhete é uma entidade associativa que a representa: guarda o código e o estado da compra e liga cada compra a exatamente um utilizador e uma sessão.

Uma ligação com atributos pode ser modelada como classe de associação ou como entidade associativa; decide também a identidade e se podem existir várias ocorrências para o mesmo par. Aqui, os bilhetes B1 e B2 pertencem à mesma pessoa U7 e à mesma sessão S12, mas são compras distintas, como mostra a figura de ocorrências abaixo.

Restrições que o desenho não mostra

O diagrama mostra estrutura, por isso algumas regras precisam de texto. Escreve-as como restrições junto ao modelo:

  • O email do utilizador é único em todo o sistema.
  • Não se vendem mais bilhetes do que a lotação da sessão.
  • Ao criar uma sessão, a sua data tem de estar no futuro; o histórico pode conter sessões passadas.
  • Um bilhete cancelado liberta o lugar para nova venda.

Estas frases são o contrato com as fases seguintes: a unicidade do email vira restrição na tabela, a lotação exige um protocolo de concorrência e a data mínima vira validação na aplicação. Um modelo sem restrições escritas empurra estas decisões para o código, onde cada programador do grupo inventa a sua versão.

Generalização e restrições dos subtipos

Se utilizador tem os subtipos comprador e administrador, distingue duas perguntas independentes:

  • Disjoint ou overlapping: uma pessoa pode pertencer a ambos?
  • Total ou partial: todos os utilizadores pertencem a pelo menos um subtipo?

Não deduzas uma resposta da outra: uma especialização total pode ser overlapping, e uma especialização disjoint pode ser partial. A tradução para tabelas tem de preservar a combinação escolhida ou declarar como a vai verificar; a Ana pertence aos dois subtipos quando a especialização é overlapping, o Bruno pertence só ao subtipo comprador em ambas as políticas, e um utilizador sem qualquer subtipo só é permitido em partial.

Uma composição representa uma relação todo-parte com pertença forte e restrições de ciclo de vida. Não marques composição apenas porque existe uma chave estrangeira. Um bilhete comprado pode ter de permanecer como registo histórico mesmo após desativar a conta. Nesse domínio, apagar automaticamente o registo pode contrariar o requisito.

Uma associação reflexiva, como utilizador segue utilizador, precisa de nomes de papéis: seguidor e seguido. Sem esses papéis, duas chaves para a mesma tabela ficam ambíguas. Se não se pode seguir a si próprio, essa restrição tem de ser escrita.

O que o modelo não garante sozinho

A multiplicidade 1..* de sessões por evento inclui um mínimo de uma sessão, mas uma chave estrangeira NOT NULL da sessão para o evento só garante que cada sessão tem evento; o mínimo na direção inversa precisa de operações coordenadas ou outras verificações. Um diagrama é uma especificação que não executa as regras, por isso confirma cada sentido de cada associação com exemplos válidos e inválidos antes de escolheres as restrições do esquema.

Escrever restrições em frases testáveis e em OCL

Escreve restrições em frases testáveis e, quando a regra é precisa, em OCL. Por exemplo, “um bilhete cancelado não ocupa lugar” traduz-se em context Bilhete inv: self.estado = 'cancelado' implies self.ocupaLugar = false, que se lê assim: para cada bilhete, se o estado é cancelado, então não ocupa lugar. Testa com dois casos: B1 pago ocupa um lugar; B2 cancelado liberta o lugar para nova venda.

Exercícios

Ler os dois sentidos

Cada sessão pertence a um evento e cada evento tem pelo menos uma sessão. Quais são as multiplicidades nas extremidades?

Pista

A etiqueta perto de Evento responde quantos eventos há para uma sessão.

Mais uma pista

O mínimo de sessões também faz parte da regra.

Solução

Evento 1; Sessão 1..*. A localização da etiqueta indica os objetos dessa classe ligados a um objeto da classe oposta.

Confere a tua resposta:

  • Indico 1 na extremidade Evento.
  • Indico 1..* na extremidade Sessão.
  • Leio cada multiplicidade a partir de um objeto do outro lado.

Erros frequentes

Não troques os lados nem apagues o mínimo 1.

Voltar à explicação
Modelar papéis que se sobrepõem

Cada utilizador registado é comprador ou administrador, podendo ter os dois papéis. Classifica a especialização quanto a totalidade e disjunção. Dá uma ocorrência que distingue “pelo menos um” de “exatamente um”. Como muda o modelo se também admitirmos utilizadores sem nenhum destes papéis?

Pista

Testa separadamente existência de subtipo e pertença a vários.

Solução

É total e overlapping. U7 comprador, U8 administrador e U9 em ambos são ocorrências válidas. U9 mostra que totalidade não significa exatamente um subtipo.

Ao admitir U10 sem nenhum dos papéis, a especialização passa a partial, conservando overlapping. Mudou a obrigação de pertencer a algum subtipo; a possibilidade de pertencer aos dois mantém-se.

Confere a tua resposta:

  • Escolho total e overlapping.
  • Apresento uma pessoa em ambos os subtipos.
  • Distingo a mudança de totalidade da de disjunção.
Voltar à explicação
Identidade da compra

Uma pessoa pode comprar três bilhetes para a mesma sessão. O par utilizador-sessão pode ser chave de Bilhete?

A tua resposta

Pista

Compara duas compras da mesma pessoa para a mesma sessão.

Mais uma pista

Um bilhete tem uma identidade própria.

Solução

O par não é único. Pode haver um id de bilhete e código único; o par mantém-se como duas referências.

  • Não, sob essa regra.. As três compras teriam o mesmo par.
  • Sim, toda a ligação N:N usa esse par como chave.. Este domínio admite ocorrências múltiplas por par.
  • Só se a sessão tiver lotação 3.. A lotação não altera a unicidade do par.

Erros frequentes

Não transfiras automaticamente a chave de uma associação simples para uma entidade com identidade própria.

Voltar à explicação

À tua maneira

Aparência

Modo de cor
Tema
Cor de destaque

Leitura

Fonte de leitura

Álgebra, lógica e uma ideia de cada vez.

Código

Fonte do código

Navegação

Cursor de leitura, sem edição. h, j, k, l movem; / pesquisa nesta página. v seleciona caracteres; V seleciona linhas; y copia. Tab permite destacar ou comentar. Espaço ou Enter abre blocos recolhíveis. Nos cartões, h, j, k, l mudam o foco.

CSS personalizado

Ativa uma sugestão ou guarda o teu CSS. Só muda este navegador.

Usa --page, --text e --accent para acompanhar o tema.

Seletores e recuperação

.site-header, .prose, .course-card, [data-reading-history], [data-playground] e .page-actions.

Abre a aparência com a tecla vírgula ou no rodapé. Se o CSS esconder os controlos, abre esta página sem CSS personalizado.

Pesquisar

Escreve para pesquisar em todo o site.

para escolher · Enter para abrir · Esc para fechar

Copiar fórmula

A cópia automática não está disponível. Copia o LaTeX abaixo.

Pesquisar nesta página

Enter procura · n / N repetem · Esc cancela. Ctrl / Cmd K pesquisa todo o site.

Atalhos de teclado

Clica numa tecla para a mudar. Esc cancela. Backspace desativa.

PesquisarCtrl / Cmd K

Os atalhos não interferem enquanto escreves. Tab e Enter funcionam sempre.