Modelação com UML

Casos de uso, classes, multiplicidades, sequência, atividades e estados sem confundir domínio com implementação.

TLDR

Perguntar sobre esta página

ChatGPTClaudePerplexityGrokGeminiCopiar e abrirDeepSeekCopiar e abrir

A reserva R de Ana ocupa a sala A das 14h às 15h. Queremos representar a quem pertence, que objetivo realiza e como o ecrã obtém confirmação. Cada diagrama escolhe uma dessas perguntas e omite pormenores que não ajudam a responder-lhe.

UML é uma linguagem de modelação, não um processo de desenvolvimento. Os modelos precisam de ser consistentes entre si e com as regras do sistema.

Casos de uso

Um ator é um papel externo que interage com o sistema. Pode ser uma pessoa ou outro sistema. Uma pessoa pode desempenhar vários papéis. Um caso de uso descreve comportamento do sistema que produz um resultado observável com valor para um ator.

A fronteira indica o sistema que estamos a modelar. Se modelarmos só a aplicação móvel, o servidor pode ser um ator externo. Se modelarmos o sistema completo, o servidor faz parte da solução.

Na aplicação de reservas, o estudante reserva uma sala. Essa operação inclui verificar disponibilidade. Pedir equipamento só acontece se o estudante o solicitar, no ponto de extensão equipamento de Reservar sala. Equipamento pertence a uma versão futura fora do âmbito inicial, por isso aparece aqui como extensão possível, não como compromisso da primeira entrega.

Casos de uso da aplicação de reservasO Estudante reserva uma sala. Reservar sala inclui verificar disponibilidade. Pedir equipamento estende reservar sala quando o estudante o pede.Aplicação de reservasEstudanteReservar salapontos de extensãoequipamentoVerificardisponibilidade«include»Pedirequipamento«extend»Condição: pediu equipamento
A inclusão aponta para o comportamento incluído. A extensão aponta para o caso base, no ponto de extensão equipamento.

A associação entre ator e caso de uso é uma linha. A relação include é uma dependência tracejada que parte do caso que inclui e aponta para o caso incluído. Mostra um comportamento incorporado no caso base, que fica incompleto sem ele.

A relação extend também é tracejada, mas aponta no sentido contrário: parte da extensão para o caso base. Liga-se num ponto de extensão e aplica-se quando a condição indicada se verifica; se não houver condição, aplica-se sempre que o ponto é atingido. O caso base tem significado sem a extensão.

Por isso não uses extend para ligar duas ações só porque uma pode acontecer depois da outra: recuperar acesso pode ser um objetivo independente e não uma extensão de iniciar sessão. A relação precisa de representar incorporação de comportamento, não proximidade no menu.

Descrever um caso de uso

Uma elipse não especifica os passos e exceções. Para “Reservar sala”, escrevemos:

CampoDescrição
Ator principalEstudante
Pré-condiçãoO estudante está autenticado
GatilhoO estudante pede a reserva
Fluxo principalEscolhe sala e intervalo; o sistema verifica regras e disponibilidade; confirma e apresenta a reserva
AlternativaSe o intervalo deixou de estar livre, o sistema informa o conflito e não cria a reserva
Pós-condição de sucessoExiste uma reserva confirmada em nome do estudante
Garantia em caso de falhaNão fica uma reserva parcialmente criada

Uma pré-condição diz o que assumimos antes do caso. Não substitui um passo que precisa de tratar uma situação possível. Se a autenticação puder expirar durante a operação, define o comportamento dessa falha.

Classes e modelo de domínio

Um modelo de domínio representa conceitos e relações do problema, como Estudante, Reserva e Sala. Não pretende enumerar todos os ecrãs, bases de dados e classes técnicas.

Uma classe descreve objetos com características comuns. Os compartimentos podem apresentar nome, atributos e operações. Num modelo de domínio podemos omitir operações técnicas que ainda não decidimos.

Modelo de domínio das reservasCada Reserva tem exatamente um Estudante e uma Sala. Cada Estudante e cada Sala podem ter zero ou mais Reservas. Reserva tem início, fim e estado.Estudantenome10..*efetuaReservainíciofimestado0..*1ocupaSalacapacidade
Lê a multiplicidade na ponta oposta à classe de partida.

A multiplicidade numa ponta diz quantas instâncias dessa classe podem relacionar-se com uma instância da outra classe. Partindo de Reserva, lemos 1 junto de Estudante: cada reserva pertence a exatamente um estudante. Partindo de Estudante, lemos 0..* junto de Reserva: um estudante pode ter nenhuma ou várias reservas.

A multiplicidade não proíbe sobreposições de horários, por isso precisamos de uma restrição adicional: duas reservas confirmadas da mesma sala não se sobrepõem. Estrutura e regras complementam-se.

Relações entre classes

Uma associação exprime uma relação estrutural. Uma dependência, normalmente tracejada, indica que um elemento usa outro e pode ser afetado pela sua alteração.

A generalização liga uma especialização ao conceito geral, com triângulo vazio apontado para o geral. Só faz sentido quando a especialização pode ser tratada como esse conceito. “Administrador usa a aplicação” não demonstra que precisamos de uma subclasse Administrador.

A composição tem losango cheio na ponta do todo. Representa propriedade forte das partes; uma parte pertence no máximo a um todo composto de cada vez, e a destruição do todo implica a destruição das partes que ainda lhe pertencem. Não escolhas composição apenas porque uma classe contém uma referência. Um exemplo positivo seria Reserva e LinhaDeReserva se cada linha só existisse dentro de uma reserva e fosse apagada com ela. Sala não é esse caso.

A agregação partilhada, de losango vazio, tem uma semântica mais fraca; uma associação simples costuma ser mais clara quando não precisamos de expressar uma relação todo-parte precisa. Na aplicação, Sala não é parte composta de Reserva, pois a sala continua a existir depois de apagar a reserva; também não há razão para pôr uma base de dados no modelo de domínio apenas por guardar os objetos.

Sequência e colaboração

Um diagrama de sequência mostra participantes e mensagens num cenário. A linha de vida prolonga-se para baixo e o tempo avança nessa direção. O nome de um participante pode identificar a instância e o tipo, como ecrã:Ecrã. :Ecrã identifica apenas o tipo de um participante sem lhe dar um nome.

Neste desenho detalhado, a regra de concorrência pertence ao serviço e ao repositório do servidor. A operação criarSeLivre verifica e cria atomicamente, em vez de fazer uma verificação local seguida de uma gravação desprotegida.

Sequência de confirmação de uma reservaO ecrã pede reservar ao Serviço de reservas, que pede criarSeLivre ao Repositório. Se estiver livre, regressam reserva criada e confirmação. Se estiver ocupada, regressam conflito e mensagem de indisponibilidade. A verificação e criação são atómicas no repositório.ecrã:Ecrãserviço:Serviçode reservasrepo:Repositórioreservar(sala, intervalo)criarSeLivre(...)alt[sala livre]reserva criadaconfirmação[sala ocupada]conflitoindisponibilidade
O tempo desce. As respostas tracejadas regressam ao participante que chamou.

Uma chamada síncrona espera pela resposta; uma mensagem assíncrona permite ao emissor continuar. Uma resposta pode ser omitida quando fica clara. O fragmento alt separa alternativas com guardas, opt descreve um comportamento opcional e loop uma repetição. As guardas têm de explicar as condições.

As mensagens devem corresponder a responsabilidades possíveis dos participantes. Se o diagrama manda o ecrã confirmar uma reserva sem consultar a autoridade dos dados, o desenho revela um erro, mesmo que as setas estejam bem desenhadas.

Atividades e estados

Um fluxo com fork e join

Um diagrama de atividades mostra um fluxo de ações. Uma decisão escolhe uma saída com base numa guarda; uma junção reúne caminhos alternativos. Uma bifurcação, fork, inicia fluxos concorrentes; uma sincronização, join, espera pelos fluxos que deve reunir.

Na figura, o losango separa confirmação e conflito. As barras iniciam atualização da lista e envio da notificação em paralelo e reúnem esses fluxos antes de apresentar o resultado. Se a atualização falhar e a notificação seguir, precisamos de definir o tratamento da falha parcial, não apenas desenhar o join.

Transições de uma reserva

A reserva de Ana começa às 14h. Às 13h59 pode passar de Confirmada para Cancelada; às 14h o mesmo pedido é recusado. Quando chega às 15h, passa para Terminada. O efeito de cancelamento pertence à primeira transição, enquanto uma ação de saída de Confirmada correria também na passagem para Terminada.

Uma máquina de estados descreve como um objeto reage a eventos. Na Reserva, podemos ter Confirmada, Cancelada e Terminada.

Um cancelamento só passa de Confirmada para Cancelada se o início ainda não tiver ocorrido. A transição pode escrever-se evento [guarda] / efeito. Por exemplo, cancelar [agora < início] / libertar intervalo liga Confirmada a Cancelada: a guarda [agora < início] é a condição necessária e o efeito acontece quando a transição é tomada. Uma ação de saída de Confirmada ocorreria em todas as saídas desse estado, por isso não é o mesmo que o efeito específico de cancelar.

Estado atualEventoCondiçãoEstado seguinte e efeito
ConfirmadacancelarAgora é anterior ao início e o pedido vem do titularCancelada; o intervalo deixa de estar reservado
ConfirmadacancelarAgora é igual ou posterior ao inícioMantém Confirmada; o sistema recusa
Confirmadaatingir o fimA hora de fim chegouTerminada
Canceladacancelar novamenteQualquer horaMantém Cancelada; não cria nem liberta outra reserva

A tabela fixa as regras deste exemplo e não presume que pedidos repetidos devolvam sucesso; esse resultado precisa de um contrato próprio. Estados descrevem situações do objeto, não nomes de ecrãs: “Página inicial” não é um estado de Reserva. Um diagrama de estados pode ajudar a encontrar testes para transições válidas e recusadas.

Conferir modelos

Segue um cenário com dados concretos. Uma reserva R pertence ao estudante Ana e ocupa a sala A das 14h às 15h. Confirma que o modelo de domínio admite essa estrutura, que o caso de uso descreve a criação e que a sequência respeita a regra de disponibilidade.

Depois muda uma condição: a sala está ocupada ou a rede falha. O modelo deve explicar o resultado sem inventar outra regra a meio. Na arquitetura, escolhemos os módulos que concretizam estas responsabilidades.

Exercícios

Incluir uma verificação e estender uma reserva

Reservar sala incorpora sempre Verificar disponibilidade. No ponto de extensão equipamento, o estudante pode pedir equipamento. Cancelar reserva é outro objetivo, realizado mais tarde. Desenha as duas dependências, indica a condição da extensão e explica se Cancelar deve estender Reservar só por acontecer depois.

Pista
A seta aponta para o comportamento reutilizado.
Solução

A seta tracejada com «include» parte de Reservar sala e aponta para Verificar disponibilidade. A seta tracejada com «extend» parte de Pedir equipamento e aponta para Reservar sala, no ponto equipamento, com condição “o estudante pediu equipamento”. Reservar continua a produzir uma reserva sem essa extensão. Cancelar é um objetivo independente: ocorrer depois não significa inserir comportamento na execução de Reservar. Não desenhamos essa relação extend. A associação ator-caso é uma linha contínua diferente.

Confere a tua resposta:

  • Desenhei include de Reservar sala para Verificar disponibilidade.
  • Desenhei extend de Pedir equipamento para Reservar sala, com ponto de extensão e condição.
  • Justifiquei que reservar continua a ter significado sem pedir equipamento.
  • Não usei extend para representar a ordem temporal de cancelar.

Erros frequentes

Não uses uma linha contínua só porque a inclusão faz parte do caso. Não escolhas extend para qualquer passo opcional de interface.

Voltar à explicação
Quem pode ter várias reservas?

Na associação Estudante e Reserva, há 1 junto de Estudante e 0..* junto de Reserva. Explica as duas pontas e diz se isso impede horários sobrepostos.

Pista
Lê a ponta oposta à classe de partida.
Solução

Cada reserva pertence a um estudante; cada estudante pode ter zero ou várias reservas, ou seja o modelo admite várias reservas e não impede sobreposição. É necessário definir a restrição temporal da sala e, se existir, a do estudante.

Confere a tua resposta:

  • Disse que cada reserva tem exatamente um estudante.
  • Disse que um estudante pode ter zero ou mais reservas.
  • Expliquei que a sobreposição exige outra restrição.

Erros frequentes

Não leias 0..* como cada reserva ter vários estudantes. Não atribuas uma regra temporal a uma multiplicidade.

Voltar à explicação
Sala é parte da reserva?

Uma Reserva referencia uma Sala. Uma colega propõe composição com losango cheio junto de Reserva. Avalia.

Pista

Ter uma referência não basta para justificar composição.

Solução

A composição não representa a relação descrita. A sala existe independentemente e pode relacionar-se com outras reservas. Uma associação Reserva-Sala, com 1 junto de Sala e 0..* junto de Reserva, exprime a relação.

Confere a tua resposta:

  • Usei propriedade e ciclo de vida para avaliar composição.
  • Observei que a sala existe sem a reserva.
  • Propus uma associação com multiplicidades adequadas.

Erros frequentes

Não uses losango por estética nem para qualquer campo que guarda um objeto.

Voltar à explicação
Uma guarda e um efeito

Uma reserva começa às 14h e está Confirmada. Escreve a transição que permite ao titular cancelá-la às 13h59 e diz o que acontece às 14h. Libertar o intervalo deve ser efeito dessa transição ou uma ação de saída genérica de Confirmada, se também houver uma passagem para Terminada?

Pista
Separa o evento, a condição e o que muda quando a transição é tomada.
Mais uma pista
A hora de início não satisfaz uma condição estrita de anterioridade.
Solução

De Confirmada para Cancelada usamos cancelar [pedido do titular e agora < início] / libertar intervalo. Às 13h59 a guarda é verdadeira e a transição liberta o intervalo. Às 14h a guarda é falsa e o sistema mantém Confirmada. O efeito pertence ao cancelamento. Uma ação de saída de Confirmada correria também na passagem para Terminada. Se a intenção é executar este efeito apenas quando se cancela, a ação de saída é demasiado abrangente. O fim normal já deixa de ocupar instantes futuros pela regra do intervalo.

Confere a tua resposta:

  • Liguei Confirmada a Cancelada pelo evento cancelar, com guarda agora < início e pedido do titular.
  • Coloquei libertar intervalo como efeito dessa transição.
  • Mantive Confirmada e recusei o pedido no instante de início.
  • Expliquei que uma ação de saída correria também numa saída para Terminada.

Erros frequentes

Não escrevas a hora como evento de cancelamento. Não uses menor ou igual nem omitas a autorização. Não confundas o efeito de uma transição com uma ação de qualquer saída do estado.
Voltar à explicação
A alternativa que deixou o fluxo parado

Neste modelo simplificado, cada ação termina sem falhas. Uma decisão escolhe pagar por cartão ou pagar por referência. Ambos os caminhos entram numa barra join que exige chegada dos dois. Depois devem começar, em paralelo, emitir recibo e atualizar o histórico. Uma segunda barra espera pelas duas ações antes de apresentar o resultado. Explica por que a primeira barra pode bloquear o fluxo e redesenha as junções necessárias.

Pista
Quantos caminhos a decisão inicia em cada execução?
Solução

A decisão escolhe apenas um meio de pagamento. O join espera por duas chegadas, mas só uma será produzida: nesse modelo, o fluxo fica parado. Reunimos cartão e referência numa junção de alternativas, representada por um losango, que deixa seguir o caminho que chegou. Depois um fork inicia emitir recibo e atualizar histórico. Agora o join final pode esperar pelas duas ações, porque ambas foram iniciadas. Decisão e junção combinam alternativas; fork e join separam e sincronizam fluxos concorrentes.

Confere a tua resposta:

  • Diagnostiquei que só um dos caminhos alternativos chega ao join.
  • Usei uma junção de alternativas antes do fork.
  • Usei o join apenas para esperar por recibo e atualização iniciados em paralelo.
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.