por blocos (if..else, for, do..while, etc.) e as simples, que são possuem em geral uma única linha de comando (atribuição, declaração de variáveis, etc.). A ferramenta CRISTA trata essas duas expressões de modos ligeiramente diferentes, pois quando uma instrução pode conter outras dentro de si, a ferramenta deve ser capaz de identificar e gerenciar tal evento. Ao passo que, quando uma instrução não pode englobar outras, sendo mais simples, a ferramenta não precisa gerenciar tal evento, economizando linhas de comando. De maneira geral, cada método para identificar uma regra na sintaxe de uma linguagem possui a 204 Apêndice A seguinte forma: Tabela 10 - Exemplo de um método para reconhecer uma produção 1 nomeDaRegra() 2 {} 3 { 4 declarações e símbolos que serão reconhecidos por essa produção. 5 } As Tabelas 11 e 12 mostram o código que deve ser inserido em métodos que analisam instruções compostas, ou seja, que podem possuir outras instruções dentro de si. A Tabela 11 mostra o código que registra as informações quando o método é iniciado. Já a Tabela 12, o código que registra as informações quando o método é finalizado. Tabela 11 - Código responsável em registrar o inicio de uma instrução composta 1 { 2 BlockDelimiter bd = new BlockDelimiter(jj_input_stream.getBeginLine(), jj_input_stream.getBeginColumn()); 3 Statement s = new Statement(actualStatement, bd , "{descrição_da_instrução}"); 4 actualStatement.addInsideStatement(s); 5 actualStatement=s; 6 } Tabela 12 - Código responsável em registrar o fim de uma instrução composta 1 { 2 actualStatement = actualStatement.getParentStatement(); 3 bd.setEndLine(jj_input_stream.getEndLine()); 4 bd.setEndColumn(jj_input_stream.getEndColumn()); 5 } Em ambos os códigos, um objeto é bastante usado: actualStatement. Este objeto é uma instanciação da classe Statement e é responsável em guardar as informações da instrução atual, ou seja, a instrução que esta sendo verificada. No contexto do método para verificar uma determinada produção da linguagem (Tabela 10), o código da Tabela 11 deveria ser inserido substituindo a linha 2 da Tabela 10. Da mesma forma, o código apresentado na Tabela 12 deveria ser inserido entre as linhas 4 e 5 da Tabela 10. A linha 2 da Tabela 11 cria o objeto bd, instância da classe BlockDelimiter, com os parâmetros jj_input_stream.getBeginLine() e jj_input_stream.getBeginColumn(), ou seja, a linha e a coluna em que a instrução começa. A linha 3 cria um objeto s da classe Statement, com três parâmetros: actualStatement, objeto do tipo Statement, que neste momento contém as informações da instrução que engloba a instrução atual; bd, que contém os valores da linha e da coluna de início da instrução; e um objeto String, que recebe uma descrição da instrução, por exemplo, “Declaração de variável” ou “Início de classe”. A linha 4 contém uma chamada de método da classe Statement, realizada pelo objeto actualStatement, para adicionar o objeto s a um array (vetor). Isto possibilita que, em outro momento, as informações das instruções mais globais sejam recuperadas. Finalmente, a linha 5 atribui o objeto s ao objeto actualStatement. Já na Tabela 12, a linha 2 atribui ao objeto actualStatement as informação da instrução que engloba a instrução que acabou de ser verificada. As linhas 3 e 4 configuram no objeto bd o valor da linha e da coluna, respectivamente, que corresponde ao fim da instrução que foi verificada. As Tabelas 13 e 14 representam o código que deve ser inserido em métodos que analisam instruções simples, ou seja, não podem englobar outras instruções. A Tabela 13 mostra o código que registra as informações quando o método é iniciado. Já a Tabela 14, o código que registra as informações Apêndice A 205 quando o método é finalizado. Tabela 13 - Código responsável em registrar o inicio de uma instrução simples 1 { 2 BlockDelimiter bd = new BlockDelimiter(jj_input_stream.getBeginLine(), jj_input_stream.getBeginColumn()); 3 Statement s = new Statement(actualStatement, bd , "{descrição_da_instrução}"); 4 actualStatement.addInsideStatement(s); 5 } Tabela 14 - Código responsável em registrar o fim de uma instrução simples 1 { 2 bd.setEndLine(jj_input_stream.getEndLine()); 3 bd.setEndColumn(jj_input_stream.getEndColumn()); 4 } Entre os códigos apresentados pelas Tabelas 11 e 12 e o código apresentado pelas Tabelas 13 e 13 há apenas duas diferenças. Para obter as informações de instruções simples não é necessário a linha 5 da Tabela 11, nem a linha 2 da Tabela 12. Isso porque essas linhas são as responsáveis em gerenciar instruções compostas. A Figura 5 representa graficamente como um código, neste exemplo em Java, é tratado pela ferramenta. Desta maneira, todas as linhas do código são analisadas pelas classes geradas pelo JavaCC, que utilizou o arquivo de definição de linguagem como modelo. Códigos de outras linguagens são tratados da mesma forma. 206 Apêndice A - actualStatement: método Teste; - Registra a linha e coluna de início do método; - Verifica a sintaxe do cabeçalho do método; - Procura por instruções dentro do método. Se houver, inicia a verificação dos mesmos. - actualStatement: bloco IF; - Registra a linha e coluna do bloco IF; - Verifica a sintaxe do cabeçalho do comando; - Procura por instruções dentro do bloco. Se houver, inicia a verificação dos mesmos. - actualStatement: instrução de atribuição; - Registra a linha e coluna de início da instrução; - Verifica a sintaxe da instrução; - Como este tipo de instrução não pode englobar nenhuma outra, é registrado a linha e coluna de fim da instrução e o objeto actualStatement volta para a instrução mais geral. - actualStatement: bloco IF; - Procura por outras instruções dentro do bloco; - Como não há nenhuma outra instrução, é registrada a linha e coluna de fim do bloco IF; - O objeto actualStatement volta para a instrução mais geral. - actualStatement: método Teste; - Procura outras instruções dentro do bloco. Se houver, inicia a verificação dos mesmos. - actualStatement: instrução return; - Registra a linha e coluna de início da instrução; - Verifica a sintaxe da instrução; - Como este tipo de instrução não pode englobar nenhuma outra, é registrado a linha e coluna de fim da instrução e o objeto actualStatement volta para a instrução mais geral. - actualStatement: método Teste; - Procura outras instruções dentro do bloco. Se houver, inicia a verificação dos mesmos. - Como não há nenhuma outra instrução, é registrada a linha e coluna de fim do método; Figura 5 - Processo realizado pela ferramenta CRISTA ao executar o parser de qualquer código submetido à ela Apêndice B APRESENTAÇÕES UTILIZADAS NOS ESTUDOS EXPERIMENTAIS 1 E 2 Treinamento sobre Inspeção e sobre a técnica Stepwise Abstraction 208 Apêndice B Apêndice B 209 210 Apêndice B Apêndice B 211 212 Apêndice B Apêndice B 213 214 Apêndice B Apêndice B 215 Apresentação sobre heurísticas de usabilidade de software 216 Apêndice B Apêndice B 217 Apêndice C PROGRAMAS USADOS NOS ESTUDOS EXPERIMENTAIS 1 E 2 Código para exercício sobre a Técnica Stepwise Abstraction Programa que calcula o maior valor primo menor que o valor informado pelo usuário 1 package br.ufscar.dc.lapes.crista.estudoCaso; 2 3 public class Classe 4 { 5 6 public static void main(String[] args) 7 { 8 int max = 100; 9 try 10 { 11 max = Integer.parseInt(args[0]); 12 } 13 catch (Exception e) 14 {} 15 16 boolean[] isprime = new boolean[max + 1]; 17 18 for (int i = 0; i <= max; i++) 19 { 20 isprime[i] =