A notação usada no método original para especificação de composições sobre ser- viços concretos não possui informações de controle. Sem essa informações de controle fica difícil para o projetista especificar alguns comportamentos do fluxo de execução do serviço, tais como, comportamentos de repetição e de tomada de decisões. A impossibili- dade de deduzir essas informações de maneira automática gerou a necessidade de propor uma notação estendida dessa composição original, essa nova versão tem como objetivo
Figura 4 – Fluxo Geral da Proposta
sanar o problema gerado pela simplicidade da composição original. Dessa forma, foram adicionadas a composição original instruções de controle como repetição e tomada de decisão.
Na notação estendida, uma composição pode estar na forma de uma lista serviços, na forma de uma estrutura condicional ou na forma de uma estrutura de repetição. Nessa extensão, não é permitida aninhamento de tais estruturas de controle, desse modo não será possível, por exemplo, uma estrutura de repetição conter uma estrutura condicional, ou vice-versa. Abaixo exemplos de como deve ser especificada uma consulta.
Exemplo 4. Composição utilizando uma sequência de serviços:
C1(A?,C!) ≡def A1(A?,X!),
A2(X?,Y!)
A3(Y?,C!)
lista representa uma funcionalidade. É importante notar que a ordem desses elementos não especifica necessariamente sua ordem de execução. Cada especificação define apenas as funcionalidade exigidas de cada serviço, assim como, a relação entre os parâmetros desses serviços. Essa relação entre parâmetros define as dependências entre os serviços, por exemplo, o parâmetro X é um parâmetro de saída em A1 e entrada em A2, significando
que há uma dependência entre A1 e A2. Uma dependência similar existe entre A2 e A3,
com relação ao termo y.
Exemplo 5. Composição utilizando If/else:
C1(A?,C!) ≡def if A1(A?,X!) then
A2(X?,Y!)
A3(Y?,C!)
else
A4(X?,Y!)
A5(Y?,C!)
No caso da estrutura condicional, utilizamos apenas a estrutura condicional if, que pode ser utilizada sem o complemento do else. É importante destacar que o serviço que indica a condição do if, neste trabalho, deve fornecer uma única saída, sendo ela do tipo booleano. No Exemplo 5, no serviço A1(A?,X!) a variável de saída X é do tipo
booleano.
De maneira análoga ao if, a estrutura de repetição while não permitirá aninha- mento de estrutura e será a única estrutura de repetição a ser usada na especificação das consultas.
Exemplo 6. Composição utilizando while:
C1(A?,C!) ≡def while A1(A?,X!) do
A2(X?,Y!)
A3(Y?,B!)
A4(B?,W!)
A5(W?,C!)
Essas informações de controle são importantes por deixar mais claro o fluxo de execução da composição mesmo utilizando serviços abstratos.
3.2.1
Identificação de Blocos Funcionalidades
Esta seção mostra como adaptar a consulta estendida para que seja entrada do algoritmo de refinamento. O algoritmo de refinamento utilizado para fazer a conversão de serviços abstratos para serviços concretos não suporta nenhum tipo de instrução de controle. Com a extensão da linguagem de especificação da composição, gerou-se uma incompatibilidade entre a linguagem de especificação estendida da composição e o tipo entrada do algoritmo de refinamento. O algoritmo de refinamento apenas aceita como en- trada uma composição nos moldes da composição original. Com isso, surgiu a necessidade de identificar lista de serviços independentes na consulta estendida, de modo que ela seja compatível com a entrada do refinamento.
Para essa identificação foi proposta uma divisão da composição estendida em blo- cos, de maneira que cada bloco tenha o formato de uma lista de serviços. Esses blocos de serviços pode ser identificados, segundo a definição da composição, de três formas dis- tintas: (i) pode-se encontrar uma lista de serviço (sem nenhuma instrução de controle), nesse caso, será gerada uma entrada com a interface e os serviços da definição formando assim a entrada do refinamento; (ii) uma estrutura condicional if, formada por três de blocos de funcionalidades, um para os serviços referentes a condição do if, um para o bloco then e outro, opcional, referente ao else; (iii) uma estrutura de repetição while, com dois blocos de funcionalidades, um para a condição de parada e outro para os serviços pertencentes ao bloco da repetição.
Exemplo Demonstrativo
Para demonstrar cada passo da abordagem proposta, criamos dois exemplos des- critos a seguir. O Exemplo 7 corresponde a uma especificação utilizando a estrutura if enquanto o Exemplo 8 corresponde a uma especificação utilizando a estrutura while.
Exemplo 7. Composição abstrata usando if :
CA1(A?,B?,C!,D!) ≡def if menor(A?,B?,L!) then sub(B?,A?, C!)
add(B?,C?,D!)
else
sub(A?,B?, C!) add(A?,B?,D!)
Os serviços pertencentes as composição são abstratos, o intuito aqui é demostrar a construção das estruturas e como será o seu resultado final.
Nesse ponto, é importante destacar que em casos como o da estrutura if podemos encontrar serviços em blocos distintos (then, else e na própria condição do if ). Portanto, essa etapa do processo visa dividir a composição inicial em blocos, de modo que tais blocos se transformem em entradas independentes do algoritmo de refinamento. Essa divisão permite que o algoritmo crie mapeamos independentes para cada bloco identificado na composição abstrata. Dessa forma, os serviços concretos resultantes do refinamento de um bloco serão independentes dos serviços obtidos pelo refinamento de outros blocos.
No caso da estrutura while, apenas dois blocos de funcionalidades são identifica- dos, o primeiro com a condição de parada e o segundo com a lista de serviços pertencentes ao bloco em questão. O processo de refinamento dessa estrutura gerará mapeamentos in- dependentes, conforme feito no refinamento de estruturas if.
Exemplo 8. Composição abstrata usando while:
CA2(D?,F?,A!) ≡def while dif(O?,F?,L!) then inc(O?,TMP!)
assign(TMP?,O!)
Considerando a composição do Exemplo 7, a divisão em bloco de serviços gerará entradas independentes para o algoritmo de reescrita, conforme mostrado no Exemplo9.
Exemplo 9. Divisão da especificação em blocos.
1. CA1’(A?,B?,C!,D!) ≡def menor(A?,B?,L!)
2. CA2”(A?,B?,C!,D!)≡def sub(B?,A?, C!),add(B?,C?,D!) 3. CA3”’(A?,B?,C!,D!)≡def sub(A?,B?, C!),add(A?,B?,D!)
Note que cada linha representa uma composição de serviços abstratos e será uma entrada distinta do algoritmo de refinamento: (i) uma para a condição do if ; (ii) outra para o bloco do then, e (iii) a última para o bloco do else. Se não existisse essa divisão em blocos e criássemos uma entrada única para o processo de refinamento, o algoritmo poderia gerar composições concretas que não condiziam com o que realmente é esperado, uma vez que, ele não saberia distinguir quais serviços fazem parte de um determinado bloco. Desse modo, seria possível criar composições de serviços concretos onde houvesse dependência entre serviços dos blocos then e else, por exemplo.
Nesta etapa foi utilizada uma estrutura XML para a representação da composi- ção inicial e dos blocos de funcionalidades (entradas do algoritmo de refinamento). Para fazer a conversão de um modelo para outro foi utilizado uma API da linguagem de pro- gramação Java chama DOM (Document Object Model). Com essa ferramenta, foi criado
um algoritmo para fazer a leitura do arquivo referente a composição e criar um arquivo com as listas de serviços candidatos que serão submetidos ao algoritmo de refinamento, explicado na seção seguinte. Os Apêndices A e F, mostram, respectivamente, exemplos dos documentos XML da especificação abstrata e da entrada do refinamento.