Integração de modelos formais e semi

Propaganda
Integração de modelos formais e semiformais: o caso de UML e VDM++
João Pascoal Faria
Prof. Auxiliar, FEUP
Coimbra, Abril de 2004
Resumo

A linguagem de modelação visual UML é utilizada
correntemente para efeito de especificação, análise,
documentação e geração automática de partes da
implementação

Esta comunicação aborda o enriquecimento dos
modelos visuais em UML (semi-formais) através de:

especificação formal de restrições (por invariantes),
semântica de operações (por pré e pós-condições) e
concorrência, para obter modelos formais completos,
rigorosos e verificáveis

especificação do corpo algorítmico de operações através de
linguagens de acções de alto nível, para obter modelos
executáveis e traduzíveis
Resumo

Em torno de UML têm surgido linguagens que
permitem criar modelos formais - caso de OCL
(Object Constraint Language) - e modelos
executáveis e traduzíveis - caso de XTUML - mas
ainda não de forma perfeitamente integrada

Em contrapartida, VDM++ é uma linguagem de
especificação formal orientada por objectos, que é
baseada num standard maduro (VDM-SL), que
permite criar modelos formais executáveis e
traduzíveis, sendo suportada por ferramentas
(VDMTools) que permitem sincronizar com Rational
Rose, executar os modelos e gerar Java e C++
Índice

Introdução








Modelos visuais (semi-formais)
Dos modelos visuais aos modelos formais
Dos modelos visuais aos modelos executáveis
Dos modelos visuais aos modelos traduzíveis
Modelos visuais, formais, executáveis e traduzíveis
Breve introdução às técnicas de especificação formal
Apresentação de um caso de estudo
Conclusões
Modelos visuais (semi-formais)

Consensual e prática cada vez mais corrente:


modelação visual (semi-formal) com diagramas
UML durante as fases de análise 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


normalmente esqueletos de código, e não código
completamente funcional
Modelos visuais são muito úteis para
compreender e visualizar um sistema
Dos modelos visuais aos modelos
formais

É possível enriquecer os modelos visuais (semiformais) com especificações formais de
restrições (por invariantes)
 semântica de operações (por pré e pós-condições)
 aspectos de concorrência




Obtém-se um modelo formal que funciona como
especificação completa, rigorosa (sem ambiguidades
nem inconsistências) e verificável
Formal não quer dizer executável
Modelos formais são importantes porque a análise
detalhada e o rigor necessários à sua construção
permitem prevenir e detectar problemas mais cedo,
quando a sua correcção é menos dispendiosa
Dos modelos visuais aos modelos
executáveis



É possível enriquecer os modelos visuais com
especificações do corpo algorítmico de operações (e
actividades) em linguagens de acções de alto nível
Obtém-se um modelo executável (com a ajuda de
ferramentas)
Modelos executáveis são importantes para efeito de
teste e validação precoce do sistema (ainda na
forma de modelo)
Dos modelos visuais aos modelos
traduzíveis






É de esperar que os modelos executáveis sejam
também traduzíveis (com a ajuda de ferramentas)
para uma linguagem de implementação-alvo (Java,
C++, C#, ...)
Geração automática de código completamente
funcional e não só esqueletos de classes a partir de
modelos de alto nível
Particularidades das linguagens, tecnologias e
plataformas-alvo são embebidas nos geradores
Aumento de produtividade
Acabam-se os programadores?
Não! Apenas se programa a um nível mais abstracto,
e separa-se melhor o domínio do problema das
tecnologias de implementação!
Modelos visuais, formais,
executáveis e traduzíveis



Que solução integrada?
Em torno de UML têm surgido linguagens que
permitem criar modelos formais - caso de OCL
(Object Constraint Language) - e modelos
executáveis e traduzíveis - caso de XTUML - mas
ainda não de forma perfeitamente integrada
Em contrapartida, o VDM++ é uma linguagem de
especificação formal orientada por objectos que
permite criar modelos formais, executáveis e
traduzíveis, sendo suportada por ferramentas
(VDMTools) que permitem sincronizar com Rational
Rose, executar os modelos e gerar código Java e
C++
Índice


Introdução
Breve introdução às técnicas de especificação formal







O que são métodos formais?
Especificação formal baseada em modelos
Especificação formal baseada em propriedades
Especificação formal baseada em comportamento
Conclusões das técnicas de especificação formal
Apresentação de um caso de estudo
Conclusões
O que são métodos formais?


Método Formal =
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
especificação/
modelação Especificação
/Modelo formal
síntese
análise
Implementação
Classificação de linguagens de
especificação formal

Baseadas em Modelos




Baseadas em Propriedades





Sistema especificado em termos de um modelo de estado, que é
construído usando construções matemáticas como conjuntos e
sequências, e de operações sobre esse estado
VDM, Z, VDM++, Object Z, ...
Particularmente adequadas para especificar sistemas de
informação
Sistema especificado em termos das suas operações e das
relações entre essas operações
Algébricas – definem operações através de uma colecção de
relações de equivalência (axiomas equacionais) - Obj, Larch, ...
Axiomáticas – definem operações através de predicados da lógica
de primeira ordem - Larch, ...
Particularmente adequadas para especificar tipos de dados
abstractos
Baseadas no Comportamento


Sistema especificado em termos de sequências possíveis de
estados em vez de tipos de dados - Petri Nets, CSP, ...
Particularmente adequadas para especificar sistemas concorrentes
e distribuídos
Exemplo de especificação formal
baseada em modelos (VDM++)
class Stack
instance variables
elems : seq of int := [];
operations
Stack () ==
elems := []
ext wr elems
post elems = [];
Push (i: int) ==
elems := [i] ^ elems
ext wr elems
post stack = [i] ^ ~elems;
Pop () ==
elems := tl elems
ext wr elems
pre elems <> []
post elems = tl ~elems;
Top () res: int ==
return hd elems
pre elems <> []
post res = hd elems;
end Stack
Exemplo de especificação formal
baseada em modelos (VDM++)
instance variables
elems : seq of int := [];
Escolhe-se uma representação (modelo) do
estado baseada em construções matemáticas
como conjuntos e sequências
Se fosse necessário, podiam-se especificar
invariantes (restrições nos estados válidos).
Exemplo: inv len elems <= 1000;
Exemplo de especificação formal
baseada em modelos (VDM++)
Pop () ==
elems := tl elems
Corpo algorítmico (executável!)
ext wr elems
Variáveis de instância cujo valor pode ser
alterado pela operação
pre elems <> []
Pré-condição: condição nos argumentos de
chamada e estado inicial do objecto a que
tem de obedecer qualquer chamada válida.
especificam semântica
post elems = tl ~elems;
tail
Valor antigo da
variável de instância
Pós-condição: relaciona resultado da
operação e estado final do objecto com
argumentos de chamada e estado inicial
Exemplo de especificação formal
baseada em propriedades (OBJ)
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;
Exemplo de especificação formal
baseada em propriedades (OBJ)

Mais abstracta: especifica semântica de operações por
axiomas, sem necessidade de escolher uma representação de
dados/estado interna (cf. noção de ADT)

Mas é mais difícil saber quando é que a especificação está
completa!


Uma stack é sempre representada por uma expressão de
construção
push(3, push(2, push(1, newstack)))
Axiomas permitem simplificar/avaliar expressões
top(pop(push(2, push(1, newstack)))) =
= top(push(1, newstack))
=1
Exemplo de especificação formal
baseada em comportamento (CSP)
envia a mensagem "EmptyStackExpression"
pelo canal "top" e depois comporta-se como
EmptyStack
Stack = EmptyStack
processos
EmptyStack =
top! EmptyStackException  EmptyStack 
pop! EmptyStackException  EmptyStack 
push? x  OneElemStack(x); EmptyStack
"ou"
Mais operacional!
pop
top
push
OneElemStack(x) =
top! x  OneElemStack(x) 
pop! x  Skip 
push? y  OneElemStack(y); OneElemStack(x)
recebe um valor (mensagem) para x pelo
canal "push" e depois comporta-se como a
composição sequencial dos processos
OneElemStack(x) e EmptyStack
Técnicas de especificação formal:
conclusões e reflexões



As linguagens de especificação formal baseadas em
modelos e orientadas por objectos (como VDM++
ou Object-Z) são as que se integram mais
naturalmente com UML
Uma vantagem de VDM++ sobre Object-Z é que
permite obter mais facilmente modelos executáveis e
permite especificar mais naturalmente algoritmos
A linguagem OCL baseia-se (e enquadra-se) neste
tipo de linguagens, sem ter ainda atingido o mesmo
grau de maturidade
Índice



Objectivos e motivação
Breve introdução às técnicas de especificação formal
Apresentação de um caso de estudo (agenda corporativa)












Caracterização sumária do sistema
Lista de requisitos
Modelo de casos de uso em UML
Modelo de domínio em UML
Tradução de UML para VDM++
Definição de tipos de dados em VDM++
Definição de classes em VDM++
Especificação de aspectos de concorrência em VDM++
Teste da especificação
Documentação
Geração de código
Conclusões
Caracterização sumária do sistema

Agenda "corporativa"

Cada recurso (pessoa, espaço ou equipamento) tem
uma agenda associada (date book), com
compromissos (appointments) e disponibilidades
(slots)

Um compromisso pode envolver vários recursos e
pode ocupar um conjunto de intervalos de tempo

Os compromissos marcados por terceiros estão
sujeitos às disponibilidade manifestadas

O sistema deve ajudar o utilizador a marcar
compromissos, mostrando hipóteses de marcação

Exemplos de aplicações: marcação de consultas,
marcação de reuniões, reserva de equipamentos,
etc.
Lista de requisitos (1)
1.
2.
3.
4.
5.
6.
7.
8.
O sistema deve permitir gerir a marcação de compromissos
envolvendo vários recursos numa organização.
Os recursos englobam pessoas, espaços e equipamentos
Cada recurso tem uma agenda associada.
Cada agenda tem um dono, que é uma pessoa da
organização.
O dono da agenda de uma pessoa é a própria pessoa
Uma agenda (datebook) tem elementos de dois tipos:
compromissos (appointments) e disponibilidades (slots).
Um compromisso é de um certo tipo (reunião, aula, etc.),
envolve um ou mais recursos e ocupa um intervalo de tempo
ou um conjunto de intervalos de tempo, com resolução ao
minuto.
Deve ficar registado quem marcou um compromisso (autor do
compromisso).
Lista de requisitos (2)
9.
10.
11.
12.
13.
Um recurso não pode ter dois compromissos ao mesmo
tempo.
Uma disponibilidade refere-se a um recurso, um tipo de
compromisso e um intervalo de tempo ou um conjunto de
intervalos de tempo.
Uma pessoa só pode marcar um compromisso numa agenda
de que não é dona, dentro das disponibilidades definidas pelo
dono da agenda. Só o dono da agenda pode marcar
compromissos sem verificação de disponibilidades.
As agendas podem ser consultadas por todas as pessoas da
organização.
Os compromissos podem ser públicos ou privados. Um
compromisso privado só pode ser consultado pelo autor do
compromisso, pelas pessoas envolvidas no compromisso e
pelos donos das agendas dos recursos envolvidos.
Lista de requisitos (3)
14.
15.
O sistema deve ajudar o utilizador a marcar compromissos da
seguinte forma: o utilizador indica o tipo de compromisso a
marcar (exemplo: reunião), os recursos envolvidos, a duração
do compromisso e restrições temporais para a marcação do
compromisso; o sistema deve fornecer uma lista de
hipóteses de marcação; cada hipótese mostra um intervalo de
tempo dentro do qual é possível marcar o compromisso em
todos os recursos (porque têm declarada disponibilidade para
o tipo de compromisso especificado e não têm marcados
compromissos de qualquer tipo).
Compete ao administrador do sistema registar os recursos da
organização (criando automaticamente as respectivas
agendas) e definir os tipos de compromissos possíveis.
Modelo de casos de uso em UML
(funcionalidades e perfis de utilizadores)
Agenda Corporativa
RegisterResourcesWithDatebooks
SystemAdministr
ator
CreateApointmentTypes
actor
generalização
DatebookOwner
fronteira
do
sistema
CreateSlotsForApointments
Can't create apointments in datebooks
not owned by the user outside the
slots previously defined
MakePrivateApointment
<<extend>>
MakeApointment
EmployeeActor
SuggestSlots
MakePublicApointment
Can't see the details of private apointments in
which he/she does not participate and was not
the author and is not the owner of the datebook
caso de uso
(use case)
QueryDatebook
restrição
Modelo de domínio em UML (1)
(modelação do estado do sistema)
classe
Faltam os
invariantes ...
atributo
agregação
multiplicidade
generalização
associação
role name
para facilitar mapeamento para VDM++,
associação bidireccional é representada
por duas associações unidireccionais
tipos de dados e
valores por omissão
definidos em VDM++
Modelo de domínio em UML (2)
(modelação das operações sobre o estado)
Agora com as operações mais
importantes (assinaturas
omitidas por falta de espaço)
Principais transacções
e consultas
Falta a semântica
das operações ...
Tradução de UML para VDM++ (1)
Tradução de UML para VDM++ (2)
Definição de tipos de dados e
classes em VDM++

Em VDM++, tipos e classes são conceitos
diferentes






Tipos são usados para representar tipos de
valores de atributos (tipos de dados)
Classes são usadas para representar o estado do
sistema
Instâncias de um tipo são valores puros
Instâncias de uma classe são objectos
Definição de um tipo pode ser acompanhada de
definição de valores (constantes) e funções (cf.
paradigma funcional)
Definição de uma classe compreende a definição
de variáveis de instância e operações (cf.
paradigma de orientação por objectos)
Definição de tipos de dados em
VDM++ (1)

Tipos de dados a definir neste caso (*):
Tipo
Descrição
StringT
cadeia de um ou mais caracteres
Date
data representada pelo número de dias decorridos desde
uma data base, útil para processamento interno
UserDate
data representada por uma combinação de dia,
mês e ano
Time
instante de tempo, representado pelo número de minutos
decorridos desde as 0 horas da data base
UserTime
instante de tempo, representado por uma
combinação de minutos, horas, dia, mês e ano
TimeInterval
intervalo entre dois instantes de tempo, fechado à
esquerda e aberto à direita, representado por 2
valores do tipo Time
Duration
uma duração em minutos
(*) Normalmente estes tipos de dados estariam definidos numa biblioteca
Definição de tipos de dados em
VDM++ (2)

Tipos de dados a definir neste caso (cont.)
Tipo
Descrição
UserTimeInterval
intervalo entre dois instantes de tempo, fechado à
esquerda e aberto à direita, representado por um
par de valores do tipo UserTime
TimeRegion
região de tempo (conjunto de intervalos de tempo)
representada por um conjunto de intervalos de
tempo unitários (com 1 min de duração),
representados pelos seus inícios (valores do tipo
Time)
representação abstracta pouco eficiente, mas que
permite efectuar operações com regiões de tempo
usando directamente os operadores de conjuntos
(reunião, intersecção e diferença), simplificando a
especificação
ResourceType
tipo enumerado que admite os valores
<EMPLOYEE>, <EQUIPMENT> ou <SPACE>
VisibilityType
tipo enumerado que admite os valores <PUBLIC> ou
<PRIVATE>
Exemplo de definição de tipos de
dados em VDM++
types
public UserDate :: year : nat1
definição de tipo de record
month: nat1
day : nat1
invariante
inv d == d.month <= 12 and d.year >= Year0
and d.day <= DaysOfMonth(d.year, d.month);
constantes
values
construção de record
private Year0 : nat1 = 1900;
private UserDate0 : UserDate = mk_UserDate(Year0,1,1);
functions
private static IsLeapYear(year: nat1) res : bool ==
year mod 4 = 0 and year mod 100 <> 0 or year mod 400 = 0;
private static DaysOfMonth(year, month: nat1) res : nat ==
(cases month :
1, 3, 5, 7, 8, 10, 12 -> 31,
4, 6, 9, 11 -> 30,
2 -> if IsLeapYear(year) then 29 else 28
pré-condição end)
pre month <= 12;
(...)
Definição de classes em VDM++



Em VDM++, as classes são usadas para modelar o
estado do sistema e as operações de consulta e
alteração de estado
É possível gerar o esqueleto das classes em VDM++
a partir de um diagrama de classes UML (usando as
ferramentas Rational Rose e VDMTools), e vice-versa
VDM++ permite completar a especificação das
classes com invariantes de estado, pré e póscondições das operações e corpo algorítmico das
operações
Exemplo de definição de classe em
VDM++ (variáveis de instância)
class Company
instance variables
só para facilitar testes
public name : StringT;
public apointmentTypes : set of ApointmentType := {};
-- Must be initialized because of invariant.
conjunto de referências para objectos
public resources : set of Resource := {};
-- Must be initialized because of invariant.
...
public apointments : set of Apointment := {};
-- Because there is a many to many relationship between
-- datebooks and apointments, they "belong" to the company
-- and are referenced by datebooks (and vice versa)
Exemplo de definição de classe em
VDM++ (invariantes)
...
-- Key constraints
-- uniqueness of Resource.rid
inv forall r1, r2 in set resources &
r1<> r2 => r1.rid <> r2.rid;
...
-- Limitation: not checked if r.rid is changed
-- Referential integrity constraints
-- referential integrity of Apointment.type
inv forall a in set apointments &
a.type in set apointmentTypes;
...
...
-- Limitation: not checked if a.type is changed
-- Generic constraints
Exemplo de definição de classe em
VDM++ (operações de alteração)
operations
public AddApointmentType(desc: StringT)
res : ApointmentType ==
(
dcl t: ApointmentType := new ApointmentType(desc);
apointmentTypes := apointmentTypes union {t};
return t
variável de instância que a operação pode alterar
)
ext wr apointmentTypes
pre desc not in set {at.description | at in set apointmentTypes}
post apointmentTypes = apointmentTypes~ union {res}
and res.description = desc;
...
pré-condição implicada por invariante
(pode-se efectuar verificação formal)
"~" designa valor
antigo da variável
Exemplo de definição de classe em
VDM++ (operações de consulta)
public SuggestSlots(type: ApointmentType, rs: set of Resource,
duration: TimeDurationT, within: TimeRegionT)
res: set of UserTimeIntervalT ==
return
{TimeIntervalToUserTimeInterval(ti) |
ti in set
TimeRegionToTimeIntervals(
dinter {
let r_slots = r.GetDatebook().GetSlotsOfType(type),
r_apoints = dunion {a.when | a in set
r.GetDatebook().GetApointments()}
in (within inter r_slots \ r_apoints)
| r in set rs
{f(x) | x in set ...} – define conjunto
}
em compreensão
)
dinter {...} – intersecção de elementos
& Duration(ti)>=duration
de conjunto
};
dunion {...} – união de elementos
& - tal que
de conjunto
Especificação de aspectos de
concorrência

Para além de suportar a definição de objectos
activos (donos de threads), a linguagem VDM++
permite especificar declarativamente condições de
sincronização



sync per nome_operação => condição_de_guarda
a execução da operação fica suspensa até a condição de
guardar se tornar verdadeira
a condição de guarda pode basear-se no estado do objecto
e em contadores de execuções de operações (finalizadas,
em espera, etc.)
Teste da especificação



Especificação pode ser testada interactivamente
(com interpretador de VDM++) ou com base em
casos de teste pré-definidos
Pode-se activar a verificação automática de
invariantes, pré-condições e pós-condições
Um caso de teste tc1 é especificado por:




ficheiro tc1.arg – com o comando a executar pelo
interpretador
ficheiro tc1.arg.exp – com o resultado esperado da
execução do comando
É produzida informação dos testes que sucederam e
dos testes que falharam
É produzida informação de cobertura dos testes


o pretty printer "pinta" as partes da especificação que
foram de facto executadas
são geradas tabelas com percentagem de cobertura e
número de chamadas de cada operação e função
Documentação


Cada classe VDM++ é especificada num ficheiro em
RTF, usando estilos pré-definidos para assinalar as
partes de VDM++ (cf. programação literária)
Pretty printer formata as partes de VDM++ e gera
versão mais bonita

Pode-se juntar tudo num documento final com paste
link
Geração de código

Ferramentas geram código completamente funcional
em Java e C++

Incluindo código para verificar pré-condições e póscondições

Facilmente legível no caso de Java

Código geralmente pouco eficiente tanto em Java
como em C++

Principal dificuldade tem a ver com utilizar
bibliotecas pré-existentes da linguagem alvo desde a
fase de especificação
Limitações e melhoramentos a
VDM++

Verificar invariantes quando muda o estado de
objectos referenciados


Definição de transacções permitindo diferir a
verificação de invariantes para o fim das transacções


questão de conveniência, para suportar restrições interobjecto
questão de necessidade, para suportar restrições interobjecto
Na pós-condição de uma operação, poder referir
mensagens enviadas (chamada de operações ou
envio de sinais)



para poder especificar o comportamento de operações que
sinalizam eventos (exemplo: TextBox.setText)
OCL já permite referir mensagens enviadas, ainda que com
limitações
problema: em geral, como se deve especificar o
comportamento de operações envolvendo callbacks?
Índice




Introdução
Breve introdução às técnicas de especificação formal
Apresentação de um caso de estudo
Conclusões
Conclusões

A integração de UML com uma linguagem como VDM++
permite enriquecer os modelos visuais criados em UML com:








especificação formal de restrições de estado e semântica de
operações
especificação do corpo algorítmico de operações a um nível de
abstracção elevado
especificação declarativa de aspectos de concorrência e
sincronização
Obtém-se rapidamente uma especificação completa (sintaxe +
semântica) e rigorosa do sistema a desenvolver a um nível de
abstracção elevado
Obtém-se rapidamente um modelo que pode ser executado,
testado e validado
Suporta-se a geração automática de código completamente
funcional
Facilita-se a verificação de conformidade da implementação
com a especificação
Ganha-se em qualidade e produtividade (desde que se consiga
evitar a duplicação de esforços)
Mais informação

www.ifad.dk/ - sobre VDM++ e VDMTools

www.projtech.com – sobre UML executável

www.uml.org – sobre UML, OCL, etc.

www.fe.up.pt/~jpf – mais detalhes sobre o caso de
estudo apresentado
Download