Title: Modela
1Modelação Especificação de Sistemas de Software
no contexto da Engenharia de Requisitos
- João Pascoal Faria
- Engenharia de Requisitos de Sistemas de Software
- Versão 4.0 (partes I, II e III), 8/12/2003
2Objectivo
- Saber criar modelos de sistemas de software
(representações em pequena escala a um nível
elevado de abstracção) que permitam - exprimir os requisitos dos sistemas de software
como propriedades nesses modelos, de forma o mais
compreensível, completa, consistente e não
ambígua possível (modelo como especificação
completa, consistente e não ambígua de sistema a
desenvolver) - verificar formalmente (por demonstração) a
consistência interna do modelo e a obediência a
propriedades (modelo formal) - testar (animar) o modelo para verificar a sua
consistência interna e validar os requisitos o
mais cedo possível (modelo executável) - verificar mais tarde a conformidade da
implementação com o modelo/especificação (i.e., a
obediência aos requisitos expressos no modelo) - servir de base para a construção/implementação do
sistema (modelo traduzível, construtivo)
3Índice
- Introdução
- Modelação visual (semi-formal) em UML
- Modelação formal com OCL
- (Enriquecimento de modelos visuais em UML com
especificações formais de invariantes,
pré-condições e pós-condições em OCL) - Elaboração de modelos executáveis e traduzíveis
em UML executável XTUML - (Enriquecimento de modelos visuais em UML com
especificações de acções em linguagem de alto
nível) - Modelação / especificação formal em VDM
- Verificação e validação baseada em modelos
4Porquê modelos formais e executáveis? (1)
- Consensual e prática cada vez mais corrente
- modelação visual com diagramas UML durante as
fases de captura e especificação de requisitos,
desenho de alto nível (arquitectura) e desenho
detalhado - geração de algum código (Java, C, SQL, XSD,
etc.) a partir de UML e vice-versa - Passos seguintes
- modelos como especificações completas e rigorosas
(sem ambiguidades nem inconsistências) de alto
nível - especificar restrições formalmente (com
invariantes) - especificar formalmente a semântica das operações
(com pré e pós condições) e, possivelmente, casos
de utilização - importante para aumentar o rigor (complementando
especificações informais) - importante para suportar a verificação formal (do
modelo e conformidade da implementação) - uma especificação pretende ser declarativa (diz
os objectivos) e não necessariamente executável
(não pretende dizer o caminho) - OCL e VDM são opções possíveis
5Porquê modelos formais e executáveis? (2)
- Passos seguintes (cont.)
- modelos executáveis de alto nível
- necessário especificar acções e algoritmos
(resposta a eventos, corpo de operações, ...), em
linguagem de muito alto nível - importante para validar os requisitos o mais cedo
possível - Executable UML e VDM são opções possíveis
- geração automática de código completo (e não só
esqueletos de classes) a partir de modelos de
alto nível - Executable UML e VDM são opções possíveis
- VDM mais maduro e parcialmente integrado com
UML, mas combinação de OCL e UML executável
poderá ganhar
6O que são métodos formais ?
- Método Formal Linguagem de Especificação
Formal Raciocínio Formal (verificação formal,
...) - As técnicas são suportadas por
- Matemática precisa
- Ferramentas de análise poderosas
- Constituem um mecanismo rigoroso e efectivo para
modelação, síntese e análise de sistemas
modelação/especificação
Especificação / modelo formal
síntese
Implementação
análise
7Classificação de métodos formais
- Baseados em Modelos
- Definem o comportamento do sistema através da
construção de um modelo de dados (ou estado)
usando estruturas matemáticas (conjuntos,
sequências, funções finitas, etc.) - VDM, Z - Particularmente apropriados para desenvolvimento
de sistemas de informação - Baseados em Propriedades
- Modelam tipos de dados implicitamente definindo o
comportamento do sistema através de um conjunto
de propriedades - Algébricos definem semântica de operações
através de uma colecção de relações de
equivalência (axiomas equacionais) - Obj, Larch,
... - Axiomáticos definem semântica de operações
através de predicados da lógica de primeira ordem
- Larch, ... - Baseados no Comportamento
- Definem sistemas em termos de sequências
possíveis de estados em vez de tipos de dados e
são normalmente usados para especificar sistemas
concorrentes e distribuídos - Exemplos de formalismos redes de Petri, Calculus
of Communicating Systems (CCS), Communicating
Sequencial Processes (CSP) lógica temporal
sistemas de transição álgebras de processos
8Exemplo em VDM (baseada em modelos)
- class Stack
- instance variables
- elems seq of int
- operations
- Stack () gt () -- construtor
- Stack () elems
- post elems
- Push int gt ()
- Push(i) elems i elems
- post elems i elems
- Pop () gt ()
- Pop() elems tl elems
- pre elems ltgt
- post elems tl elems
- Top () gt int
- Top() return (hd elems)
- pre elems ltgt
- post RESULT hd elems
- and elems elems
É necessário escolher uma representação do estado
de uma stack! Representação de dados (estado)
baseada em construções matemáticas (conjuntos,
sequências, funções finitas, etc.)!
Se fosse caso disso, podiam-se especificar
invariantes, i.e., condições a que têm de
obedecer os estados válidos.
Corpo algorítmico
Pré-condição é uma condição (nos argumentos de
chamada e estado inicial do objecto) a que tem de
obedecer qualquer chamada válida.
Pós-condição é uma condição que relaciona o
resultado da operação e o estado final do objecto
com os argumentos de chamada e o estado inicial
do objecto.
Pré e pós-condição especificam semântica da
operação!
9Exemplo em OBJ (algébrica)
Mais abstracta especifica semântica de operações
por axiomas, sem necessidade de escolher uma
representação de dados interna (cf. noção de ADT)!
- Spec Stack
- Extend Nat by
- Sorts Stack
- Operations
- newstack ? Stack
- push Stack ? Nat ? Stack
- pop Stack ? Stack
- top Stack ? Nat
- Variables
- s Stack n Nat
- Axioms
- pop(newstack) newstack
- top(newstack) zero
- pop(push(s,n)) s
- top(push(s,n)) n
Uma stack é sempre representada por uma expressão
de construção, e.g., push(push(push(newstack,
1), 2), 3)
Axiomas permitem simplificar/avaliar expressões
top(pop(push(push(newstack, 1), 2)))
top(push(newstack, 1)) 1
10Índice
- Introdução
- Modelação visual (semi-formal) em UML
- Modelação formal com OCL
- (Enriquecimento de modelos visuais em UML com
especificações formais de invariantes,
pré-condições e pós-condições em OCL) - Elaboração de modelos executáveis e traduzíveis
em UML executável XTUML - (Enriquecimento de modelos visuais em UML com
especificações de acções em linguagem de alto
nível) - Modelação / especificação formal em VDM
- Verificação e validação baseada em modelos
11Modelação visual em UML
- Os modelos visuais são muito importantes para
facilitar a visualização e compreensão - Peças principais para captura e especificação de
requisitos - Modelo da arquitectura do sistema
- Modelo de casos de utilização
- Modelo de (objectos de) domínio
12Modelo da arquitectura do sistema
- Só se justifica em sistemas complexos
- Decomposição em sub-sistemas, com indicação de
dependências entre sub-sistemas, e dependências
em relação a sistemas externos - Cada sub-sistema corresponde a uma área funcional
(grupo de funcionalidades), cobrindo todas as
camadas da implementação (UI, BL, BD) - Os sub-sistemas podem por sua vez ser decompostos
da mesma forma - Em UML, representar por diagrama de estrutura
estática, com pacotes (packages) e sub-pacotes - Possibilidade de indicar estereótipos system e
subsystem - Em alternativa, representar por diagrama de
blocos com ligações/fluxos entre blocos
13Exemplo Sistema de Gestão de Cuidados de Saúde
sistema
Gestão de Cuidados de Saúde
Cuidados Primários
Cuidados Diferenciados
sub-sistema
dependência
Cuidados Comuns
14Modelo de casos de utilização
- Finalidade mostrar a utilidade ou usos possíveis
do sistema - Conteúdo actores (tipos de utilizadores e
sistemas externos que interagem com o sistema),
casos de utilização (funcionalidades do sistema
tal como são vistas externamente, ou tipos de
interacções entre actores e o sistema) e relações
entre ambos - Casos de utilização capturam os requisitos
funcionais e alguns requisitos não funcionais - Dificuldade qual a granularidade dos casos de
utilização?
15Forma do modelo de casos de utilização (1)
- Visão geral
- Diagrama de casos de utilização acompanhado de
descrição textual que passa superficialmente
pelos casos de utilização e actores mais
importantes
16Exemplo Sistema de Gestão de Conferências
nome do sistema
fronteira do sistema
actor
caso de utilização
diagrama de casos de utilização
17Forma do modelo de casos de utilização (2)
- Visão geral (cont.)
- Se existirem muitos casos de utilização,
apresentar um primeiro diagrama de pacotes de
casos de utilização e depois um diagrama de casos
de utilização para cada pacote - Pacotes correspondem normalmente a sub-sistemas
no modelo da arquitectura
18Exemplo Sistema de Gestão de Hotéis (CRM4SH) (1)
diagrama de pacotes de casos de utilização
19Exemplo Sistema de Gestão de Hotéis (CRM4SH) (2)
diagramas de casos de utilização (com pacotes de
2º nível)
20Exemplo Sistema de Gestão de Hotéis (CRM4SH) (3)
generalização
21Forma do modelo de casos de utilização (3)
- Visão geral (cont.)
- Opcionalmente, modelar através de um ou mais
diagramas de actividades o encadeamento de casos
de utilização (i.e., modelar workflows ou
processos de negócio) - casos de utilização aparecem como actividades no
diagrama de actividades - se tiver sido construído anteriormente um modelo
de processos de negócio, isto já foi feito
22Exemplo Sistema de Gestão de Conferências (1)
actor
objectos de classes do modelo de domínio (ver
adiante)
passos são execuções de casos de utilização!
fluxo de controlo
fluxo de objectos
23Exemplo Sistema de Gestão de Conferências (2)
barra de sincronização (inicia ou termina
execução em paralelo)
24Exemplo Sistema de Gestão de Cuidados de Saúde
Consulta externa do pedido até à efectivação
Manual
EPR
SIIMS
actor interno
Marcar Consulta
Observar Doente
Prescrever Terapêutica
Registar DadosClínicos
Prescrição
Médico
Admitir Doente
Carimbar Prescrição
Funcionário Administrativo
processo de negócio modelado por diagrama de
actividades
SIIMS
EPR
Marcar Consulta
Registar Dados Clínicos
Médico
sistema ou sub-sistema
Admitir Doente
sistema ou sub-sistema
Prescrever Terapêutica
Func. Admin.
25Forma do modelo de casos de utilização (4)
- Actores
- Breve descrição de cada actor
- Casos de Utilização
- Descrição mais ou menos detalhada de cada caso de
utilização - ver a seguir
26Descrição de cada caso de utilização
- Identificação e utilidade
- Nome e descrição sumária tornando evidente
objectivo/utilidade - Features e restrições (Opcional)
- Lista de requisitos internos ao caso de
utilização - Pré-condições e pós-condições (Opcional)
- Condições sobre inputs, outputs, estado inicial e
estado final do sistema (com base em modelo de
estado definido no modelo de domínio ver
adiante) - Opcionalmente, formalizar em OCL (a tratar mais
tarde) - Interface e sequência de funcionamento
- Mostrar sequências normais e excepcionais por
diagramas de sequência - Mostrar todas as sequências possíveis por um
diagrama de actividades - Opcionalmente, mostrar diagrama de navegação
(diagrama de estados com estados da interface) e
esboços de interface (um esboço por estado) - Fontes e referências, classes participantes (do
modelo de domínio), actores participantes,
atributos (prioridade, dificuldade, ...) - Implementação claramente fora do âmbito desta
fase
27Exemplo Sistema de Gestão de Hotéis
diagrama de sequência, mostrando sequência normal
de funcionamento do caso de utilização "Registar
entrada de cliente sem reserva"
objectos
mensagens
28Exemplo Sistema de Gestão de Hotéis
diagrama de actividades, mostrando todas as
sequências possíveis de funcionamento do caso de
utilização "Registar entrada de cliente sem
reserva"
29Exemplo Sistema de Gestão de Conferências
Diagrama de navegação do caso de utilização
"Atribuir Revisores a Artigos" (diagrama de
estados em UML, em que estados são estados de
interface)
estado da interface
evento (acção do utilizador)
Atribuir Revisores a Artigo
artigo
Atribuir Revisores a Artigos
terminar
título autores autor1, autor2, ... resumo
seleccionar artigo
nº de revisores
PDF
artigo
revisores atribuídos
titulo1
0
nome
nº art.
excluir
1
titulo 2
excluir
seleccionar opção "Atribuir revisores a artigos"
terminar
revisor 1
3
revisor 2
excluir
1
Terminar
revisores disponíveis
nome
nº art.
atribuir
Dados de Revisor
seleccionar revisor
atribuir
revisor 3
3
nome instituição e-mail áreas de
interesse artigos que revê artigo1, ...
revisor 4
0
atribuir
fechar
Terminar
Fechar
excluir
atribuir
30Modelo de (objectos de) domínio (1)
- Objectivos
- organizar o vocabulário do domínio do problema
(utilizado na descrição dos casos de utilização) - organizar e relacionar termos que estão definidos
num glossário ou num dicionário de dados - capturar os requisitos de informação
- que informação é mantida no sistema e trocada com
o ambiente - especificar as transacções do negócio (por
operações) - três tipos de classes
- classes que modelam o estado interno persistente
e partilhado do sistema, como atributos de
entidades (e eventos) do negócio e respectivas
ligações são as classes mais importantes - classes que modelam a estrutura de documentos
trocados entre o sistema e o seu ambiente - classes que modelam tipos de dados (usados nos
atributos e operações das classes anteriores)
31Modelo de (objectos de) domínio (2)
- Forma
- Visão geral
- Diagrama de classes
- Descrição textual que passa superficialmente
pelas classes mais importantes
32Exemplo Sistema de Gestão de Hotéis
agregação
classe com atributos
associação
classe-associação (para indicar atributos)
diagrama de classes
nota
(versão corrigida para ficar consistente com OCL)
generalização
33Modelo de (objectos de) domínio (3)
- Forma (cont.)
- Descrição de cada classe
- Significado
- Descrição de atributos
- Definição de restrições
- Informalmente
- Formalmente, como invariantes em OCL (a ver mais
tarde) - Descrição de operações (quando definidas)
- Sintaxe
- Semântica
- Informalmente
- Formalmente, com pré-condições e pós-condições em
OCL (a ver mais tarde) - (Opcional) Ciclo de vida dos objectos da classe
(diagrama de estados) - Estados devem corresponder a condições nos
valores de atributos e ligações - Nesta fase, eventos devem corresponder a casos de
utilização, podendo ter parâmetros
34Exemplo Sistema de Gestão de Hotéis
ciclo de vida de uma reserva (diagrama de estados)
estado
transição
evento (corresponde a execução de caso de
utilização)
estado composto
subestado
evento temporal
35Índice
- Introdução
- Modelação visual (semi-formal) em UML
- Modelação formal com OCL
- (Enriquecimento de modelos visuais em UML com
especificações formais de invariantes,
pré-condições e pós-condições em OCL) - Elaboração de modelos executáveis e traduzíveis
em UML executável XTUML - (Enriquecimento de modelos visuais em UML com
especificações de acções em linguagem de alto
nível) - Modelação / especificação formal em VDM
- Verificação e validação baseada em modelos
36O que é OCL?
- OCL Object Constraint Language
- Faz parte de UML
- Linguagem textual para formalizar invariantes,
pré-condições e pós-condições por intermédio de
expressões booleanas sem efeitos laterais - Expressões podem invocar métodos que consultam o
estado de objectos (query methods), mas não
métodos que alteram o estado de objectos ou criam
ou eliminam objectos - Baseada em conceitos matemáticos (conjuntos,
sequências, lógica matemática, etc.) - Versão corrente 1.5
- Versão em preparação 2.0
37Especificação de invariantes em OCL
- Invariantes são restrições a que devem obedecer
os estados válidos - Definidos em OCL usando palava-chave inv
- Em OCL, invariantes são sempre definidos no
contexto de uma classe (ou objecto de classe) - Tipos de invariantes comuns
- restrição ao domínio (ou conjunto de valores
possíveis) de um atributo - chaves de uma classe - atributo ou conjunto de
atributos de uma classe que não pode tomar o
mesmo valor (ou conjunto de valores) em dois
objectos diferentes da classe - restrições relacionadas com ciclos nas
associações - restrições relacionadas com datas e horas
- restrições que definem a fórmula de derivação de
elementos derivados (replicados ou calculados) - regras de existência indicam que certos
objectos devem existir quando outros objectos
existem
38Exemplo Sistema de Gestão de HotéisRestrições a
domínios de atributos (1)
- R1) Em "Preço Serviço", o número de pessoas tem
de ser maior que 0context Preço_Serviço inv
número_de_pessoas gt 0 - R2) Em "Estadia", o número de pessoas tem de ser
maior que 0context Estadia inv
número_de_pessoas gt 0 - R3) Em "Reserva", o número de pessoas tem de ser
maior que 0context Reserva inv
número_de_pessoas gt 0 - R4) Em "Estadia_Quarto", o número de pessoas tem
de ser maior que 0context Estadia_Quarto inv
número_de_pessoas gt 0
39Exemplo Sistema de Gestão de HotéisRestrições a
domínios de atributos (2)
- R5) Em "Quarto", a capacidade tem de ser maior
que 0context Quarto inv capacidade gt 0 - R6) Em "Preço_Serviço", o preço tem de ser maior
que 0context Preço_Serviço inv preço gt 0
40Elementos de OCL
- Formas equivalentescontext Reserva inv
número_de_pessoas gt 0context Reserva inv
self.número_de_pessoas gt 0context r Reserva
inv r.número_de_pessoas gt 0 - Pode-se dar um nome ao invariantecontext
Reserva inv NumPesResPos número_de_pessoas gt 0
41Exemplo Sistema de Gestão de HotéisChaves
simples (1)
- R7) Não podem existir dois clientes com o mesmo
número, isto é, o número de cliente é
chavecontext Cliente inv R7
Cliente.allInstances-gtisUnique(número_de_cliente)
- R7') (Equivalente a anterior, porque só há 1
hotel) Um hotel não pode ter dois clientes com o
mesmo númerocontext Hotel inv R7b
clientes-gtisUnique(número_de_cliente)Nota
Sempre que possível é de evitar usar
classe.allInstances, pois é fácil implementar
numa base de dados mas é difícil implementar em
objectos em memória (em memória prefere-se partir
de um objecto raiz).
42Elementos de OCLColecções
- Cliente.allInstances dá o conjunto (Set) de todas
as instâncias existentes da classe Cliente - O operador "-gt" toma o lado esquerdo como
colecção e aplica-lhe a operação indicada no lado
direito - Colecções em OCL podem ser dos seguintes tipos
- Set conjunto de elementos distintos
- Bag conjunto admitindo elementos repetidos
- Sequence sequência de elementos admitindo
repetição - OrderedSet (só versão 2.0) conjunto ordenado de
elementos distintos - Uma colecção OCL contém objectos (instâncias de
classes) ou valores de tipos primitivos (Integer,
Real, Boolean ou String) - Classes são tipos-referência (reference types)
- variáveis contêm referências para objectos
comparação e atribuição de referências - Tipos primitivos, colecções e tuplos (ver
adiante) são tipos-valor (value types) - variáveis contêm os próprios valores comparação
e atribuição de valores - equivalem a tipos-referência em que não se podem
criar duas instâncias (objectos) com o mesmo
conteúdo e o conteúdo de uma instância é imutável
43Elementos de OCLOperações com colecções (1)
- collection-gtexists(expressãoBooleana) dá true
se a expressão for verdadeira para pelo menos um
elemento da colecção - ? x ? collection expressãoBooleana(x)
- collection-gtforAll(expressãoBooleana) dá true
se a expressão for verdadeira para todos os
elementos da colecção - ? x ? collection expressãoBooleana(x)
- collection-gtisUnique(expressão) dá true não
existirem dois elementos da colecção com o mesmo
valor da expressão - ? x, y ? collection x ? y ? expressão(x) ?
expressão(y) - collection-gtnotEmpty()
- collection-gtselect(expressãoBooleana)
selecciona os elementos da colecção para os quais
a expressão é verdadeira - x ? collection expressãoBooleana(x) - (tb.
com sequências)
44Elementos de OCLOperações com colecções (2)
- collection-gtcollect(expressão) produz uma nova
colecção formada pelos valores da expressão
indicada sobre os elementos da primeira colecção - collection-gtsum() soma valores de uma colecção
de inteiros ou reais - collection-gtincluding(elem) dá nova colecção
incluindo o elemento indicado - collection-gtexcluding(elem) dá nova colecção
excluindo o elemento indicado - collection-gtiterate(iterador DeclaraçãoEInicializ
açãoAcumulador proximoValorAcumulador) dá o
valor final do acumulador depois de iterar sobre
todos os elementos da colecção - collection-gtany(expressãoBooleana) dá um
elemento qualquer da colecção que verifica a
expressão booleana indicada
45Elementos de OCLNavegação através de associações
e classes-associações
versão 4.0
quartos
Estadia
Quarto
quartos Set(Quarto)estadia_Quarto
Set(Estadia_Quarto)
estadia Set(Estadia)estadia_Quarto
Set(Estadia_Quarto)
Estadia_Quarto
quartos Quartoestadia Estadia
- No contexto de uma instância de Estadia
- quartos conjunto de instâncias correspondentes
da classe Quarto (usa-se o rolename), do tipo
Set(Quarto) - estadia_Quarto conjunto de instâncias
correspondentes da classe-associação
Estadia_Quarto (usa-se o nome da
classe-associação com 1ª letra em minúscula), do
tipo Set(Estadia_Quarto) - No contexto de uma instância de Quarto
- estadia conjunto de instâncias correspondentes
da classe Estadia (como não existe rolename,
usa-se o nome da classe com 1ª letra em
minúscula), do tipo Set(Estadia) - estadia_Quarto conjunto de instâncias
correspondentes da classe-associação
Estadia_Quarto (usa-se o nome da
classe-associação com 1ª letra em minúscula), do
tipo Set(Estadia_Quarto) - No contexto de uma instância de Estadia_Quarto
- quartos instância correspondente da classe
Quarto (usa-se o rolename), do tipo Quarto - estadia instância correspondente da classe
Estadia (como não existe rolename, usa-se o nome
da classe com 1ª letra em minúscula), do tipo
Estadia
46Elementos de OCLNavegação através de associações
qualificadas
versão 4.0
Hotel
cliente
númeroCliente
Pessoa
0..1
1..
hotel Set(Hotel)
cliente Set(Pessoa)clientei Pessoa
- No contexto de uma instância de Hotel
- cliente conjunto de instâncias correspondentes
da classe Cliente, do tipo Set(Pessoa) - clientei instância da classe Pessoa
correspondente a númeroCliente i - No contexto de uma instância de Pessoa
- hotel conjunto de instâncias correspondentes da
classe Hotel, do tipo Set(Hotel) - Dado um hotel, como obter o seu conjunto de
números de clientes (instâncias do
qualificador)?? - Dada uma pessoa, como obter o seu conjunto de
pares hotel número de cliente??
47Elementos de OCLNavegação para classe-associação
em associação recursiva
versão 4.0
Empregado
chefes
Avaliação
subordinados
avaliação
guarda avaliação atribuída pelo chefe ao
subordinado
- No contexto de uma instância de Empregado
- chefes conjunto de chefes correspondentes
(instâncias de Empregado) - subordinados conjunto de subordinados
correspondentes (instâncias de Empregado) - avaliaçãochefes conjunto de instâncias
correspondentes da classe-associação Avaliação
quando se navega do empregado para os seus chefes
(permite aceder às avaliações que foram
atribuídas ao empregado pelos seus chefes) - avaliaçãosubordinados - conjunto de instâncias
correspondentes da classe-associação Avaliação
quando se navega do empregado para os seus
subordinados (permite aceder às avaliações que o
empregado atribuiu aos seus subordinados)
48Exemplo Sistema de Gestão de HotéisChaves
simples (2)
- R8) (Chave alternativa) Não podem existir dois
clientes com o mesmo número de bilhete de
identidade ou passaporte (este atributo pode ser
visto como uma combinação de tipo de documento
número de documento)context Cliente inv
Cliente.allInstances-gtisUnique(
número_do_bilhete_de_identidade_ou_passaporte) - R9) Não podem existir duas reservas com o mesmo
númerocontext Reserva inv Reserva.allInstances
-gtisUnique(número_da_reserva) - R10) Não podem existir duas estadias com o mesmo
número context Estadia inv Estadia.allInstance
s-gtisUnique(número_da_estadia)
49Exemplo Sistema de Gestão de HotéisChaves
simples (3)
- R11) Não podem existir dois quartos com o mesmo
númerocontext Quarto inv Quarto.allInstances-gt
isUnique(número) - R12) Não podem existir dois empregados com o
mesmo logincontext Empregado inv
Empregado.allInstances-gtisUnique(login) - R13) Não podem existir duas facturas com o mesmo
número context Factura inv Factura.allInstance
s-gtisUnique(número) - R14) Não podem existir dois serviços com o mesmo
nome context Serviço inv Serviço.allInstances-
gtisUnique(nome)
50Exemplo Sistema de Gestão de HotéisChaves
compostas
- R15) Em "Preço Serviço", não podem existir duas
ocorrências para a mesma combinação de serviço,
data de início e número de pessoasEm OCL 2.0
(em preparação), existe o conceito de tuplo
(conjunto de componentes com nome e valor), pelo
que se poderá escrevercontext Preço_Serviço
inv Preço_Serviço.allInstances-gtisUnique(p
Preço_Serviço Tupleserviço Serviço
p.serviço, data_de_início
Date p.data_de_início,
número_de_pessoas Integer p.número_de_pessoas
)Ou omitindo os tipos do iterador e dos
componentes dos tuploscontext Preço_Serviço
inv Preço_Serviço.allInstances-gtisUnique(p
Tupleserviço p.serviço,
data_de_início p.data_de_início,
número_de_pessoas p.número_de_pessoas )
variável/iterador (para desambiguar)
separador entre iterador e expressão
51Exemplo Sistema de Gestão de HotéisChaves em
classes derivadas
- R16) Em "Preço Serviço", não podem existir duas
ocorrências para a mesma data, número de pessoas
e serviço (chave em classe derivada resultante de
desdobrar "Preço Serviço" por datas)context
Preço_Serviço inv not Preço_Serviço.allInstances
-gtexists(p1, p2 p1 ltgt p2 and p1.serviço
p2.serviço and DateInterval.overlap(p1.data_d
e_início, p1.data_de_fim,
p2.data_de_início,
p2.data_de_fim, false) and p1.número_de_pessoa
s p2.número_de_pessoas)Notas 1) Esta
restrição implica a restrição anterior (R15)2)
Uma vez que o standard não inclui a definição do
tipo Date, pressupõe-se definição apropriada dos
tipos Date e DateInterval (ver adiante)
52Exemplo Sistema de Gestão de HotéisRestrições
relacionadas com ciclos (1)
- R17) A reserva a que se refere uma estadia tem de
ser do mesmo cliente que a estadiacontext
Estadia inv reserva-gtnotEmpty() implies
reserva.cliente clienteNota "reserva"
designa o objecto correspondente pela associação
c/"Reserva", cuja multiplicidade é 0..1, pelo que
é necessário fazer o teste - R18) A reserva a que se refere um contacto tem de
ser do mesmo cliente que o contactocontext
Contacto inv reserva-gtnotEmpty() implies
reserva.cliente cliente
53Exemplo Sistema de Gestão de HotéisRestrições
relacionadas com ciclos (2)
- R19) A estadia a que se refere um contacto tem de
ser do mesmo cliente que o contacto.context
Contacto inv estadia-gtnotEmpty() implies
estadia.cliente cliente - R20) O contacto anterior a que se refere um
contacto tem de ser do mesmo cliente que o
contacto actual.context Contacto inv
contacto_anterior-gtnotEmpty() implies
contacto_anterior.cliente cliente - Nota ver mais em elementos derivados
54Exemplo Sistema de Gestão de HotéisRestrições
relacionadas com datas (1)
- R21) Numa reserva, a data de saída prevista tem
de ser posterior à data de entrada
previstacontext Reserva inv
data_de_saída_prevista.isAfter(data_de_entrada_pre
vista) - R22) Numa reserva, a data de entrada prevista não
pode ser anterior à data da reservacontext
Reserva inv not data_da_reserva.isBefore(data_de
_entrada_prevista) - R23) Numa estadia, a data de saída tem de ser
posterior à data de entradacontext Estadia
inv data_de_saída.isAfter(data_de_entrada)
55Exemplo Sistema de Gestão de HotéisRestrições
relacionadas com datas (2)
- R24) Numa estadia, a data de expiração do cartão
de crédito tem de ser posterior à data de saída
context Estadia inv R24 data_de_expiração_do_c
artão_de_crédito.isAfter(data_de_saída) - R25) Em "Estadia Quarto", a data da saída tem de
ser posterior à data de entradacontext
Estadia_Quarto inv R25 data_de_saída.isAfter(dat
a_de_entrada) - R26) O intervalo de datas de uma ocorrência de
"Estadia Quarto" (classe-associação), tem de
estar contido no intervalo de datas da estadia
correspondentecontext Estadia_Quarto inv R26
DateInterval.contains(estadia.data_de_entrada,
estadia.data_de_saída, data_de_entrada,
data_de_saída, true)
56Exemplo Sistema de Gestão de HotéisRestrições
relacionadas com datas (3)
- R27) Na relação entre contactos, a data-hora do
contacto anterior tem de ser anterior à data-hora
do contacto seguintecontext Contacto inv R27
contacto_anterior-gtnotEmpty() implies
contacto_anterior.data_hora.isBefore(data_hora)N
ota Pressupõe definição de tipo DateTime com
operações apropriadas
57Exemplo Sistema de Gestão de HotéisRegras de
existência
- R28) Têm de estar definidos preços para se
aceitarem estadias ou reservascontext e
Estadia inv R28a e.data_de_entrada.getDatesUntil
(e.data_de_saída, true) -gtforAll(d
e.serviço.preços -gtexists( p
p.número_de_pessoas
e.número_de_pessoas and
p.data_de_início.containsUntil(p.data_de_fim, d,
true))context r Reserva inv 28b
r.data_de_entrada_prevista. getDatesUntil(r.data_d
e_saída_prevista, true) -gtforAll(d
r.serviço.preços -gtexists( p
p.número_de_pessoas
r.número_de_pessoas and
p.data_de_início.containsUntil(p.data_de_fim, d,
true) )Notas na realidade, seria mais correcto
definir em Hotel atributos com número máximo de
pessoas por estadia/reserva e gama de datas com
preços definidos (data inicial e final), e
obrigar depois a estarem definidos preços para
todos os serviços, nº de pessoas e datas nas
gamas definidas
58Exemplo Sistema de Gestão de HotéisConsistência
de preços
- R29) Aumentando o número de pessoas o preço (do
grupo) não pode baixarcontext Preço_Serviço inv
R29 Preço_Serviço.allInstances-gtforAll(p1, p2
p1.serviço p2.serviço and
p1.número_de_pessoas gt p2.número_de_pessoas
and DateInterval.overlap(p1.data_de_início,
p1.data_de_fim,
p2.data_de_início, p2.data_de_fim, true)
implies p1.preço gt p2.preço) - R30) Partindo um grupo o preço não pode baixar
context Preço_Serviço inv R30
Preço_Serviço.allInstances-gtforAll(p1, p2, p3
p1.serviço p2.serviço and p1.serviço
p3.serviço and DateInterval.overlap(p1.data_
de_início, p1.data_de_fim,
p2.data_de_início,
p2.data_de_fim, true) and DateInterval.overlap(
p1.data_de_início, p1.data_de_fim,
p3.data_de_início,
p3.data_de_fim, true) and DateInterval.overlap(
p2.data_de_início, p2.data_de_fim,
p3.data_de_início,
p3.data_de_fim, true) and p1.número_de_pessoas
(p2.número_de_pessoas
p3.número_de_pessoas)
implies p1.preço lt p2.preço p3.preço)
59Exemplo Sistema de Gestão de HotéisConsistência
de estados
- R31) Uma reserva no estado "efectivada" é uma
reserva com uma estadia associadacontext
Reserva inv R31 (estado 'efectivada')
estadia-gtnotEmpty() - R32) Assim que se ultrapassa a data de entrada
prevista de uma reserva sem que o cliente
compareça, uma reserva que não foi cancelada
passa ao estado "cliente faltou" context
Reserva inv R32 (Date.curDate.isAfter(data_de_en
trada_prevista) and estadia-gtisEmpty() and
estado ltgt 'anulada') (estado 'cliente
faltou')
60Exemplo Sistema de Gestão de HotéisRestrições
relativas à ocupação do hotel (1)
- R33) O mesmo quarto não pode estar ocupado duas
vezes na mesma data (isto é, não pode ter duas
ocorrências de "Estadia Quarto" na mesma
data)context Quarto inv R33
estadia_Quarto-gtforAll( e1, e2 e1 ltgt e2
implies DateInterval.disjoint(e1.data_de_ent
rada, e1.data_de_saída,
e2.data_de_entrada,
e2.data_de_saída, true)) - R34) O número de pessoas colocadas num quarto tem
de estar compreendido entre 1 e a capacidade do
quarto. context Estadia_Quarto inv R34
número_de_pessoas gt 1 and número_de_pessoas lt
quarto.capacidade
61Exemplo Sistema de Gestão de HotéisRestrições
relativas à ocupação do hotel (2)
- R35) Para qualquer data e estadia, a soma dos
números de pessoas indicados em "Estadia Quarto"
deve ser igual ao número de pessoas indicado em
"Estadia"context e Estadia inv R35
e.data_de_entrada.getDatesUntil(e.data_de_saída,
true) -gtforAll(d e.número_de_pessoas
e.estadia_quarto -gtselect(q
q.data_de_entrada.containsUntil(q.data_de_saída,
d, true)) -gtcollect(número_de_pessoas)
-gtsum() )
62Exemplo Sistema de Gestão de HotéisRestrições
relativas à ocupação do hotel (3)
modificado versão 3.0
- R36) Deve ser possível satisfazer todas as
reservas activas. context Reservadef
arranjaQuartos( gruposPorColocar
Bag(Tuple(entrada Date, saída Date, n_pessoas
Integer)), gruposColocados
Set(Tuple(entrada Date, saída Date, quarto
Quarto)) ) Boolean (
gruposPorColocar-gtnotEmpty() implies let
g gruposPorColocar-gtany(true) in
Quarto.allInstances-gtexists (q
gruposColocados-gtforall(gc gc.quarto q
implies
DateInterval.disjoint(gc.entrada, gc.saída,
g.entrada, g.saída, true)) and
arranjaQuartos( if q.capacidade gt g.n_pessoas
then gruposPorColocar-gtexcluding(g)
else
gruposPorColocar-gtexcluding(g)
-gtincluding(Tupleentrada g.entrada, saída
g.saída,
n_pessoas g.n_pessoas q.capacidade)
endif,
gruposColocados-gtincluding(Tupleentrada
g.entrada,
saída g.saída, quarto
q))) )inv R36 arranjaQuartos(Reserva.allInstan
ces-gtselect(estado 'activa')-gtcollect( r
Tupleentrada r.data_de_entrada, saída
r.data_de_saída, n_pessoas r.número_de_pessoas)
,
Estadia_Quarto.allInstances-gtcollect( eq
Tupleentrada eq.data_de_entrada, saída
eq.data_de_saída, quarto eq.quarto))
63Exemplo Sistema de Gestão de HotéisRestrições
relativas a elementos derivados
- R37) A capacidade do hotel é a soma das
capacidades dos seus quartos (caso de dado
calculado)Context Hotel inv R37 capacidade
quartos-gtselect(capacidade)-gtsum() - R38) O cliente da factura é o cliente da estadia
a que se refere a factura (caso de dado
replicado)Context Factura inv R38 cliente
estadia.cliente - R39) O valor da factura é calculado em função dos
preços tabeladosContext Factura inv R39 valor
estadia.serviço.preços -gtselect(p
p.número_de_pessoas estadia.número_de_pessoas)
-gtcollect(p p.preço
Integer.max(0,
1Date.difference(
Date.min(estadia.data_de_fim, p.data_de_fim),
Date.max(estadia.data_de
_início, p.data_de_início))) -gtsum()
64Exemplo Sistema de Gestão de HotéisRestrições
relativas a elementos derivados (OCL 2.0)
- Na versão 2.0 será possível escrever
- R37') A capacidade do hotel é a soma das
capacidades dos seus quartosContext
Hotelcapacidade Integer derive
quartos-gtselect(capacidade)-gtsum() - R38) O cliente da factura é o cliente da estadia
a que se refere a facturaContext
Facturacliente Cliente derive
estadia.cliente - R39) idem
65Exemplo Sistema de Gestão de HotéisDefinição
dos tipos Date, DateTime e DateInterval (1)
Date
DateTime
curDate Date
isAfter(d2 DateTime) BooleanisBefore(d2
DateTime) Boolean
toInteger() Integer isAfter(d2 Date)
Boolean isBefore(d2 Date) Boolean max(d1
Date, d2 Date) Date min(d1 Date, d2 Date)
Date difference(d1 Date, d2 Date) Integer
DateInterval
disjoint(left1 Date, right1 Date, left2 Date,
right2 Date, openRight Boolean )
Booleanoverlap(left1 Date, right1 Date, left2
Date, right2 Date, openRight Boolean )
Booleancontains(left1 Date, right1 Date,
left2 Date, right2 Date, openRight Boolean )
Boolean(...)
Apenas foram indicados métodos que não alteram
estado, e que por isso podem ser usados em
expressões OCL
66Exemplo Sistema de Gestão de HotéisDefinição
dos tipos Date, DateTime e DateInterval (2)
- Definição de operações auxiliares em OCL
(OclHelper)context Date-- obtém conjunto de
datas representadas por inteiros desde self até
uma-- outra data (right), incluída ou
excluídadef getDatesUntil(right Date,
openRight Boolean) Set(Integer) if
openRight then Sequenceself.asInteger()
.. (right.asInteger()-1)-gtasSet() else
Sequenceself.asInteger() .. right.asInteger()-gta
sSet() endif-- verifica se o intervalo que
vai desta data (self) até outra data (right), --
incluída ou excluída, contém uma terceira data
representada por inteirodef containsUntil(right
Date, data Integer, openRight Boolean )
Boolean data gt self.asInteger() and data
lt (if openRight then right.asInteger()-1 else
right.asInteger() endif)Nota como não se pode
dizer que são static, foram definidas em Date em
vez de em DateInterval
67Especificação da semântica de operações em OCL
- Nos diagramas de classes apenas se indica a
sintaxe ou assinatura das operações - A semântica das operações pode ser especificada
por pré-condições e pós-condições em OCL - A pré-condição é uma condição booleana nos
argumentos de chamada e estado inicial do(s)
objecto(s) a que deve obedecer uma chamada válida - Pré-condição é indicada a seguir a "pre"
- A pós-condição é uma condição booleana nos
argumentos de chamada, valor retornado, estado
inicial do(s) objecto(s), e estado final do(s)
objecto(s) que se deve verificar no final da
execução da operação, supondo que a pré-condição
se verifica - Pós-condição é indicada a seguir a "post"
- Indica o efeito que a operação deve produzir, sem
indicar o algoritmo - Estado inicial de uma propriedade de um objecto é
acedido com o sufixo "_at_pre" (ver a seguir) - Valor retornado pela operação é acedido com
"result"
68Acesso a valores antigos em pós-condições (1)
- propriedade_at_pre valor antigo da propriedade (no
início da execução da operação a que se refere a
pós-condição) - Se não se usar "_at_pre", estamos a aceder ao novo
valor da propriedade, i.e., ao valor no fim da
execução da operação - São consideradas propriedades
- atributos
- extremos de associações
- operações ou métodos sem efeitos laterais (só de
consulta) - Estas propriedades podem estar definidas em
- classes, interfaces e tipos (interfaces e tipos
são classes especiais) - associações
- tipos de dados primitivos (datatypes)
69Acesso a valores antigos em pós-condições (2)
- No caso de operações ou métodos, "_at_pre" é
colocado entre o nome da operação e a lista de
argumentos - operação_at_pre(argumentos)
- Quando o valor antigo de uma propriedade se
refere a um objecto, é necessário voltar a usar
"_at_pre" se quisermos aceder a valores antigos de
propriedades desse objecto - a.b_at_pre.c -- takes the old value of property b of
a, say x -- and then the new
value of c of x. - a.b_at_pre.c_at_pre -- takes the old value of property
b of a, say x -- and then
the old value of c of x. - Não se pode aceder ao valor antigo de uma
propriedade de um objecto criado no decurso da
operação, nem ao novo valor antigo de uma
propriedade de um objecto destruído no decurso da
operação. Senão o resultado é OclUndefined
70Exemplo Sistema de Gestão de HotéisDefinição de
pré e pós-condições de reserva (1)
- Registo de reserva 1ª versão, recebendo e
devolvendo objectoscontext ReservacriarReserva
( cliente Cliente, serviço
Serviço, número_de_pessoas Integer,
data_de_entrada_prevista Date,
data_de_saída_prevista Date,
número_do_cartão_de_crédito Integer,
titular_do_cartão_de_crédito String,
data_de_expiração_do_cartão_de_crédito Date)
Reservapre número_de_pessoas gt 0 -- R3
and not data_de_entrada_prevista.isBefore(Date.cur
Date()) -- R32 and data_de_saída_prevista
.isAfter(data_de_entrada_prevista) -- R21
and data_de_expiração_do_cartão_de_crédito.isAfter
(data_de_saída_prevista) -- R24 and
Hotel.temQuartos(data_de_entrada_prevista,
data_de_saída_prevista, número_de_pessoas) --
R36 and serviço.temPreços(data_de_entrada_p
revista, data_de_saída_prevista,
número_de_pessoas) -- R28 and
GestãoCartões.cartãoVálido(número_do_cartão_de_cré
dito, titular_do_cartão_de_crédito,
data_de_expiração_do_cartão
_de_crédito) -- envolve acesso a sistema externo
(continua)
Exercício definir em OCL as operações auxiliares
temQuartos e temPreços (ver R36 e R28)
71Exemplo Sistema de Gestão de HotéisDefinição de
pré e pós-condições de reserva (2)
- (continuação)post result.oclIsNew() -- ou
Reserva.allInstances Reserva.allInstances_at_pre-gti
ncluding(result) -- atributos com
valores dados pelos argumentos da operação
and result.número_de_pessoas
número_de_pessoas and result.data_de_entra
da_prevista data_de_entrada_prevista
and result.data_de_saída_prevista
data_de_saída_prevista and
result.data_de_saída_prevista
data_de_saída_prevista and
result.número_do_cartão_de_crédito
número_do_cartão_de_crédito and
result.titular_do_cartão_de_crédito
titular_do_cartão_de_crédito and
result.data_de_expiração_do_cartão_de_crédito
data_de_expiração_do_cartão_de_crédito
-- associações and result.serviço
serviço and result.cliente cliente
and result.estadia-gtisEmpty() and
result.contacto_com_Cliente-gtisEmpty()
-- atributos calculados and
result.data_da_reserva Date.curDate()
and result.estado 'activa' and
result.número_da_reserva 1 Reserva.allInstance
s_at_pre-gt
iterate(r maiorNum Integer 0
maiorNum.max(r.número_da_reserva_at_pre))
Como dizer que não há mais alterações de estado
além das referidas explicitamente?!
Pós-condição está escrita de forma construtiva!
72Exemplo Sistema de Gestão de HotéisDefinição de
pré e pós-condições de reserva (3)
- Registo de reserva - 2ª versão, recebendo e
devolvendo chaves de objectoscontext
ReservacriarReserva( número_de_cliente
Integer, nome_do_serviço String,
número_de_pessoas Integer,
data_de_entrada_prevista Date,
data_de_saída_prevista Date,
número_do_cartão_de_crédito Integer,
titular_do_cartão_de_crédito String,
data_de_expiração_do_cartão_de_crédito Date)
Integer -- número_da_reservapre
Cliente.allInstances-gtexists(c
c.número_de_cliente número_de_cliente) --
integridade referencial and
Serviço.allInstances-gtexists(s s.nome
nome_do_serviço) -- integridade referencial
and ... (o resto como anteriormente)post let
cliente Cliente Cliente.allInstances_at_pre-gt
select(c c.número_de_cliente_at_pre
número_de_cliente)-gtany(true),
serviço Serviço Serviço.allInstances_at_pre-gt
select(s s.nome_at_pre nome_do_serviço)-gtany(true)
, novas_reservas Set(Reserva)
Reserva.allInstances - Reserva.allInstances_at_pre
in novas_reservas-gtsize() 1
and let reserva Reserva novas_reservas-gtany(
true) in result
reserva.número_da_reserva
and ... (o resto como anteriormente, com
"result" substituído por "reserva")
73Exemplo Sistema de Gestão de HotéisDefinição de
pré e pós-condições de check-in (1)
- Check-in com reserva prévia versão em que
quartos são atribuídos automaticamentecontext
EstadiacheckInComReserva(reserva Reserva)
Estadiapre reserva.estado 'activa'
and reserva.data_de_entrada_prevista
Date.curDate() post result.oclIsNew()
and result.número_de_pessoas reserva.número_de_p
essoas_at_pre and result.data_de_entrada
reserva.data_de_entrada_prevista_at_pre and
result.data_de_saída reserva.data_de_saída_previ
sta_at_pre and result.número_do_cartão_de_cr
édito reserva.número_do_cartão_de_crédito_at_pre
and result.titular_do_cartão_de_crédito
reserva.titular_do_cartão_de_crédito_at_pre
and result.data_de_expiração_do_cartão_de_crédito
reserva.data_de_expiração_do_cartão_de_crédito_at_pre
and result.número_da_estadia 1
Estadia.allInstances_at_pre-gt
iterate(r maiorNum Integer 0
maiorNum.max(r.número_da_estadia_at_pre))
and result.cliente reserva.cliente_at_pre
and result.serviço reserva.serviço_at_pre
and result.reserva reserva and
result.contacto_com_Cliente-gtisEmpty()
and result.factura-gtisEmpty() (continua)
Exercício escrever pré e pós-condição de
check-out
74Exemplo Sistema de Gestão de HotéisDefinição de
pré e pós-condições de check-in (2)
- (continuação) -- actualização do estado da
reserva and reserva.estadia result
and reserva.estado 'efectivada' - -- Condições a que tem de obedecer a
atribuição automática de quartos (sem mudanças de
quartos) - -- selecção de quartos (já optimizada)
and reserva.escolhasQuartosPossiveis_at_pre-gtincl
udes(result.estadia_Quarto-gtcollect(quarto) )
-- ver definição de escolhasQuartosPossiv
eis a seguir -- definição de datas de
estadia em cada quarto (garantindo R26) and
result.estadia_Quarto-gtforall(eq
eq.data_de_entrada result.data_de_entrada
and eq.data_de_saída result.data_de_saída)
-- escolha de número de pessoas em cada quarto
(garantindo R34 e R35) and
result.estadia_Quarto-gtforall(eq
eq.número_de_pessoas gt 1
and
eq.número_de_pessoas lt quarto.capacidade)
and result.estadia_Quarto-gtcollect(eq
eq.número_de_pessoas)-gtsum() result.número_de_pe
ssoas
Neste caso, a pós-condição não fixa completamente
o estado final (nomeadamente o conjunto de
quartos escolhidos e o número de pessoas em cada
quarto), apenas fixa as condições a obedecer na
produção do estado final.
75Exemplo Sistema de Gestão de HotéisDefinição de
operação auxiliar para escolher quartos (1)
- context reserva Reserva-- Obtém o conjunto de
escolhas possíveis de quartos para uma
reserva.-- Cada escolha é um conjunto com um ou
mais quartos.-- As escolhas são efectuadas por
forma a não inviabilizar a satisfação das outras
reservas.-- São excluídas escolhas de quartos
nitidamente inferiores em relação ao objectivo de
maximizar-- a taxa de ocupação do hotel (aceitar
mas estadias/reservas posteriores). def
escolhasQuartosPossíveis Set(Set(Quarto))
let -- obtém o conjunto de quartos que não têm
estadias em curso no período da reserva
quartosLivres Set(Quarto) Quarto.allInstances-
gtselect(estadia_Quarto-gtforall(eq
DateInterval.disjoint(eq.data_de_entrada,
eq.data_de_saída,
reserva.data_de_entrada,
reserva.data_de_saída, true))), -- dado
um conjunto de quartos livres, obtém
(recursivamente) o conjunto dos seus subconjuntos
-- não vazios, excluindo subconjuntos
com quartos em excesso para satisfazer a reserva
subconjuntosQuartos(quartos
Set(Quarto)) Set(Set(Quarto)) if
quartos-gtisEmpty() then Set else let
este Quarto quartos-gtany(true),
semEste Set(Set(Quarto))
subconjuntosQuartos(quartos-gtexcluding(este)),
comEste Set(Set(Quarto))
SetSeteste-gtunion(semEste-gt
-gtselect(qq
qq-gtcollect(capacidade)-gtsum() lt
reserva.número_de_pessoas)
-gtcollectNested(qq
qq-gtincluding(este)) in
semEste-gtunion(comEste) endif, (continua)
só versão 2.0 collect não serve pois não
permite criar conjuntos de conjuntos (aplana tudo
num só conjunto)
76Exemplo Sistema de Gestão de HotéisDefinição de
operação auxiliar para escolher quartos (2)
- (continuação) -- verifica se uma escolha
de quartos livres é válida, isto é, se o número
de quartos é suficiente -- para satisfazer
esta reserva e se não inviabiliza a satisfação
das restantes reservas (usando -- a
operação auxiliar arranjaQuartos definida a
propósito da restrição R36)
escolhaVálida(quartos Set(Quarto)) Boolean
quartos-gtselect(capacidade)-gtsum() gt
reserva.número_de_pessoas and
arranjaQuartos(
Reserva.allInstances-gtexcluding(reserva)-gtselect(e
stado 'activa')-gtcollect( r
Tupleentrada
r.data_de_entrada, saída r.data_de_saída,
n_pessoas r.número_de_pessoas),
Estadia_Quarto.allInstances-gtcollect(
eq Tupleentrada eq.data_de_entrada,
saída eq.data_de_saída,
quarto eq.quarto)
-gtunion(quartos-gtcollect(q Tupleentrada
reserva.data_de_entrada,
saída reserva.data_de_saída, quarto
q.quarto))), -- obtém as escolhas de
quartos válidas para satisfazer a reserva, ainda
sem optimizar -- (para já apenas garante
que cada escolha de quartos não tem quartos em
excesso) escolhasVálidas
Set(Set(Quarto)) subconjuntosQuartos
(quartosLivres)-gtselect(s escolhaVálida(s)),
in escolhasVálidos-gtselect(s1 not
escolhasVálidas-gtexists(s2 Hotel.melhorEscolha(s
2, s1) )) -- ver definição de melhorEscolha
a seguir
77Exemplo Sistema de Gestão de HotéisDefinição de
operação auxiliar para comparar escolhas (1)
- context Hotel-- Compara duas escolhas de