Modelo conceptual em UML
Classes, multiplicidades, associações, generalizações e regras do domínio.
Uma encomenda de Ana contém dois teclados e um rato. A data pertence à encomenda; o nome pertence ao produto; a quantidade depende dos dois. O modelo conceptual distingue estes factos e define as ligações permitidas antes de escolher tabelas. Em BD usamos o subconjunto de UML destinado à modelação de dados, sem métodos de programação.
Classes e atributos
Uma classe descreve objetos com propriedades e significado comuns. Cliente tem id, nome e email. Ana é uma instância dessa classe.
O atributo pertence à definição da classe. O seu valor pertence a cada objeto. Essa distinção decide onde colocar cada facto.
Escolhe uma classe quando precisas de identificar objetos e guardar as suas propriedades ou ligações. Se a cidade de uma morada for apenas texto para mostrar, pode ser um atributo. Nada mais depende dela nesse desenho.
Se o sistema guarda população, país e ligações da cidade a outras entidades, Cidade deve ser uma classe. Passa a ter identidade própria e relações.
Uma chave identifica cada objeto. O nome de uma pessoa não é uma boa chave se nomes iguais forem permitidos.
Um identificador artificial pode ser útil. Não elimina outras unicidades do domínio. Se cada cliente tem um número fiscal distinto, esse número continua a precisar de uma restrição própria. Aqui sublinhamos os atributos da chave escolhida.
Não escrevas idCliente em Encomenda só para simular uma ligação conceptual. Liga as classes por uma associação. A chave estrangeira aparece depois, no modelo relacional.
Associações e multiplicidades
Uma associação liga objetos. Uma ligação concreta entre Ana e a encomenda 100 é uma instância da associação faz.
A multiplicidade junto de uma extremidade conta objetos dessa classe associados a um objeto da outra. Lê cada direção separadamente:
1significa exatamente um, o mesmo que1..1.0..1permite ausência, mas proíbe dois.*abrevia0..*, sem limite superior.1..*exige pelo menos um.2..5exige entre dois e cinco, incluindo os limites.
Na ligação Cliente 1 ── 0..* Encomenda, lê cada direção em separado.
O 1 junto de Cliente diz que cada encomenda tem exatamente um cliente. O 0..* junto de Encomenda diz que um cliente pode não ter encomendas ou ter muitas.
Não contamos clientes a partir da multiplicidade junto de Encomenda. A multiplicidade conta sempre os objetos da classe onde está escrita.
O mínimo e o máximo têm funções diferentes. Mudar 0..* para 1..* não muda o facto de ser uma associação muitos para um. Muda a obrigação de participar.
Por isso Mia, que ainda não comprou, satisfaz 0..* e viola 1..*. O máximo autoriza várias encomendas; o mínimo decide se zero é permitido.
Modelo da loja
Assumimos três regras para a loja. Uma encomenda registada tem pelo menos um produto. O mesmo produto aparece no máximo uma vez em cada encomenda. Todas as encomendas pertencem a um cliente.
A quantidade e o preço acordado dizem respeito à compra daquele produto naquela encomenda. Não pertencem só ao produto nem só à encomenda.
A encomenda 100 pode conter Teclado e Rato. Um Produto pode ainda não ter sido vendido.
As multiplicidades junto de Produto e Encomenda são, respetivamente, 1..* e 0..*. O preço atual pertence a Produto. O preço da compra pertence a Item. Mesmo quando os dois números coincidem, são factos diferentes.
Se admitirmos encomendas em preparação sem produtos, precisamos de alterar o mínimo para 0..*, ou de distinguir o estado de preparação do estado confirmado. Uma implementação não pode escolher silenciosamente uma regra diferente do desenho.
Classes de associação e acontecimentos repetidos
Uma classe de associação guarda propriedades da ligação, como qtd em Item. Nenhum produto tem uma quantidade comprada única para todas as encomendas. Nenhuma encomenda tem uma quantidade única para todos os produtos. O valor depende do par.
Uma associação UML liga um dado par de objetos uma vez. Se um aluno se pode candidatar à mesma faculdade em vários anos, uma classe de associação apenas entre Aluno e Faculdade não chega. O atributo ano não distingue várias ligações ao mesmo par.
Modela Candidatura como uma classe própria, ligada ao aluno e à faculdade. A chave distingue os acontecimentos. Pode ser um id ou, se as regras o permitirem, o conjunto aluno, faculdade e ano.
A mesma dúvida surge na loja. Se o mesmo produto puder surgir em linhas distintas da mesma encomenda, por exemplo com descontos diferentes, precisamos de uma classe Linha com um número de linha. O modelo apresentado consolida cada produto numa só linha e usa o par como identificador.
Papéis, associações reflexivas e qualificadores
Uma classe pode associar-se a si própria. Em Pessoa, uma associação parental liga uma pessoa no papel de progenitor a outra no papel de filho. Os papéis evitam confundir as duas referências na tradução para tabelas. Uma regra de “não ser o próprio progenitor” não resulta apenas das multiplicidades; precisa de uma restrição adicional.
Um qualificador identifica uma ligação dentro do contexto de um objeto. Um clube atribui números aos seus membros. O número 7 pode existir em dois clubes diferentes, mas dentro de um clube identifica no máximo uma pessoa. O identificador relevante é (clube, numeroMembro), não numeroMembro globalmente.
A multiplicidade de uma associação qualificada tem de ser lida com esse contexto. “Para este clube e este número, há no máximo uma pessoa” é diferente de “o clube tem no máximo uma pessoa”.
Associações com três participantes
Fornecimento(Fornecedor, Produto, Projeto) afirma que um fornecedor fornece um produto a um projeto. O facto completo envolve os três objetos ao mesmo tempo.
Substituir esta associação por três ligações binárias pode inventar combinações. Considera apenas estes fornecimentos:
| Fornecedor | Produto | Projeto |
|---|---|---|
| F1 | P1 | J2 |
| F1 | P2 | J1 |
| F2 | P1 | J1 |
Os pares guardados incluem F1/P1, F1/J1 e P1/J1, mas vêm de três fornecimentos diferentes. Ao juntar as três relações de pares, esses valores encaixam e produzem também F1/P1/J1. Esse fornecimento nunca foi registado. Os pares não dizem quais os três objetos que participaram juntos; conserva a associação ternária.
Numa associação ternária, a multiplicidade junto de um participante limita quantos valores desse participante existem para uma combinação fixa dos outros dois. Se junto de Fornecedor estiver 1, cada par Produto/Projeto determina um fornecedor. Não significa que cada fornecedor esteja ligado a um único produto ou projeto.
Generalizações
Uma generalização representa “é um”: um Funcionário é uma Pessoa. A subclasse herda os atributos e as associações da superclasse e acrescenta propriedades específicas.
Há duas decisões independentes:
| Propriedade | Pergunta |
|---|---|
| Completa | Todo o objeto da superclasse pertence a pelo menos uma subclasse? |
| Parcial | Existem objetos só na superclasse? |
| Disjunta | Um objeto pertence no máximo a uma subclasse? |
| Sobreposta | Um objeto pode pertencer a várias subclasses? |
Pessoa → Aluno, Docente pode ser parcial e sobreposta: nem toda a pessoa é aluno ou docente, e uma pessoa pode ser ambos. Pagamento → Cartao, Transferencia, sob uma regra que exige exatamente uma forma de pagamento, é completa e disjunta. Não inferimos uma destas propriedades a partir da outra.
Composição, agregação e restrições
A composição representa uma parte com um único composto de cada vez e com ciclo de vida dependente do composto. Uma linha de encomenda pertence a uma encomenda; se removemos a encomenda definitivamente, as suas linhas deixam de existir. O losango preenchido fica junto do todo.
A agregação usa um losango vazio para uma relação todo/parte mais fraca. A parte pode sobreviver à remoção do todo. Não acrescentes automaticamente uma política de eliminação em cascata só porque há um losango.
As multiplicidades não exprimem todas as regras. Se o capitão de uma equipa tem de ser um dos seus jogadores, duas associações “tem jogadores” e “tem capitão” não asseguram essa inclusão. Acrescenta a restrição capitao pertence aos jogadores da equipa.
Um elemento derivado, marcado com /, calcula-se a partir de outros. /total da encomenda é a soma de qtd × precoUnitario. Decidir guardá-lo exige uma regra que o mantenha atualizado. A barra mostra a dependência, não implementa o cálculo.
Resolver um enunciado
Sublinha os objetos que precisam de identidade e os acontecimentos que podem repetir-se. Para cada ligação, escreve duas frases com “cada” e “pode” ou “tem de”. Essas frases dão os limites mínimo e máximo. Só depois coloca atributos e regras que as multiplicidades não representam.
Valida com contraexemplos. Uma encomenda com dois clientes deve ser proibida; um cliente sem encomendas deve ser permitido. Se não conseguires justificar um limite a partir do enunciado, não o inventes. Explicita a hipótese de modelação.
Exercícios
O mesmo par em vários acontecimentos
Um leitor pode pedir o mesmo exemplar emprestado várias vezes em datas diferentes. Uma classe de associação entre Leitor e Exemplar, com dataInicio e dataFim, chega? Propõe um modelo que guarde todos os empréstimos.
Pista
Mais uma pista
Distingue o exemplar físico de cada acontecimento de empréstimo.
Solução
Não chega. A classe de associação apenas distingue o par leitor/exemplar e não várias ocorrências desse par. Cria Emprestimo(id, dataInicio, dataFim) com duas associações: cada empréstimo tem exatamente um Leitor e um Exemplar; cada leitor e exemplar pode ter zero ou mais empréstimos. O id identifica o acontecimento. Impedir dois empréstimos ativos do mesmo exemplar é uma restrição adicional, não uma multiplicidade que proíba todo o histórico.
Confere a tua resposta:
- Modelei Emprestimo como acontecimento próprio.
- Indiquei multiplicidades nas duas direções.
- Separei histórico da regra de empréstimo ativo.
Erros frequentes
Colocar máximo 1 do lado dos empréstimos de um exemplar impediria também empréstimos sucessivos. Não assumes que uma data identifica um empréstimo sem uma regra que o garanta.
Três pares não provam um fornecimento
Existem apenas os fornecimentos F1/P1/J2, F1/P2/J1 e F2/P1/J1. Guardamos separadamente os pares fornecedor/produto, fornecedor/projeto e produto/projeto. Que fornecimento adicional aparece ao juntar os três conjuntos? Explica como evitar essa informação falsa.
Pista
Procura três pares compatíveis que venham de linhas diferentes.
Solução
Aparece F1/P1/J1. F1/P1 veio do primeiro fornecimento, F1/J1 do segundo e P1/J1 do terceiro. A junção combina esses pares, embora não tenham participado juntos. Conserva Fornecimento(fornecedor, produto, projeto) como relação ternária. Uma chave artificial não recupera a combinação se guardarmos apenas os três conjuntos de pares.
Confere a tua resposta:
- Encontrei o fornecimento espúrio F1/P1/J1.
- Identifiquei a origem de cada par e conservei o facto ternário.
Erros frequentes
Não confundas existência de cada par com existência do triplo. Uma amostra sem tuplos espúrios também não prova que a separação funciona sempre.
Classes, ligações e histórico de preços
Uma loja guarda clientes identificados por id e nome e produtos identificados por id e nome, com um preço atual. Cada encomenda tem id, data, exatamente um cliente e pelo menos um produto. Um produto só aparece uma vez em cada encomenda; para esse par guardamos quantidade e preço acordado.
Desenha o modelo UML. Decide se permite um cliente sem encomendas, uma encomenda sem produtos e duas compras do mesmo produto pelo mesmo cliente em dias diferentes. Uma mudança do preço atual deve alterar compras antigas?
Pista
Mais uma pista
Solução
Classes: Cliente(id,nome), Produto(id,nome,precoAtual) e Encomenda(id,data), com id como chave em cada classe. Cada encomenda tem um cliente: 1 junto de Cliente. Cada cliente tem zero ou mais encomendas: 0..* junto de Encomenda.
Na associação Encomenda/Produto, 1..* junto de Produto obriga cada encomenda a ter produtos; 0..* junto de Encomenda permite produtos ainda não vendidos. A classe de associação Item(qtd,precoUnitario) guarda os valores do par.
Um cliente sem encomendas é válido; uma encomenda vazia não é. O mesmo cliente pode comprar o mesmo produto nas encomendas 100 e 101: são ligações diferentes. Alterar o preço atual não modifica o acordado nessas ligações.
Confere a tua resposta:
- Coloquei data na Encomenda e preço atual no Produto.
- Justifiquei as multiplicidades nas duas direções.
- Modelei quantidade e preço acordado no par encomenda/produto.
- Distingui uma encomenda vazia de um cliente sem encomendas.
Erros frequentes