Jpf@fe.up.pt www.fe.up.pt/~jpf Complementos de Engenharia de Software A linguagem VDM++ (1ª parte - Estrutura geral duma especificação; importação de.

Slides:



Advertisements
Apresentações semelhantes
Integração de modelos formais e semi- formais: o caso de UML e VDM++
Advertisements

A Linguagem Formal de Especificação VDM-SL
PROGRAMANDO EM JAVA Dilvan Moreira (baseado no livro Big Java)
PROGRAMAÇÃO ORIENTADA A OBJETOS EM C++ Professor: Dilvan Moreira.
Linguagens de Programação Conceitos e Técnicas Valores e Tipos de Dados Prof. Isabel Cafezeiro
Lógica de Programação.  Um algoritmo é um conjunto de instruções, dispostas em um sequência lógica, que levam à resolução de um problema.  Um algoritmo.
Linguagens de Programação Conceitos e Técnicas Comandos Prof. Isabel Cafezeiro
Linguagens de Programação Conceitos e Técnicas Expressões Prof. Isabel Cafezeiro
Classes Objetos Atributos Métodos Coletor de Lixo (Garbage Collector ) Confraria do Java Nivelamento. Caroline, Marcelo e Luiz 12/05/2007.
Algoritmos e Programação utilizando Visualg
Estruturas de Dados Aula 2: Estruturas Estáticas
Métodos Formais em Engenharia de Software Especificação Baseada em Modelos em VDM++ (5ª parte) João Pascoal Faria
Álgebra Relacional Vania Bogorny.
Métodos Formais em Engenharia de Software Especificação Baseada em Modelos em VDM++ (2ª parte) João Pascoal Faria
Métodos Formais em Engenharia de Software Utilização da Ferramenta VDMTools Lite João Pascoal Faria
Programação Funcional
(baseado em slides de ex-alunos)
EGP, CPC, 2004/05 Manipulação de strings, colecções e ficheiros em Visual Basic .Net João Pascoal Faria Dezembro de 2004.
INF1007: Programação 2 2 – Alocação Dinâmica
Introdução OO.
Complementos de Engenharia de Software A linguagem VDM++ (2ª parte - Operadores e expressões; definição de invariantes,
Estruturas de Decisão.
Métodos Formais em Engenharia de Software 3c
Métodos Formais em Engenharia de Software Especificação Baseada em Modelos em VDM++ (4ª parte) João Pascoal Faria
Métodos Formais em Engenharia de Software Utilização da Ferramenta VDMTools Lite João Pascoal Faria
Teste e Qualidade de Software Teste baseado em modelos – exemplo da biblioteca João Pascoal Faria
Complementos de Engenharia de Software A linguagem VDM++ (4ª parte – Funções avançadas) João Pascoal Faria
Métodos Formais em Engenharia de Software Especificação Algébrica em CafeOBJ (3ª parte) João Pascoal Faria
TQS - Teste e Qualidade de Software (Software Testing and Quality) Introdução a testes unitários automatizados com JUnit.
Módulo I Capítulo 2: IDE e Variáveis
Introdução Java.
PROGRAMAÇÃO ORIENTADA A OBJETO - JAVA
Linguagem C Para programadores Python
3.1 Classes e Objetos Em um programa orientado a objetos normalmente existem vários objetos de um mesmo tipo. Por exemplo, um programa de controle de.
TQS - Teste e Qualidade de Software (Software Testing and Quality) Caso de estudo: Problema da procura duma string num.
Aula 4 Estruturas.
Prof. Wellington Franco
FUNDAMENTO DE PROGRAMAÇÃO
Programação Lógica: PROLOG
POO - Classes Dilvan Moreira.
Estrutura de dados Pilhas e filas
Singleton e Template Method
Programador/a de Informática
FUNDAMENTO DE PROGRAMAÇÃO
Criação e manipulação de objetos
Algoritmos e Técnicas CEFET/RN.
PROGRAMAÇÃO I UNIDADE 3.
Complementos de Engenharia de Software A linguagem VDM++ (3ª parte – instruções; aplicação à descrição de algoritmos e.
Modelagem de Banco de Dados através do ERwin

TQS - Teste e Qualidade de Software (Software Testing and Quality) Teste baseado em modelos (visuais e formais): exemplo.
Tecnologia para Internet - II
TQS - Teste e Qualidade de Software (Software Testing and Quality) Discussão de Exercícios de Teste Baseado em Modelos.
Aula 22 Modularização 22/10/08.
3.2 Sobrecarga de Métodos (Overloading)
Rosemary Silveira Filgueiras Melo
3.1.7 Variáveis de Classe e Instância
Programação Orientada a Objetos
Programação Funcional
DHD – Desenvolvimento em Hardware
Professora Roberta Bonamichi Guidi Garcia
Linguagem de Programação I
Curso básico de PHP. 1 Vantagens: Gratuito Multiplataforma Estável Rapidez Comunicação.
Tipos Primitivos de Dados
Sistemas de Tipo Paradigmas de Linguagens Computacionais
Programação Funcional
RESULUÇÃO DOS EXERCÍCIOS E
Introdução ao Modelo Relacional Capítulo 2 - Database System Concepts – 6ª. Ed - Silberschatz et al Curso: Ciência da Computação Disciplina: Banco de Dados.
Programação de Computadores II
Aula 2 Professores: Conteúdo: Dante Corbucci Filho
Transcrição da apresentação:

jpf@fe.up.pt www.fe.up.pt/~jpf Complementos de Engenharia de Software A linguagem VDM++ (1ª parte - Estrutura geral duma especificação; importação de diagramas de classes UML) João Pascoal Faria jpf@fe.up.pt www.fe.up.pt/~jpf

Estrutura geral duma especificação

Características gerais de VDM++ Linguagem de especificação formal baseada em modelos orientada por objectos Permite criar modelos formais, executáveis e traduzíveis Combina dois paradigmas Paradigma funcional, com tipos, funções e valores (instâncias de tipos) Paradigma de orientação por objectos, com classes, variáveis de instância, operações e objectos (instâncias de classes) Suportada por ferramentas VDMTools que permitem: Executar uma especificação escrita em VDM+ Testar a especificação e analisar a cobertura dos testes Sincronizar com Rational Rose (integração com modelação visual em UML) Gerar código Java e C++ Permite duas notações: ASCII ou símbolos matemáticos

Estrutura de uma especificação em VDM++ class <class-name> end <class-name> instance variables ... Paradigma OO Internal object state types values functions operations ... Paradigma funcional Definitions Paradigma OO thread ... Dynamic behaviour sync ... Synchronization control

Classes Uma especificação em VDM++ é organizada em classes Classes são “tipos referência” (reference types), como em todas as linguagens OO Instâncias são objectos mutáveis acessíveis por uma referência Variável do tipo C (nome de uma classe) contém uma referência para o objecto com os dados, e não os próprios dados Comparação e atribuição operam com as referências Na nossa abordagem, vão ser usadas para modelar o estado do sistema (como em UML) Estado é representado pelo conjunto de objectos existentes e pelos valores das variáveis de instância

Variáveis de instância Correspondem a atributos em UML, ou campos em Java e C# Podem ser private (por omissão), public ou protected Podem ser static (estáticas) Declaradas na secção “instance variables” com a sintaxe: [private | public | protected] [static] nome : tipo [ := valor_inicial]; A secção “instance variables” também pode conter definições de invariantes (inv), que restringem os valores válidos das variáveis de instância A tratar mais tarde

(variáveis de instância) Operações Correspondem a operações em UML e métodos em Java ou C# Podem ser private (por omissão), public ou protected Podem ser static Podem consultar ou modificar o estado de objectos (representado por variáveis de instância) ou o estado global do sistema (representado por variáveis estáticas) Podem ter corpo (para definição explícita, paradigma imperativo), pré-condição e pós-condição (para definição implícita) Construtores são operações com o mesmo nome da classe Operação parâmetros de entrada (argumentos) parâmetros de saída (resultado) Estado (variáveis de instância)

Operações - definição argumento tipo resultado Estilo 1: op(a: A, b: B, …, z: Z) r: R == bodystmt ext rd instvarx, instvary, … wr instvarz, instvarw, … pre preexpr(a, b, …, instvar1, instvar2, …) post postexpr(a, b, …,r, instvar1, instvar2, …, instvar1~, instvar2~, …) ; Estilo 2: op: A * B * … ==> R op(a,b,…) == bodystmt pre preexpr(a, b,…, instvar1, instvar2, …) post postexpr(a, b,…,RESULT, instvar1, instvar2, …, instvar1~, instvar2~, …) ; tipo omitir quando não retorna nada quando não há argumentos ou resultados, escrever () nome pré-definido para o valor retornado

Operações – partes da definição Corpo algorítmico (bodysmt) - instrução ou bloco de instruções entre ( ) Paradigma imperativo: pode ter atribuições, declarar variáveis, etc. Adequado para descrever algoritmos No caso de operação abstracta, escrever “is subclass responsibility” No caso de não estar ainda definido, escrever “is not yet specified”, ou omitir a parte “== bodystmt” no estilo 1 Pré-condição (pre) - expressão booleana nos valores dos argumentos e das variáveis de instância, que se deve verificar na chamada da operação Pode ser omitida (mesmo que true) Pós-condição (post) - expressão booleana nos valores dos argumentos, resultado, valores iniciais das variáveis de instância (com sufixo “~”) e valores finais das variáveis de instância (sem “~”), que se deve verificar no retorno da operação Cláusula “ext” (externals) - lista as variáveis de instâncias que são lidas (rd) e actualizadas (wr) no corpo da operação Obrigatório indicar no estilo 1, quando se indica a pós-condição

Exemplo de definição duma classe class FStack instance variables private elements : seq of int := []; private capacity: nat; inv len elements <= capacity; operations public FStack(c : nat) res: FStack == (elements := []; capacity := c) ext wr elements, capacity post elements = [] and capacity = c ; public Push(x: int) == elements := [x] ^ elements ext wr elements pre len elements < capacity post elements = [x] ^ elements~ ; public Pop() == elements := tl elements pre elements <> [] post elements = tl elements~ ; public Top() res: int == return hd elements ext rd elements post res = hd elements; end FStack

Tipos Tipos são “tipos valor” (value types) Sudividem-se em: Instâncias são valores puros imutáveis Comparação e atribuição operam com os próprios valores Variável do tipo T (nome de um tipo) tem os próprios dados Sudividem-se em: Tipos básicos - bool, nat, real, char, ... Tipos construídos (colecções e outros) – set of T, seq of T, map T1 to T2, ... Nomes para novos tipos podem ser definidos dentro de classes, na secção “types” Definição de um novo tipo pode ser complementada com invariante, para restringir as instâncias válidas A estudar mais tarde Na nossa abordagem, vão ser usados para modelar tipos de valores de atributos (tipos de dados)

<identificador> Tipos básicos Símbolo Descrição Exemplos de valores bool Booleano true, false nat1 Número natural não nulo 1, 2, 3, … nat Número natural 0, 1, 2, … int Número inteiro …, -2, -1, 0, 1, … rat real Número racional Número real (mesmo que “rat”, pois só números racionais podem ser representados no computador) -12.78, 0, 3, 16.23 char Caracter 'a', 'b', '1', '2', '+', '-', … token Encapsula um valor de qualquer tipo (argumento de mk_token pode ser qualquer valor), útil quando se sabe pouco sobre o tipo mk_token(1) <identificador> Quotes (nomes literais, usados normalmente para definir tipos enumerados) <Branco>, <Preto>

Tipos construídos - colecções Descrição Sintaxe Exemplo de instância Conjunto de elementos do tipo A set of A {1 , 2} Sequência de elementos do tipo A seq of A [1, 2, 1] Sequência não vazia seq1 of A Mapeamento de elementos do tipo A para elementos do tipo B (função finita, conjunto de pares chave-valor) map A to B { 0 |-> false, 1 |-> true } Mapeamento injectivo (a chaves diferentes correspondem valores diferentes) inmap A to B Cada elemento de um mapeamento é designado maplet e representa-se em ASCII na forma chave |-> valor Não existem bags (conjuntos admitindo repetidos) Não existem arranjos (sequências sem repetidos)

Outros tipos construídos Descrição Sintaxe Exemplo de instância Produto dos tipos A, B, … (instâncias são tuplos) A * B * ... mk_(0, false) Record T com campos a, b, etc. de tipos A, B, etc. T :: a : A b : B ... mk_T(0, false) União dos tipos A, B, … (tipo A ou tipo B ou …) A | B | ... Tipo opcional (admite nil) [A] Definições alternativas de records: T :: a : A b :- B -- campo com “:-” é ignorado na comparação de records T :: A B -- campos anónimos

Strings Não está pré-definido o tipo string, mas pode ser facilmente definido como sequência de caracteres (seq of char) Todas as operações sobre sequências podem ser usadas com strings Strings literais podem ser indicadas com aspas "eu sou" é equivalente a ['e', 'u', ' ', 's', 'o', 'u']

Exemplo de definição de tipos class Pessoa types public String = seq of char; public Date :: year : nat month: nat day : nat; public Sexo = <Masculino> | <Feminino>; instance variables private nome: String; private sexo: Sexo; private dataNascimento: Date; … end Pessoa sequência record tipo enumerado (definido com “union” e “quote”) atributo tipo de dados

O tipo referência Referência para objecto de classe Permite modelar associações entre classes Exemplo: class Pessoa instance variables private conjuge : [Pessoa]; private filhos : set of Pessoa; … Guarda referência para um objecto da classe Pessoa, ou nil Guarda conjunto de 0 ou mais referências para objectos da classe Pessoa

Constantes simbólicas Constantes simbólicas são constantes às quais é dado um nome, por forma a tornar a especificação mais legível e fácil de alterar São declaradas na secção values com a sintaxe: [private | public | protected] nome [: tipo] = valor; Exemplo: values public PI = 3.1417;

(variáveis de instância) Funções São funções puras, sem efeitos laterais, que convertem entradas em saídas Não têm acesso (seja para leitura, seja para alteração) ao estado do sistema representado pelas variáveis de instância São definidas na secção functions Podem ser private (por omissão), public ou protected Podem ser static (caso normal) Podem ter corpo (para definição explícita, paradigma funcional), pré-condição e pós-condição (para definição implícita) parâmetros de entrada (argumentos) Função parâmetros de saída (resultado) Estado (variáveis de instância)

Funções - definição Estilo 1: f(a:A, b:B, …, z:Z) r1:R1, …, rn:Rn == bodyexpr pre preexpr(a,b,…,z) post postexpr(a,b,…,z,r1,…,rn) ; Estilo 2: f: A * B * … * Z -> R1 * R2 * … * Rn f(a,b,…,z) == bodyexpr pre preexpr(a,b,…,z) post postexpr(a,b,…,z,RESULT) ; podem existir vários parâmetros de saída (valor simples ou tuplo)

Funções – partes da definição Corpo – definição explícita do(s) resultado(s) da função por uma expressão sem efeitos laterais Paradigma funcional Pode-se omitir - escrever “is not yet specified”, ou omitir “== bodyexpr” no estilo 1 Pré-condição (pre) - expressão booleana nos valores dos argumentos que se deve verificar na chamada da função (restrição aos valores dos argumentos) Permite definir funções parciais (que não estão definidas para alguns valores dos argumentos) Pode ser omitida (mesmo que true) A pré-condição de uma função f é também uma função que pode ser invocada explicitamente com o nome pre_f Pós-condição (post) – expressão booleana que relaciona o resultado da função com os argumentos (restrição a que deve obedecer o resultado) Permite definir a função de forma implícita A pós-condição de uma função f é também uma função que pode ser invocada explicitamente com o nome post_f

Funções - exemplos Definição explícita, função total public static IsLeapYear(year: nat1) res : bool == year mod 4 = 0 and year mod 100 <> 0 or year mod 400 = 0; Definição implícita (não executável), função parcial public static sqrt(x: real) res : real pre x > 0 post res * res = x and res >= 0; Combinação de definição implícita com definição explícita public static sort(s: seq of nat) res: seq of nat == cases s: [] -> [], [x] -> [x], [x, y] -> if x < y then [x, y] else [y, x], - ^ [x] ^ - -> quicksort ([y | y in set elems s & y<x]) ^ [x] ^ quicksort ([y | y in set elems s & y>x]) end post IsSorted(res) and IsPermutation(res, s);

Herança Uma classe pode ter várias super-classes Sintaxe: class C1 is subclass of C2, C3 … end C1 Semântica habitual

Aspectos sintácticos Comentários são indicados com “--” e vão até ao fim da linha Minúsculas e maiúsculas são distinguidas (a linguagem é case sensitive) Acentos são suportados, mas apenas parcialmente, pelo que é melhor não usar Para referir um membro (variável de instância ou operação) de um objecto, usa-se a notação habitual “objecto.membro” Para referir um membro estático (variável, operação ou função estática), tipo ou constante definido noutra classe, usa-se a notação “classe`membro”, e não “classe.membro” Usa-se “nil”, e não “null” Usa-se “self”, e não “this”

Correspondência entre a notação matemática e a notação ASCII

Importação de diagramas de classes UML

Mapeamento de associações unidireccionais e generalizações * q : Q 1 r4 r6 r7 C4 C6 {ordered} 0..1 0..1 * C7 class C1 is subclass of C2 instance variables r3 : C3; r4 : [C4]; r5 : set of C5; r6 : seq of C6; r7 : map Q to C7; end C1 seq1 se for para 1..* inmap se for de 0..1

Cuidados a ter na elaboração do diagrama de classes em UML Nomes de classes, atributos e operações devem ser identificadores válidos, sem espaços Acentos e cedilhas funcionam mal em nomes de classes Indicar sentido de navegação nas associações Associações são mapeadas para referências entre objectos (como aconteceria numa linguagem de programação OO) O sentido da navegação vai indicar que objectos guardam referências para que objectos Se for necessário navegar nos dois sentidos (guardar referências nos dois sentidos), criar duas associações navegáveis em sentidos opostos Indicar role names nos extremos navegáveis das associações O role name vai ser usado para navegar para o objecto ou conjunto de objectos relacionados Os nomes dos parâmetros das operações de alteração de valores de atributos devem ser diferentes dos nomes dos atributos Senão, no VDM++ não se consegue desambiguar a atribuição Usar tipos de dados da linguagem alvo (neste caso, VDM++) Atender a que em VDM++ (tal como acontece nas linguagens de programação OO), não existe acesso automático ao conjunto de instâncias de uma classe (como acontece em OCL)

Exemplo: Registo Civil Diagrama de classes Construtor Operações de alteração Operações de consulta (Desenhado em Rational Rose) (Pode ser importado automaticamente para VDM++)

Exemplo: Registo Civil Diagrama de estados (estado civil) (Desenhado em Rational Rose) Não é importado automaticamente para VDM++, mas permite desde já definir os valores possíveis do estado civil, e mais tarde vai ser importante para a definição das operações

Exemplo: Registo Civil Restrições adicionais R1 – O pai tem de ser do sexo masculino R2 – A mãe tem de ser do sexo feminino R3 – Os cônjuges têm de ser de sexos opostos R4 – O falecimento tem de ser posterior ao nascimento R5 – Os pais têm de nascer antes dos filhos Vão mais tarde originar invariantes

Importação de Rational Rose para VDM++

Resultado da importação para VDM++ (1) Ficheiro “Pessoa.rtf” class Pessoa instance variables private nome : String; private sexo : Sexo; private dataNascimento : Date; private dataFalecimento : [Date] := nil; private estadoCivil : EstadoCivil := <Solteiro>; private pai : [Pessoa]; private mae : [Pessoa]; private conjuge : [Pessoa]; private exConjuges : seq of Pessoa; private static pessoas : set of Pessoa; ... Mapeamento de atributos Mapeamento de associações

Resultado da importação para VDM++ (2) (após alteração de estilo, para ficar mais compacto) … operations public Pessoa(nome_ : String, sexo_ : Sexo, dataNascimento_ : Date, pai_, mae_ : [Pessoa]) res : Pessoa == is not yet specified; public Casamento(conjuge_ : Pessoa) == is not yet specified; public Divorcio() == is not yet specified; public Falecimento(data: Date) == is not yet specified; public GetNome() res : String == is not yet specified; public GetSexo() res : Sexo == is not yet specified; public GetDataNascimento() res : Date == is not yet specified; public GetDataFalecimento() res : [Date] == is not yet specified; public GetPai() res : [Pessoa] == is not yet specified; public GetMae() res : [Pessoa] == is not yet specified; public GetConjuge() res : [Pessoa] == is not yet specified; public GetExConjuges() res: seq of Pessoa == is not yet specified; public static GetPessoas () res: set of Pessoa == is not yet specified; public GetEstadoCivil() res: EstadoCivil == is not yet specified; public GetFilhos() res: set of Pessoa == is not yet specified; end Pessoa Construtor Operações de alteração Operações de consulta directa de variáveis de instância Outras consultas acrescentado

Acrescentar a definição de tipos de dados class Pessoa types public String = seq of char; public Date :: year : nat1 month : nat1 day : nat1; public Sexo = <Masculino> | <Feminino>; public EstadoCivil = <Solteiro> | <Casado> | <Divorciado> | <Viuvo> | <Falecido>; instance variables … operations end Pessoa Já passa na verificação de sintaxe e tipos (mas não é suficiente para executar)!

*Mapeamento de associações qualificadas RegistoCivil + RegistaPessoa(p: Pessoa, bi: nat) + GetPessoa(bi: nat) : [Pessoa] bi : nat Qualificador: atributo(s) usado(s) para navegar de “RegistoCivil” para Pessoa (chave de navegação) A cada número de bi corresponde 0 (no caso de nº não atribuído) ou 1 pessoa 1 0..1 - pessoas Associação qualificada Pessoa class RegistoCivil instance variables private pessoas : inmap nat to Pessoa := { |-> } ; operations public RegistaPessoa(bi: nat, p : Pessoa) == is not yet specified ; public GetPessoa(bi: nat) res : [Pessoa] == is not yet specified; end RegistoCivil

Referências e leituras adicionais Validated Designs for Object-oriented Systems. John Fitzgerald, Peter Gorm Larsen, Paul Mukherjee, Nico Plat and Marcel Verhoef. ISBN: 1-85233-881-4. Springer Verlag, New York. 2005. Manual de VDM++ (langmanpp_a4.pdf) Manual de VDMTools (usermanpp_a4.pdf)