• Nenhum resultado encontrado

CAPÍTULO 4 UM PROCESSO PARA MODULARIZAÇÃO DE FRAMEWORKS

4.3 Processo de Modularização de Frameworks

4.3.4 Modularizar com Aspectos

O objetivo desta etapa é analisar as marcações que foram feitas no modelo de classes produzido na etapa anterior e refatorar atributos e métodos marcados para se tornarem aspectos, a fim de remover o entrelaçamento e o espalhamento de interesses relacionados a esse interesse do framework que está sendo modularizado.

Em virtude de linguagens orientadas a aspectos, como AspectJ (KICZALES et al., 1997), fornecerem estruturas para alterar o comportamento estático e dinâmico do fluxo de execução de um programa, esta etapa do processo está dividida em duas subetapas:

 Analisar o Crosscutting Estático, que consiste em verificar atributos e operações que devem ser adicionados a unidades do framework em tempo de compilação, por meio de inter-type declarations. Por exemplo, considere a classe A da Figura 4.8 que contém uma declaração de atributo relacionada ao interesse implementado pela classe B (linha 05). Essa declaração deve ser modularizada por meio de crosscutting estático. Dessa forma, o atributo atrB foi removido da classe A e encapsulado no aspecto ConcernB, que novamente o introduz por meio de

inter-type declarations na classe A (linha 06) ; e

 Analisar o Crosscutting Dinâmico, que consiste em analisar trechos de código relacionados ao interesse em análise que devem ser adicionados em tempo

Capítulo 4 - Um Processo para Modularização de Frameworks 55 execução, por meio de advices. Por exemplo, dentro do método construtor da classe A da Figura 4.8 há código relacionado ao interesse implementado pela classe B (linha 09), o que indica que esse código que deve ser modularizado por meio de

crosscutting dinâmico. Assim, esse código foi removido do método construtor da

classe A e encapsulado no aspecto ConcernB, por meio de um advice (linhas 08- 14), que captura a execução do método construtor de A e inicializa o atributo atrB.

Figura 4.8. Exemplos de crosscutting estático e crosscutting dinâmico.

Para a realização dessa etapa o engenheiro de software deve inicialmente identificar quais atributos e operações relacionados ao interesse em análise, que estão em unidades do

framework projetadas para implementar outros interesses que devem ser modularizados por

meio de crosscutting estático e crosscutting dinâmico. Isso significa definir o que deve ser implementado utilizando o mecanismo de inter-type declarations e o que deve ser implementado por meio de advices (Figura 4.9). Posteriormente, deve-se analisar o código fonte das unidades originais do interesse em análise para identificar os atributos e operações que estão relacionados a outros interesses, que devem ser removidos dessas unidades e modularizados em outras iterações do processo.

Capítulo 4 - Um Processo para Modularização de Frameworks 56

Figura 4.9. Descrição da etapa “Modularizar com Aspectos”.

Após análise do código fonte do framework, o engenheiro de software deve utilizar o seu conhecimento de domínio para estabelecer os aspectos que devem ser criados para modularizar a implementação do interesse em análise das demais unidades do framework que estão relacionadas a outros interesses. Isso deve ser feito para desacoplar a implementação do interesse em análise das unidades que foram projetadas para implementar outros interesses. Como comentado na Seção 4.3.1, podem ser considerados interesses: uma feature, um interesse transversal, um padrão ou variante de padrão.

Com a definição dos aspectos que devem ser criados, deve-se iniciar a modularização do interesse em análise com orientação a aspectos. Primeiramente, os atributos e operações classificados pelo engenheiro de software como crosscuting estático devem ser removidos de unidades do framework que foram projetadas para implementar outros interesses. Esses atributos e operações devem ser encapsulados em aspectos, que novamente os introduzem nessas unidades por meio de inter-type declarations. É possível utilizar os idiomas propostos por Hanenberg et al. (2003) como o Container Introduction, para implementar o crosscutting estático.

Implementado o crosscutting estático, o engenheiro de software deve remover o código relacionado ao interesse em análise das operações classificadas como crosscutting dinâmico. Esse código deve ser removido desses métodos e advices devem ser criados em um aspecto para separar o código relacionado ao interesse em análise desses métodos. Por exemplo, considere o modelo de classes da Figura 4.10 com duas classes. Uma que foi projetada para implementar o “interesse 1” (Classe1) e outra para implementar o “interesse

Capítulo 4 - Um Processo para Modularização de Frameworks 57 2” (Classe2). Na Classe2 há código relacionado ao “interesse 1” em seu método construtor, o que é um exemplo de funcionalidade que deve ser modularizada por meio de

crosscutting dinâmico. Para modularizar a implementação da Classe2, o trecho de código relacionado ao “interesse 1” deve ser removido e encapsulado em um aspecto, por meio de um advice. Dessa forma, evita-se o espalhamento de interesses relacionado ao “interesse 1” pela Classe2.

Figura 4.10. Exemplo de crosscutting dinâmico.

Durante a modularização de interesses de um framework com orientação a aspectos é importante considerar a ordem de precedência de execução dos aspectos existentes, caso existam, para implementar novos aspectos. Isso é relevante uma vez que determinado aspecto pode entrecortar um conjunto de métodos que outro aspecto introduziu por inter-type

declarations em uma classe. Sendo assim, para evitar erros de compilação é necessário que o

aspecto que utiliza inter-type declarations para introduzir métodos nessa classe execute primeiro que o aspecto que os entrecorta para adicionar comportamento aos mesmos. Outro problema que pode ocorrer quando não se considera a ordem de precedência de execução dos aspectos são comportamentos inesperados que podem causar erros de execução em situações nas quais há dois ou mais advices que acessam o mesmo ponto de junção (chamada ou execução de um método) para adicionar determinados comportamentos ao mesmo. Esses

advices podem estar localizados no mesmo aspecto ou em diferentes aspectos, como

exemplificado na Figura 4.11. Os aspectos X e Y entrecortam o método m1() da classe Z para adicionar comportamentos distintos a esse método. Por esse motivo é necessário utilizar o mecanismo de controle de precedência presentes em linguagens orientadas a aspectos nessas situações, de modo a evitar erros de compilação e de execução.

Capítulo 4 - Um Processo para Modularização de Frameworks 58

4.4 Considerações Finais

O processo de modularização de frameworks apresentado foi obtido a partir da modularização do framework de aplicação GRENJ-OO, que é baseado na linguagem de padrões GRN, e pode ser aplicado na modularização de outros frameworks que tenham as mesmas características. Os frameworks modularizados podem ser transformados em Linhas de Produtos de Frameworks, na qual seus membros são frameworks, ao invés de aplicações.

A aplicação do processo de modularização auxilia o engenheiro de software a separar a implementação de features opcionais e alternativas de um framework de seu núcleo, por desacoplá-las umas das outras. Isso permite ao engenheiro de aplicação selecionar apenas o conjunto de features necessário para satisfazer os requisitos da aplicação.

Esse processo possui relação com alguns princípios da Decomposição Horizontal (ZHANG e JACOBSEN, 2004), em virtude de ambos terem o enfoque em separar o núcleo do

framework da implementação de outras features e no refactoring incremental de features. Mas

diferente da Decomposição Horizontal, que possui maior enfoque na modularização de

crosscutting features, que são features relacionadas a interesses transversais, o processo

apresentado neste capítulo também trata da modularização de features opcionais e alternativas de frameworks. No capítulo seguinte é apresentada a aplicação desse processo na modularização do framework GRENJ-OO.