• Aucun résultat trouvé

Les inégalités d’accès à la formation selon la taille des entreprises

4. La construction des compétences dans les TPE-PME

4.1. Les inégalités d’accès à la formation selon la taille des entreprises

Tabela 3.1 Extensões Java

Sintaxe Significado a ==> b a implica b a <==> b a se e somente se b a <=!=> b negação de a <==> b

3.1.15 Redundância

O JML permite que suas especificações possuam redundância. Esta redundância consiste em demonstrar algumas características que estão implícitas nas especificações. Em outras pala- vras, através da redundância é possível demonstrar o que não foi demonstrado na especificação diretamente.

Através de pré e pós-condições redundantes, o especificador pode demonstrar, por exemplo, o que um método que está sendo utilizado na especificação faz. A Figura 3.11 demonstra um caso de pós-condição redundante.

/*@ ensures \result == theAID.length &&

@ Util.arrayCompare(theAID,(short)0,

@ dest,offset,(short)theAID.length) == 0;

@

@ ensures_redundantly

@ (\forall short i; 0 <= i && i < theAID.length

@ ==> theAID[i] == dest[offset+i]);

@*/

Figura 3.11 Exempo de uma especificação com redundância

Nesta figura nós podemos perceber que a cláusula ensures faz uma comparação entre dois

arrays através do método Util.arrayCompare. Para quem está verificando a especificação, não

é possível analisar o que este método executa sem ir à classe Util. A redundância é utilizada para demonstrar o que está sendo feito implicitamente na classe Util.arrayCompare, facilitando assim a leitura da especificação.

3.2

Ferramentas JML

Assim como nas linguagens de programação, a linguagem de especificação formal, como o JML, necessita de ferramentas que possam auxiliar nas tarefas de leitura, escrita e verificação das anotações. Existem duas categorias de ferramentas para JML: as ferramentas responsáveis pela verificação em tempo de execução e as que fazem a verificação estática.

As ferramentas que fazem a verificação em tempo de execução são responsáveis por verifi- car a conformidade da sintaxe e a análise semântica das especificações. A principal ferramenta responsável por esta verificação é o JMLRAC (Runtime Assertion Checker). O JMLRAC é res- ponsável por notificar ao usuário se ocorreu alguma violação em tempo de execução entre o que está descrito na especificação e o que está implementado, englobando informações de caráter

3.2 FERRAMENTAS JML 28

estático e dinâmico. Quando notificado que um erro foi encontrado, este erro não necessaria- mente está no código. Da mesma maneira que o programador pode implementar códigos com erro, o usuário responsável pela especificação pode também fazer as anotações erradas. En- tão, é importante também que seja feita uma verificação da corretude do que está descrito nas especificações.

O compilador JMLRAC é um compilador Java que compila o código transformando em

bytecodes devidamente instrumentados com o que está especificado nas anotações JML. Esta

instrumentação tem como objetivo fazer com que o próprio código seja capaz de detectar vio- lações de sua especificação [DFG05].

As informações estáticas incluem acontecimentos que indicam as partes da especificação que foi violada e a localização do erro no código, enquanto as informações dinâmicas incluem as chamadas dos métodos que levaram à violação e os valores das variáveis [DFG05].

Como as verificações dinâmicas estão ligadas aos valores das variáveis e das chamadas dos métodos, para que o compilador detecte violações, será necessário que vários cenários diferentes sejam testados para que estas violações sejam vistas.

O funcionamento do RAC consiste em ter como entrada um código Java anotado com JML para primeiramente realizar uma checagem sintática das anotações. Esta checagem é feita pelo compilador JML, o JMLc. Este compilador é uma extensão do compilador padrão Java com o

JML Type Checker.

Como o verificador JMLc irá verificar inconsistências entre o contrato e o que foi imple- mentado no código, ele deve ser confiável. Isto porque, caso o JMLc possua algum erro ou inconsistência, irá ser notificado falsas violações. Um exemplo do que poderia ocorrer seria se as especificações informais, vista na seção 3.1.13, fossem analisas pelo compilador e valores fossem atribuídos. Isto poderia causar muitas inconsistências já que este tipo de especifica- ção é mais utilizado para documentação. Para o JMLc as especificações informais são apenas desconsideradas.

Para realizar a verificação dos contratos em tempo de execução, o compilador JMLc traduz as anotações formais em códigos binários, adicionando as declarações que verificam o código, cujo objetivo é testar se o predicado é válido no momento em que um método é chamado. Portanto, o uso de JMLc não garante que o contrato será respeitado, isto porque o objetivo do compilador é encontrar inconsistências entre a especificação e o código Java através da execução das asserções geradas. Apenas que em caso de ser violado, o usuário receberá uma notificação da violação. Ou seja, usa-se o mesmo princípio de teste: pode-se mostrar presença de problemas (violação), mas não sua ausência.

A Figura 3.12 exemplifica com é realizado o processo de compilação do JML. O JMLc foi construído baseado em ferramentas JML já existentes e sobre o compilador MultiJava [CMLC06]. A principal ferramenta JML utilizada é a JML Type Checker que é responsável pela verificação dos tipos JML. O processo de compilação é realizado em duas etapas:

1. Checagem dos tipos através do JML Type Checker e uma compilação através do RAC; 2. Compilação do código gerado pelo RAC no MultiJava.

A primeira etapa consiste em realizar uma análise gramatical através de uma extensão do compilador Java tradicional (javac) e do MultiJava. Esta etapa irá realizar a verificação sintá-

3.2 FERRAMENTAS JML 29

Figura 3.12 Estrutura do Compilador JML (JMLc)

tica e semântica das anotações JML, tendo como saída uma árvore de sintaxe abstrata (AST) [NFH05], através do JML Type Checker. A árvore gerada é compilada através do RAC, que cria as asserções para verificação dos métodos anotados, gerando um arquivo Java temporário. No código Java temporário, para cada método anotado, é criado três novos métodos de asserções. Um para verificação das pré-condições e os outros dois para a verificação das pós- condições normal e excepcional.

Na segunda etapa, o arquivo temporário é compilado pelo MultiJava. Como saída, são gerados bytecodes instrumentados para serem executados no compilador tradicional do Java. Nesse código instrumentado estão as asserções que serão verificadas em tempo de execução.

Apesar de não possuir nenhuma metodologia de implementação específica, o RAC exige que algumas propriedades sejam verificadas antes que seja executado. Por exemplo, que sempre as pré-condições venham no início da anotação para garantir que o método está sendo invocado da maneira correta [DFG05].

Após a compilação do código Java com as especificações JML, a execução do bytecode gerado deve ser totalmente transparente para o usuário. A execução pode se tornar mais lenta, pois será necessária a verificação das asserções geradas pelo JML. Mas, enquanto não houver violações do contrato, o usuário não precisará saber o que está ocorrendo. Um programa com o mecanismo de checagem de asserções habilitado e consistente com sua especificação deve se comportar exatamente da mesma forma como se este mecanismo não existisse [DFG05].

Quando o compilador encontra uma violação de uma pré-condição, não se pode afirmar que o erro é da classe (especificação ou implementação). Nesta situação o responsável pelo erro é o programador que não seguiu as regras pré-estabelecidas pelo contrato na hora da instanciação da classe. Já quando a violação ocorre na pós-condição ou no invariante, podemos isentar o programador da culpa. Provavelmente nesta situação o erro encontrado foi causado pela classe