• Nenhum resultado encontrado

CAPÍTULO 4 REFATORAÇÃO DE MODELOS DE CLASSES ANOTADOS COM

5.5 Estendendo o MoBRe

5.5.1 A API e o Módulo de Extensão do Plug-in MoBRe

A API do plug-in MoBRe consiste em um metamodelo para construção de modelos de classes OA. Ela possui um conjunto de classes relacionadas que permite armazenar informações sobre o código fonte de um sistema, como: classes e seus relacionamentos, atributos, métodos, aspectos e seus relacionamentos, conjuntos de junção, adendos e declarações inter-tipo que serão utilizadas posteriormente para geração de modelos de classes OA. O metamodelo do MoBRe é um extensão do metamodelo do DMAsp (Seção 4.3) e é apresentado na Figura 5.18 (as classes em cinza representam classes do metamodelo do DMAsp).

A classe Advice representa um adendo, possui um atributo adType que

armazena o tipo desse adendo: before, after ou around. Além disso, ela pode se relacionar com apenas um conjunto de junção (classe Pointcut). Apesar das linguagens de programação OA permitirem a associação de um adendo a mais de um conjunto de junção, essa decisão foi tomada para "forçar" a utilização de conjuntos de junção compostos, sendo essa uma boa prática para implementação de programas OA.

A classe Pointcut representa conjuntos de junção, possui o atributo

isAbstract que determina se o conjunto de junção é ou não abstrato. Além disso, ela implementa a interface Term que será importante para construção de conjuntos de junção compostos. Um conjunto de junção pode estar relacionado a várias operações (classe Operation) e conter vários parâmetros (classe Parameter).

Aspect é a classe que representa um aspecto. Além de adendos (Advice) e

conjuntos de junção (Pointcut), um aspecto pode conter declarações do tipo

declare parents (DeclareParents). Essas construções especificam relacionamentos de herança e realização de interfaces entre classes da aplicação.

A classe DeclareParents representa uma construção do tipo declare

parents. Além do identificador (id) e do tipo (dpType), que especifica se é uma construção do tipo declare implements ou do tipo declare extends, essa classe possui uma classe ou interface base (baseClass) e várias subclasses ou interfaces (subClasses). Declare implements declaram relacionamentos de realização de interfaces e declare extends, relacionamentos de herança.

CrossCuttingConcern é uma classe que representa um interesse transversal

e pode conter vários aspectos (Aspect). Essa classe herda características e comportamento da classe Package e por isso pode conter várias classes também.

CompositePointcut é um tipo de conjunto de junção e possui uma lista de

termos (Term). Esses termos podem ser outros conjuntos de junção ou operadores (Operator). O objetivo dessa classe é armazenar conjuntos de junção compostos, como por exemplo, pc1() && pc2(), onde pc1 e pc2 são conjuntos de junção e && é o operador lógico “e”.

Operator é uma classe utilizada para criação de conjuntos de junção

compostos. O atributo name armazena o símbolo correspondente ao operador. Os tipos de operadores disponíveis são especificados como constantes estáticas da

classe Operator. São eles: OPEN_PAR e CLOSE_PAR, que correspondem aos operadores de abertura e fechamento de parênteses, “(” e “)”, respectivamente; e AND_COND, OR_COND e NOT, que correspondem aos operadores lógicos "e", "ou" e "não".

Em Orientação a Aspectos os conjuntos de junção Target e This permitem capturar a instância de um objeto que executou ou onde está ocorrendo uma determinada operação. A diferença entre eles é o contexto no qual são executados. O This captura o objeto onde está o ponto de junção, já o Target captura o objeto que é o alvo da chamada do método. Para modelar esse comportamento, criou-se a classe TargetPointcut que representa um conjunto de junção que permite capturar

a instância de um objeto. Essa classe está relacionada a um alvo (interface Target) que pode ser uma classe ou interface. O atributo isThis é utilizado para determinar o contexto no qual a instância da classe alvo deve ser capturada. Por exemplo, se isThis receber o valor falso, o conjunto de junção representa uma construção

Target, caso contrário, representará uma construção This.

Within e WithinCode são classes que representam os conjuntos de junção

responsáveis, respectivamentre, por capturar todos os pontos de junção que ocorrem no interior de uma classe ou método.

A classe Cflow representa o conjunto de junção que intercepta todos os

pontos de junção que ocorrem no fluxo de execução de um determinado conjunto de junção, incluindo a chamada desse conjunto de junção. Há uma variação desse conjunto de junção, o cflowbelow, que desconsidera a chamada do conjunto de junção declarado no cflowbelow. Para representar essa diferença no metamodelo o atributo isBelow é utilizado. Quando isBelow é true, o conjunto de junção Cflow é do tipo cflowbelow.

IntroductionAttribute e IntroductionOperation são classes que

representam conjuntos de junção para declarações inter-tipo e são utilizados para modificar a estrutura de classes e interfaces, inserindo novos atributos e métodos nelas. Dessa forma, IntroductionAttribute está relacionado com um atributo e com uma ou mais classes que receberão esses atributos. IntroductionOperation, por sua vez, está relacionado com uma operação e com um ou mais alvos (Target) que podem ser classes ou interfaces.

De modo análogo ao que acontece no DMAsp, toda instância criada a partir do metamodelo do MoBRe será armazenada em um arquivo XML, cujo conteúdo consiste das informações necessárias para geração do modelo de classes OA. Esse arquivo possui uma sintaxe própria que não está em conformidade com qualquer ferramenta CASE. Por isso, para poder visualizar o modelo de classe OA é necessário transformar o arquivo XML em um arquivo XMI compatível com alguma ferramenta CASE. No caso do MoBRe, a ferramenta utilizada é a mesma do DMAsp, o ambiente Eclipse.

O trecho de código da Figura 5.19 exemplifica a utilização das classes da API do MoBRe apresentadas anteriormente para criação da classe UML Account apresentada na Figura 5.20.

1 public static void main(String[] args) {

2 Project prj = new Project("Class Model", "c:\test"); 3 Package pck1 = new Package("model");

4 Class cl = new Class("model.Account", "Account"); 5 Attribute attr = new

6 Attribute("model.Account.connection","connection", 7 new Type("java.sql.Connection", "Connection")); 8 Concern concern = new Concern("DatabasePersistence", 9 "DatabasePersistence"); 10 attr.addConcern(concern); 11 cl.addAttribute(attr); 12 pck1.addClass(cl); 13 prj.addPackage(pck1); 14 }

Figura 5.19 – Exemplo de Utilização da API do MoBRe.

Figura 5.20 – Classe Account afetada pelo Interesse de Persistência.

A linha 2 é responsável por criar um projeto Java, prj. Para esse projeto são armazenados seu nome e o caminho onde ele encontra-se localizado. Na linha 3 um pacote Java é criado (pck1), passando como parâmetro seu nome, que servirá também como identificador desse pacote. Na linha 4 uma classe, cl, é criada, passando como parâmetro seu identificador e seu nome. O identificador é utilizado para encontrar uma determinada classe no projeto e, por isso, deve ser único. O nome, por sua vez, é o que será apresentado no diagrama de classes. Isso serve também para outros elementos, como atributos e métodos. As linhas 5-7 são responsáveis pela criação de um atributo denominado connection do tipo

Connection. Nas linhas 8-10 é criado um interesse (Concern) denominado “DatabasePersistence” que é adicionado ao atributo connection. Ao adicionar um determinado interesse a um atributo ou método, ele é automaticamente adicionado à classe da qual esse atributo ou método pertence. Por fim, a linha 11 adiciona o atributo connection à classe cl, a linha 12 adiciona a classe cl ao pacote pck1 e a linha 13 adiciona o pacote pck1 ao projeto prj.

O módulo de extensão de plug-in MoBRe é um recurso que permite ao usuário implementar, sem muito esforço, suas próprias refatorações de interesses transversais. Entende-se por sem muito esforço o fato de que o MoBRe abstrai detalhes da plataforma de implementação de plug-ins de Eclipse, deixando com que o Engenheiro de Software se preocupe apenas com a resolução de seu problema, nesse caso, com a elaboração de refatorações para modularização de interesses transversais. Um exemplo de implementação de refatorações utilizando o módulo de extensão do MoBRe é apresentado nas próximas Subseções.