• Nenhum resultado encontrado

Um estudo sobre a utilização de aspectos no desenvolvimento de projetos reutilizáveis de software

N/A
N/A
Protected

Academic year: 2021

Share "Um estudo sobre a utilização de aspectos no desenvolvimento de projetos reutilizáveis de software"

Copied!
116
0
0

Texto

(1)

ANEXO 3

Modelo Aspectj para Introduções

declare parents: Ponto implements Comparable : esta declaração diz que a classe Ponto agora implementa a interface Comparable. Logicamente um erro a menos que Ponto declare os métodos de Comparable.

declare parents: Ponto extends GeometricObject : esta declaração define que a classe Ponto agora estende a classe ObjetoGeometrico. Um aspecto pode introduzir diversos elementos ao mesmo tempo.

Esta declaração introduz um novo campo e um novo método na classe Ponto

public String Ponto.name;

public void Ponto.setName(String name)

{

this.name = name;

}

Esta declaração introduz o método getName() nas classes Ponto e Linha

public String (Point || Line).getName()

{

return name;

(2)

O ponto de corte cflow escolhe os pontos de junção que ocorram entre a entrada e a saída de cada ponto de junção P escolhido pelo ponto de corte, incluindo o próprio P. Assim, são escolhidos os pontos de junção no controle de fluxo dos pontos

de junção escolhidos pelo ponto de corte.

O ponto de corte do tipo cflowbelow escolhe todos os pontos de junção que ocorrem entre a entrada e a saída de cada ponto de junção P escolhidos pelo ponto de

corte mas não incluindo o próprio P.

TIPO DEFINIÇÃO

cflow(Pointcut) Escolhe cada ponto de junção do fluxo de controle de

qualquer ponto de junção P escolhido por Pointcut, inclusive o próprio P

Cflowbelow(Pointcu

t)

Escolhe cada ponto de junção do fluxo de controle de

qualquer ponto de junção P escolhido por Pointcut, mas não o próprio P

Descritores Primitivos Relacionados ao Controle de Fluxo de Execução

Enquanto muitas responsabilidades estão relacionadas com a estrutura de execução do programa, outras são relacionadas com sua estrutura léxica. O AspectJ permite definir pontos de corte que escolham pontos de junção baseados na localização de um código a ser executado.

O ponto de corte do tipo within escolhe pontos de junção onde a execução do código é definida na declaração de um dos tipos de TypePattern. Isto inclui pontos

de junção do tipo inicialização de classe, inicialização de objeto, execução de método e execução de construtor.

TIPO DEFINIÇÃO

within(TypePattern )

Escolhe os pontos de junção cujo código executante esteja definido em um Tipo equivalente a TypePattern. Withincode(MethodP

attern)

Escolhe cada ponto de junção cujo código executante esteja definido em um método cuja assinatura corresponda a

MethodPattern

(3)

2) pointcut pegaPonto(Point p): call(*.*(Ponto)) && args(p)

O ponto de corte representado pelo segmento de código numero 1 define como

pontos de junção todas as chamadas a métodos da classe Linha que recebam um tipo

inteiro como argumento disponibilizando o valor deste argumento ao ponto de corte por meio da variável x. O ponto de corte representado pelo segmento de código de número 2 define como pontos de junção todas as chamadas a métodos que recebam um objeto

Ponto como argumento. A variável p disponibilizará o valor deste argumento ao ponto de corte.

A primitiva target permite selecionar pontos de junção cuja origem do evento seja um objeto específico. O ponto de corte descrito no segmento de código abaixo determina como pontos de junção a chamada aos métodos setX(int) e setY(int). A primitiva target(Ponto) garante que estes métodos sejam invocados de alguma instância da classe Ponto. Vejamos:

Pointcut atribuidor(): target(Ponto) && (call(void setX(int)) || call(void setY(int)));

Um ponto de corte do tipo this seleciona os pontos de junção do objeto corrente em execução quando este objeto corrente for uma instância de um tipo em particular.

TIPO DEFINIÇÃO

This(Type or

Id)

Escolhe cada ponto de junção onde o objeto corrente em

execução seja uma instância de Type ou seja do mesmo tipo de Id. Não estarão incluídos pontos de junção de contextos estáticos Target(Type or

Id)

Escolhe cada ponto de junção onde o objeto alvo (objeto sobre o qual uma chamada ou operação sobre campo é aplicada) seja uma instância de Type ou seja do mesmo tipo de Id. Não estarão incluídos chamadas leituras ou atribuições a membros estáticos Args(Type or

Id, ...)

Escolhe cada ponto de junção onde os argumentos são instâncias de um determinado Tipo ou identificador

Descritores Primitivos Relacionados ao Estado

Algumas responsabilidades são relacionadas ao controle de fluxo do programa. O AspectJ provê os descritores cflow e cflowbelow, que capturam pontos de

(4)

TIPO DEFINIÇÃO

Handler(Tipo) Escolhe os pontos de junção do tipo execução de exceção cujo Tipo corresponda ao argumento entre os parênteses

Descritores Primitivos Relacionados à Execução de Exceções

TIPO DEFINIÇÃO

AdviceExecution() Escolhe os pontos de junção do tipo advice execution

Descritores Primitivos Relacionados à Execução de Advices

O AspectJ prevê um descritor primitivo para capturar pontos de corte do tipo

execução de advice. Este tipo de descritor pode ser usado para por exemplo filtrar

algum ponto de junção que faça parte do fluxo de execução de algum advice. Um exemplo de tal aplicação para este tipo de descritor pode ser visto no segmento de código abaixo:

aspect TraceStuff {

pointcut myAdvice(): adviceexecution() && within(TraceStuff);

before(): call(* *(..)) && !cflow(myAdvice) { //fazer alguma coisa

} }

Os pontos de corte podem especificar parâmetros formais tipados de forma similar aos métodos Java. Desta forma o AspectJ permite que partes do contexto de execução dos pontos de junção seja exposta. Esta exposição é conseguida através do modelo de parametrização dos pontos de corte.

Sob este enfoque a primitiva args permite expor parte do contexto pontos de

junção. Quando args é especificado, permite a captura da argumentação recebida pelo

evento associado ao ponto de junção possibilitando o retorno deste valor ao ponto de

corte vejamos dois exemplos simples utilizando as classes Linha e Ponto apresentadas

anteriormente:

(5)

TIPO DEFINIÇÃO

Call(assinaturaCon

strutor)

Escolhe os pontos de junção do tipo chamada do construtor cuja assinatura do construtor corresponda ao

argumento entre os parênteses. Execution(assinatu

raConstrutor)

Escolhe os pontos de junção do tipo execução construtor cuja assinatura do construtor corresponda ao argumento entre os parênteses.

Initialization(ass inaturaConstrutor)

Escolhe os pontos de junção do tipo inicialização do objeto cuja assinatura do construtor corresponda ao

argumento entre os parênteses. Preinitialization(

assinaturaConstrut

or)

Escolhe os pontos de junção do tipo pre-inicialização do

objeto cuja assinatura do construtor corresponda ao

argumento entre os parênteses.

Descritores Primitivos Relacionados ao Objeto

TIPO DEFINIÇÃO

Staticinitializati on(Tipo)

Escolhe os pontos de junção do tipo execução do inicializador estático cujo Tipo corresponda ao argumento

entre os parênteses

Descritores Primitivos Relacionados à Inicialização da Classe

O AspectJ prevê um descritor primitivo para capturar pontos de corte do tipo

execução de exceção. Para todo ponto de junção deste tipo é considerado um argumento

de retorno que é o valor da exceção sendo manipulada. Este valor pode ser acessado com o uso de um ponto de corte do tipo args(). Assim, um aspecto que capture uma exceção hipotética qualquer antes que ela seja manipulada pode ser escrita conforme abaixo:

Aspect NormalizeFooException {

before(FooException e): handler(FooException) && args(e) {

e.normalize(); }

(6)

ANEXO 2

Modelo Aspectj para Pontos de Corte

DESCRITOR TIPO DEFINIÇÃO

Call(assinaturaMét

odo)

Escolhe os pontos de junção do tipo chamada de método cuja assinatura do método seja correspondente ao argumento entre os parênteses

Execution(assinatu

raMétodo)

Escolhe os pontos de junção do tipo execução de método cuja assinatura do método seja correspondente ao argumento entre os parênteses

Descritores Primitivos Relacionados a Método

TIPO DEFINIÇÃO

Get(assinaturaCamp

o)

Escolhe os pontos de junção do tipo referência a campo cuja assinatura do campo corresponda ao argumento entre os parênteses. Campos do tipo constante conforme mencionado não são pontos de junção

Set(assinaturaCamp

o)

Escolhe os pontos de junção do tipo atribuição de campo cuja assinatura do campo corresponda ao argumento entre os parênteses. Campos do tipo constante conforme mencionado não são pontos de junção

Descritores Primitivos Relacionados a Campo

O AspectJ considera para todo ponto de junção do tipo set um argumento de retorno que é o valor sendo atribuído ao campo. Desta forma este valor pode ser acessado com o uso de um ponto de corte do tipo args().

aspect GuardedX {

static final int MAX_CHANGE = 100;

before(int newval): set(int T.x) && args(newval) { if (Math.abs(newval - T.x) > MAX_CHANGE)

throw new RuntimeException(); }

(7)

ANEXO 1

Modelo Aspectj para Pontos de Junção

Nome Definição

Method call

quando um método é chamado

Method executio n

quando o corpo do método está sendo executado

Construc tor call

quando o construtor do objeto está sendo chamado

Construc tor executio n

quando o corpo do construtor está sendo executado. Nenhum valor é retornado deste tipo de ponto de junção

Static initiali zer executio n

quando um inicializador estático para a classe é executado. Nenhum valor é retornado deste tipo de ponto de junção

Field referenc e

para campos do tipo não constante. Campos do tipo constante não são pontos de

junção em função do Java os utilizar no processo de inline

Handler executio n

Quando um manipulador de exceção executa. Este tipo de ponto de junção requer um parâmetro que é o tipo de exceção manipulada. Nenhum valor retorna deste tipo de ponto de junção

Advice executio n

(8)
(9)

S5 Systems Inc. Byte code Optimization, 2002 http://www.s5systems.com/index .shtml?tech4.

SHUDO, Kazuyuku. shuJIT: a Java Just-in-Time Compiler for x86, 2002 http://www.shudo.net/jit.

SUZUKI, Junichi; Yamamoto, Yoshikazu. Extending UML with Aspects: Aspect Support in the Design Phase. Department of Computer Science, Graduate Scholl of Science and Technology, Keio University: Yokohama City, 1999.

VOELTER, Markus. Aspect-Oriented Programming in Java, 2000

http://www.voelter. de/data/articles/aop/aop.html.

WALKER, Robert J.; Baniassad, Elisa L. A.; Murphy, Gail C. An Initial Assessment of Aspect-oriented Programming. Dept. of Computer Science: University of Brithish Columbia, 1999.

XUE, Jingling; Cai, Qiong; Phung, Nguyen Hua. Dynamic and Adaptive Compilation , 2001 http://www.cse.unsw.edu.au/~jxue/jit.html.

(10)

HIGHLEY, T. J.; Lack, Michael; Miers, Perry. Aspect Oriented Programming: A Critical Analysis Of A New Programming Paradigm. Programing Languages: CS655 Semester Project from Professor Paul Raynolds, 2000.

HOMEPAGE BY IBM LABS. JIT/400, 1999 http://www.haifa.il.ibm.com/projects /systems/cot/jit400/index.html.

JENSEN, Markus. Jopt - The Java Class File Optimizer, 2000 http://www-i2.informatik.rwth-aachen.de/~markusj/jopt.

JENSEN, Markus. Optimizations, 2001 http://www-i2.informatik.rwth-aachen.de/~ markusj/jopt/htmldoc/node4.html.

KICKZALES, Gregor; Lamping, John; Mendhekar, Anurag; Maeda, Chris; Lopes, Cristina Videira; Loingtier, Jean-Marc; Irwin, John. Aspect-Oriented Programming – Published in proceedings of the European Conference on Object-Oriented Programming (ECOOP), Finland : Springer-Verlag, 1997.

KICKZALES, Gregor; Hilsdale, Eric; Hugumin, Jim; Kersten, Mik; Palm, Jeffrey; Griswold, William G. An Overview of AspectJ. Department of Computer Science, University of British Columbia, Xerox Palo Alto Research Center USA, Department of Computer Science and Engeneering: University of California. San Diego, 2001. LESIECKI, Nicholas. Improve modularity with aspect- oriented programming.

Technical Team Lead, eBlox, Inc., January 2002 http://www-106.ibm.com/developerworks/java/library/j-aspectj/?loc.

LOPES, Cristina Videira; Kickzales, Gregor. Recent Developments in AspectJ™. Xerox Palo Alto Research Center USA, 1998.

LOPES, Cristina; Kiczales, Gregor. Aspect-Oriented Programming with AspectJ™. Xerox PARC Palo Alto Research, 2000 www.parc.xerox.com/aop.

LOPES, Cristina Videira. Aspect-Oriented Programming:An Historical Perspective (What’s in a Name?). Institute for Software Research, University of California : Irvine, 2002.

RICHTER, Jeffrey. Earthweb Networking and Communications: Microsoft & .NET: JIT Compilation and Performance, 2002 http://softwaredev.earthweb.com.

(11)

Referências Bibliográficas

APPLE COMPUTER, INC. Automated Code Optimization, 2001:

http://developer.apple.com/techpubs/macosx/Essentials/Performance/Languages/Au tomated_C_ptimization.html.

ASPECT-ORIENTED PROGRAMMING (AOP), 2000. http://www.peterindia.com/ AOP.html.

ASPECTJ DOCUMENTATION AND RESOURCES, 2002. http://eclipse.org/aspectj. ALWIS, Brian de; Gudmundson, Stephan; Smolyn, Greg; Kiczales, Gregor. Coding

Issues in AspectJ. Department of Computer Science, University of British Columbia: Vancouver, 2000.

BLAIR, Lynne; Blair, Gordon S.. The Impact of Aspect-Oriented Programming on Formal Methods. Computing Department, Lancaster University, Bailgrig: Lancaster, 1998.

BOOLLERT, Kai. On Weaving Aspects. Heintzestr, 17 24143 Kiel: Germany, 1999.

BOOLLERT, Kai. AOP Case Study: System Management Application.

Fachhochschule Germany: Bóblingen, 2000.

ERNST, Erik. Separation of Concerns and Then What?. Department of Computer Science, University of Aalborg: Denmark, 2000 .

HARDWIK, Jonathan. Java Compilers, 1997 http://www-2.cs.cmu .edu /~jch /java/com pilers.html.

HARDWIK, Jonathan. Optimizing Java for Speed, 1997 http://www-2.cs.cmu.edu /~jch/java/speed.html

HERRERO, José Luis; Sanchez, Fernando; Lucio, Fabíola; Toro, Miguel. Introducing Separation Of Aspects At Design Time. Departamento de Informática, Universidad de Extremadura: Sevilha, 1999.

(12)

Capítulo VI

Conclusão

O objetivo em utilizar a POA como ferramenta de projeto de software reutilizáveis foi alcançado com sucesso. Foi possível evidenciar que a modularização das RCE possibilitou a reutilização do projeto Figuras Flutuantes em dois contextos diferenciados, sem a necessidade de adaptações de qualquer natureza nas classes do sistema.

Como resultado final foi possível obter dois ganhos que nas abordagens de programação OO e procedural encontram-se em posições antagônicas. São eles:

· Aumento do grau de especialização: os atributos e métodos necessários para a execução das instâncias no contexto específico C1 foram agregadas apenas quando as instâncias foram executadas neste contexto;

· Manutenção do grau de reusabilidade: o mesmo conjunto de classes foi executado nos dois contextos diferenciados C1 e C2, mesmo sob o fato de que ambos exigem um conjunto diferenciado de operações.

6.1. Sugestão para Trabalhos Futuros

Como sugestão para trabalhos futuros propõe-se o desenvolvimento de uma ferramenta que modularize as RCE identificadas nas classes do sistema de forma automatizada.

(13)

· Não existem notações formais para representação dos aspectos concretos ou abstratos e neles as suas operações;

· Torna-se difícil avaliar o grau de abrangência dos aspectos sobre as classes do sistema ou seja quais classes um aspecto realmente afeta. Isto gera:

- Dificuldade na manutenção dos aspectos pois altera-los pode afetar diversas

classes do sistema;

- As classes podem implementar pontos de corte nomeados e estes pontos de corte

podem ser reusados por diversos aspectos. É necessária uma representação formal que permita visualizar quais aspectos reusam um determinado ponto de corte pois altera-lo ou aos aspectos que os reusam podem gerar reflexos sobre o sistema.

A separação de responsabilidades mostrou-se viável como forma de diminuir a complexidade do código e aumentar o grau de reusabilidade dos componentes do sistema. Mas conforme pôde ser percebido durante a implementação do aplicativo Figuras Flutuantes, é fundamental um mecanismo que permita a representação formal dos aspectos. As seguintes vantagens são descritas

· Documentação e aprendizado - os aspectos devem ser documentados gerando um aprendizado mais fácil a respeito do seu relacionamento com os componentes do sistema; · Reuso - documentar como um aspecto foi construído(sua estrutura) e a forma pela

qual ele pode afetar os componentes do sistema pode determinar sua utilização em diferentes domínios.

Existem propostas como a extensão da UML pela adição de uma nova metaentidade para representar o aspecto. No entanto encontram-se ao nível de mera proposição. Desta forma necessitam ser alvo de estudos e avaliações que as permitam alçar ao nível de um formalismo que possa ser aceito e utilizado para suprir esta deficiência do modelo orientado a aspectos.

(14)

classe(s) afetada(s). Ocorre que alterações nas classes do sistema ou nos requerimentos relativos ao contexto podem gerar alterações nos aspectos no seguinte sentido:

· Em acordo com a convenção de classificação das RCE aqui adotada, uma RCE que passe a ser requerida pelo conjunto total de contextos passará a ser implementada como membro de classe;

· Da mesma forma uma operação que passe a ser requerida apenas por um conjunto restrito de contextos poderá passar a ser modularizada como uma RCE em um aspecto.

Novamente surgem dificuldades de visualização entre o aspecto que modulariza a RCE e o conjunto de classes por ele afetadas. Novamente o motivo é o fato de que a POA não prevê mecanismos que permitam a visualização dos aspectos em tempo de projeto.

5.4. Crítica ao Modelo Orientado a Aspectos

No decorrer do desenvolvimento das atividades deste trabalho surgiram diversos temas que oferecem pontos de vista críticos ao modelo orientado a aspectos. Não somente ao modelo da forma como foi concebido mas também a outros pontos considerados como relevantes por diversos autores. Entretanto estas abordagens não são o foco deste trabalho e podem ser vistas em diversas fontes (ALWIS et al, 2000, HERRERO et al, 1999, SUZUKI & YAMAMOTO, 1999, ERNST, 2000).

É comentado neste trabalho apenas uma deficiência que é a falta de padrões que possibilitem a representação dos aspectos em tempo de projeto. Existe realmente a falta de atenções no que diz respeito a técnicas que permitam a documentação dos aspectos. Foi possível verificar que (KICZALES, 2001) é o idealizador deste paradigma porém em suas publicações trata os aspectos apenas no tempo de implementação.

Esta deficiência gera dificuldades pois impede uma visão mais apurada do relacionamento entre as classes e os aspectos. A falta de um formalismo que permita a documentação dos aspectos como uma entidade do diagrama de classes implica nas seguintes dificuldades:

(15)

aspectos. Foram modularizados como RCE o seguinte conjunto de membros das classes:

- Duas declarações de importação de bibliotecas; Trinta atributos; Sete

implementações de métodos.

· A especialização das classes de forma que elas agora implementam apenas as operações realmente comuns aos contextos C1 e C2. O resultado foi a diminuição do código das classes em aproximadamente 54%;

A eliminação das referências entre as classes do sistema eliminando a dependência gerada na versão OO.

Figura 5.17 – Aplicativo Figuras Flutuantes com a Modularização das RCE

Entretanto surge uma questão semelhante àquela encontrada na modularização das responsablidades comuns. Não há mecanismos que garantam a evolução do aspecto que modulariza as RCE no que diz respeito à evolução da(s)

(16)

· Com a identificação e modularização das RCE de deslizamento, colisão e conexão as instâncias das classes Circulo, Triangulo, Retangulo passaram a herdar apenas as operações de pintura – métodos pintaFigura();

· As instâncias a classe Display passaram a herdar apenas as operações referentes ao suporte de pintura das figuras – métodos inicializaImagem(), paint() e update(); · A classe Registrador passou a não herdar mais o método pegaFiguras().

Todo o conjunto de atributos e bibliotecas de recursos associados a estas operações passaram a não ser mais agregados pelas instâncias inseridas no contexto C2. As instâncias inseridas no contexto C1 entretanto passaram a agregar estes recursos através das RCE modularizadas. As classes do sistema passaram a implementar apenas o conjunto de atributos e métodos comuns aos dois contextos idealizados para o aplicativo Figuras Flutuantes. Os demais métodos e atributos referentes às operações dos esquemas de deslizamento, colisões e conexões são agregadas apenas pelas instâncias inseridas no contexto C1.

A fig. 5.17 apresenta a caracterização do ambiente de execução após a modularização das RCE. Observe-se que a área de cor cinza, que representa a implementação das operações modularizadas como RCE, se estendem apenas sobre o retângulo da esquerda que é a representação do contexto C1. O retângulo da direita que é a representação do contexto C2 não é afetado.

A modularização das RCE de deslizamento, conexão e colisão nos aspectos

Navegacao, trataColisao, pintaLinhas, reduzTempoDeVida e protecaoDoRegistro

permitiu:

· Que as instâncias das classes Display, Circulo, Retangulo, Triangulo e Registrador quando inseridas no contexto C2 não herdem o conjunto que para elas é obsoleto de operações somente aplicados ao contexto C1;

· Que estas classes quando inseridas no contexto C1 agreguem o conjunto de operações de deslizamento, conexão e colisão por meio das RCE modularizadas nos

(17)

mecanismos que garantam a permanente evolução dos aspectos em função da evolução da(s) classe(s) por ele afetada(s).

Não há visibilidade alguma em tempo de projeto sobre quais classes e operações são afetadas por um aspecto que modulariza um determinado tratamento de erros. Surgem assim duas situações que podem gerar algum tipo de inconsistência no relacionamento classe-aspecto. São elas:

· Novas operações implementadas na classe geram alterações nos advices;

· Operações antigas que venham a ser alteradas de modo a eliminar ou alterar a natureza do seu tratamento de erros também geram alterações nos advices.

A única forma de administrar as inconsistências que podem ser geradas pelas situações acima citadas é a constante verificação do código dos aspectos e classes. Esta não é uma solução prática e pode vir a se tornar uma tarefa trabalhosa tendo em vista a complexidade que o sistema pode vir a adquirir. Os efeitos são os seguintes: · Advices inúteis poderão ser esquecidos poluindo o código do aspecto;

· Advices necessários para o tratamento de erros de alguma operação poderão não ser implementados.

Se por simples esquecimento as inclusões e alterações das necessidades de tratamento de erros não forem tratadas pelos aspectos haverá deficiência no tratamento de exceções.

5.3.3.2. Benefícios da Modularização das RCE

As RCE do aplicativo Figuras Flutuantes foram identificadas e modularizadas com o uso da metodologia sugerida no cap. 4. Como resultado obteve-se um conjunto de classes reutilizáveis que podem ser inseridas nos dois contextos distintos C1 e C2 sem a necessidade de customizações.

O benefício mais relevante foi o fato de que a modularização das RCE permitiu de certa forma especializar o mecanismo de herança do modelo OO da seguinte forma:

(18)

5.3.3. Os Benefícios Obtidos

A migração do aplicativo para uma abordagem orientada a aspectos possibilitou a obtenção de benefícios relativos às deficiências detectadas e descritas na seção 4.2.2. possibilitando a obtenção de vários itens de otimização.

5.3.3.1. Benefícios da Modularização das Responsabilidades Comuns

O modelo orientado a aspectos permitiu de uma forma natural modularizar no aspecto trataExecao todo o código referente ao tratamento de exceções. O resultado pôde ser visto na fig. 5.4 que mostra a implementação deste aspecto onde cada advice implementado faz uso de um ponto de corte nomeado declarado como membro da própria classe. Optou-se então por uma abordagem per-class para a declaração dos

pontos de corte deste aspecto.

É interessante mencionar que a flexibilidade oferecida pelo modelo de aspectos permitiria também uma abordagem centralizada onde todos os pontos de corte poderiam ter sido declarados dentro do próprio aspecto trataExcecao. Com a modularização do tratamento de exceções adquiriu-se:

· Um nível mais alto de modularização visto que o tratamento de exceções referentes às operações de pintura e navegação, entre outras, puderam ser modularizados em um único aspecto ao invés de estar disperso pelas classes do sistema;

· Um nível mais alto de reusabilidade visto que o código referente ao tratamento de um mesmo tipo de exceção pode ser reutilizado por mais de uma classe em mais de um método sem a ocorrência de replicação de código;

· A eliminação da replicação de código provocada pelo tratamento de exceções por meio da implementação do aspecto trataExcecao. O código replicado foi eliminado em dezoito pontos distintos das classes do sistema num total de sete classes beneficiadas, ou seja, 100% das classes implementadas.

A POA mostrou vantagens reais no que diz respeito à modularização e reutilização do código recorrente do tratamento de exceções. Mas por outro lado não há

(19)

aspect protecaoDoRegistro {

after() returning(): (call(void Registrador.Registra(Figura)) ||

call(void Registrador.Apaga(Figura))) && within(Figura)&& (withincode(new(..)) ||

withincode(void morre()))) {

throw new IllegalAccessError(

"Este é um acesso ilegal a " + thisJoinPoint + "\n" + "Apenas o construtor e o método morre() de Figura " + "\n" +

"podem invocar operações da classe Registrador. "); }

}

Figura 5.16 – O Aspecto protecaoDoRegistro

Se analisarmos o advice implementado para o aspecto mostrado na fig. 5.16 é possível separá-lo em quatro segmentos distintos que são:

· call(void Registrador.Registra(Figura)) || call(void Registrador.Apaga(Figura)): usa a primitiva call para especificar como

pontos de junção as chamadas aos métodos registra(Figura) e apaga(Figura). O

operador lógico OU aqui representado pelo símbolo ‘| |’ determina que o advice deverá ser executado quando um ou outro ponto de junção for encontrado;

· !(within(Figura)&& (withincode(new(..)) || withincode(void morre()))): determina a negação da seguinte sentença – o ponto de junção, quando encontrado, deverá estar contido dentro de um objeto da classe Figura (!(within(Figura)) e neste dentro do seu construtor ou dentro do método morre() - ((withincode(new(..)) || withincode(void morre()));

· after() returning(): determina a execução à partir do retorno normal do

ponto de junção encontrado.

Em suma, o advice será executado quando houver a invocação de um método registra() ou de um método apaga() cuja origem não seja exclusivamente o construtor ou o método morre() de um objeto da classe Figura.

Sendo executado o advice levantará uma exceção onde a forma especial

(20)

Quando o ponto de junção declarado no ponto de corte navegaFigura() é encontrado, ocorre a suspensão do fluxo de execução no tipo que originou o ponto de

junção. O objeto retornado permanece como objeto corrente no momento em que a

variável tempoRestante declarada no corpo do advice invoca o método pegaTempoDeVida() do objeto adquirindo o valor atual do atributo tempoVida desta

instância.

Sendo este valor maior que zero, o formato especial proceed() devolve o fluxo de execução ao objeto para que ele transcorra de forma natural. Caso contrário, o método morre() do tipo é invocado determinado o fim do tempo de vida do objeto. 5.3.2.5. O Aspecto protecaoDoRegistro

Este aspecto é utilizado para reforçar uma diretriz do projeto que é a seguinte: os métodos registra() e apaga() da classe Registrador podem ser invocados em apenas dois pontos da classe Figura que são seu construtor e o método morre(). A invocação destas primitivas a partir de qualquer outro ponto determinará o levantamento de exceção. São empregados neste advice três primitivas:

· call : determina como ponto de junção a chamada de métodos;

· within : associada à primitiva call permite determinar o tipo associado o ponto de

junção encontrado;

· withincode: associado à primitiva call possibilita a identificação da operação associada ao ponto de junção encontrado.

Os três operadores lógicos que na sintaxe AspectJ (&&, | | e !) são os operadores lógicos AND, OR e NOT respectivamente. São empregados para determinar o resultado da sentença. É aplicada também uma forma especial ThisJoinPoint que oferece informações reflectivas sobre o ponto de junção encontrado.

(21)

nomeação permite seu reuso em múltiplos advices sem a necessidade de rescrever o conjunto de pontos de junção.

Outro elemento até agora não apresentado é o advice do tipo around(). Este tipo de advice, diferentemente dos advices after() e before(), permite algum controle sobre o fluxo de execução na origem do ponto de junção. Este controle é conseguido pela combinação do formato especial proceed() que é disponível apenas para este tipo de advice e é mostrado na fig. 5.15.

aspect reduzTempoDeVida {

pointcut navegaFigura(Figura figura): target(figura) && (call(void

Figura+.navega()));

void around (Figura figura): navegaFigura(figura) {

int tempoRestante = figura.pegaTempoDeVida(); if (tempoRestante > 0) { figura.reduzTempoDeVida(); proceed(figura); } else figura.morre(); } }

Figura 5.15 – O Aspecto reduzTempoDeVida

Se analisarmos o advice implementado para o aspecto reduzTempoDeVida é possível separá-lo em quatro segmentos distintos que são:

· target(figura) && (call(void Figura+.navega(): a diretiva call determina como ponto de junção a chamada ao método navega() de todos os subtipos da classe Figura, neste caso objetos Circulo, Retangulo e Triangulo. A primitiva target() determina como objeto origem da operação uma instância desta classe;

· void around (Figura figura):navegaFigura(figura): o advice

around(), quando executado, retorna uma referência ao objeto Figura que originou o ponto de junção. Esta referência retorna na variável figura declarada no advice.

(22)

· call(Graphics Figura+.pintaFigura(Graphics, double, double)): usa a primitiva call para especificar como ponto de junção as chamadas ao método pintaFigura() de qualquer subtipo da classe Figura;

· after(Figura figura) returning(Graphics g): determina que após a execução do corpo do ponto de corte, havendo retorno normal do método

pintaFigura(), serão armazenados na variável figura uma referência ao objeto de

origem do ponto de junção e na variável g uma referência ao objeto Graphics recebido como parâmetro pelo ponto de corte;

· target() && call(): o operador lógico ‘E’ , aqui determinado pelo símbolo

‘&&’ que é utilizado para reforçar a determinação do ponto de corte de que o advice

somente será executado para pontos de junção cuja origem seja um objeto da classe

Display. Não serão válidos quaisquer outros pontos de junção eventualmente

encontrados cuja origem não seja o tipo especificado pela primitiva target().

Sendo encontrado o ponto de junção especificado o advice é executado e o método detectaColisao(g) é invocado. Este método é introduzido na classe Display, bem como os métodos ocorreuColisao() e manipulaColisao() pelo mecanismo de introduções.

5.3.2.4. Aspecto reduzTempoDeVida

Na versão OO do aplicativo a redução do tempo de vida dos objetos Figura foi implementado à dentro do método manipulaNavegação() da classe Display. Tal escolha foi efetuada em função da convenção adotada para o projeto onde o tempo de vida do objeto é reduzido à medida em que ele se movimenta sobre o plano.

A justificativa para implementação do aspecto reduzTempoDeVida é que a classe Display, a qual representa o plano onde os objetos Figura flutuam, não tem como responsabilidade primária dar suporte à operação de redução do tempo de vida das figuras.

Observamos para este aspecto a nomeação explícita de um ponto de corte. Nos aspectos anteriormente apresentados os pontos de corte são ditos anônimos. A

(23)

5.3.2.3. O Aspecto trataColisao

Na versão OO do aplicativo o tratamento de colisões foi implementado à partir do método trataColisao() da classe Display. É possível encapsular no aspecto

trataColisao a responsabilidade relativa a estas operações.

Isto permitirá que a classe Display implemente apenas sua responsabilidade primária que é suportar a pintura das figuras no plano, podendo agregar o aspecto de tratamento de colisões quando o contexto assim o exigir.

A implementação do aspecto trataColisoes pode ser vista na fig. 5.14 que apresenta a declaração de um advice do tipo after() e três elementos do tipo Introdução.

aspect trataColisao {

after(Figura figura) returning(Graphics g): target(figura) && call(Graphics Figura+.pintaFigura(Graphics, double, double)) {

figura.pegaDisplay().detectaColisao(g); }

public void Display.detectaColisao(Graphics g) {...}

static boolean Display.ocorreuColisao(Figura a, Figura b) {...}

private void Display.manipulaColisao(Graphics g, Figura a, Figura b)

{...} }

Figura 5.14 –O Aspecto trataColisao

O aspecto trataColisao concentra todas as operações relativas ao tratamento de colisões do aplicativo. A classe Display não declara mais estes métodos livrando-se desta responsabilidade que conforme convencionado no cap. 4 é caracterizada como uma RCE. Ocorre então um processo de ‘limpeza’ da estrutura desta classe. Se analisarmos o advice implementado para o aspecto é possível separá-lo em quatro segmentos distintos que são:

· target(display): determina que a origem do ponto de junção a ser encontrado seja uma instância da classe Display;

(24)

5.3.2.2. O Aspecto pintaLinhas

Na versão OO do aplicativo o esquema de conexões foi implementado à partir do método pintaLinhas() da classe Linha. A classe Display tem sua participação nas operações do esquema de conexões por meio do método atualizaLinhas(). A justificativa para implementação do aspecto pintaLinhas são as seguintes:

· A classe Display, a qual representa o plano onde os objetos Figura flutuam, não tem como responsabilidade primária dar suporte às operações do esquema de conexão das figuras e aplicada;

· Aplicar a classe Display a um contexto onde o esquema de conexões fosse diferenciado ou não existisse, como é o caso do contexto C2, tornaria necessário customizações manuais de modo a remover as referências às operações deste esquema;

· As referências à classe Linha dentro da classe Display determinam um grau de dependência entre as duas classes visto que elas referenciam uma à outra.

A implementação do aspecto pintaLinhas pode ser vista na fig. 5.13 que apresenta a declaração de um advice do tipo after() e um elemento do tipo introdução.

aspect pintaLinhas {

after(Display display) returning(Graphics g): target(display) && (call(public Graphics getGrafico(Graphics)))

{

display.atualizaLinhas(g); }

public void Display.atualizaLinhas(Graphics g) {...} }

Figura 5.13 – O Aspecto pintaLinhas

Este advice é implementado de forma similar ao advice do aspecto

Navegacao. Entretanto, quando o ponto de junção é encontrado é invocado o método atualizaLinhas(). Este método é introduzido na classe Display por meio de um elemento

(25)

O aspecto Navegacao concentra agora todas as operações relativas ao

esquema de deslizamento do aplicativo. As classes Display e Figura não declaram mais estes métodos livrando-se desta responsabilidade que conforme convenção adotada no cap. 4 é caracterizada como uma RCE.

Ocorre então um processo de ‘limpeza’ da estrutura destas classes. Se analisarmos o advice implementado para o aspecto é possível separá-lo em quatro segmentos distintos que são:

· target(display): determina que a origem do join point a ser encontrado seja uma instância da classe Display;

· call(public Graphics getGrafico(Graphics)): usa a primitiva call para especificar como pontos de junção as chamadas ao método getGrafico(Graphics);

· after(Display display) returning(Graphics g): determina que após a execução do corpo do ponto de junção, havendo retorno normal do método

getGrafico(Graphics), serão armazenados na variável display uma referência ao

objeto de origem do ponto de junção e na variável g uma referência ao objeto

Graphics recebido como parâmetro pelo ponto de junção;

· target() && call(): o operador lógico ‘E’ , aqui determinado pelo símbolo

‘&&’ que é utilizado para reforçar a determinação do ponto de corte de que o advice

somente será executado para pontos de junção cuja origem seja um objeto da classe

Display. Não serão válidos quaisquer outros pontos de junção eventualmente

encontrados cuja origem não seja o tipo especificado pela primitiva target().

Sendo encontrado o ponto de junção especificado o advice é executado e o método manipulaNavegacao(g) é invocado. Este método é introduzido na classe

Display, bem como os métodos navega() das classes Círculo, Retângulo e Triangulo

pelo mecanismo já apresentado chamado introdução. Conforme já visto as introduções são utilizados para introduzir novos membros em uma classe.

(26)

instâncias da classe. Segue adiante a descrição dos aspectos implementados e que modularizam as RCE classificadas anteriormente.

5.3.2.1. O Aspecto Navegacao

Na versão OO do aplicativo o esquema de deslizamento foi implementado à partir do método navega(), herdado da superclasse Figura e sobrescrito nas subclasses

Circulo, Retangulo e Triangulo. A classe Display tem sua participação nas operações do

esquema de deslizamento por meio do método manipulaNavegação(). A justificativa para implementação do aspecto Navegacao são as seguintes:

· A classe Display, a qual representa o plano onde os objetos Figura flutuam, não tem como responsabilidade primária dar suporte às operações de deslizamento das figuras;

· A implementação do esquema de deslizamento contido nestas classes pode ser considerado como uma responsabilidade secundária pois, aplicando estas classes ao contexto C2, o esquema de deslizamento não existe.

A implementação do aspecto Navegacao pode ser vista nna fig. 5.12 pela declaração de um advice do tipo after() e cinco elementos do tipo introdução.

aspect Navegacao {

after(Display display) returning(Graphics g): target(display) && (call(public Graphics getGrafico(Graphics)))

{

display.manipulaNavegacao(g); }

public void Display.manipulaNavegacao(Graphics g) {...} private void Circulo.navega() {...}

private void Triangulo.navega() {...} private void Retangulo.navega() {...} }

(27)

Cabe frisar que uma alternativa diversa à modularização destas RCE em aspectos seria declarar classes intermediárias que implementassem estas operações. Como resultado desta abordagem classes intermediárias encapsulariam as operações de deslizamento, colisão e conexão. É uma alternativa que preserva a diretriz de modularização da OO mas menos desejável sob os seguintes aspectos:

· Menor performance - teríamos inúmeras chamadas dos objetos Figura aos métodos destas classes intermediárias sempre que fosse necessária a execução de uma destas operações. Isto é menos otimizado em termos de velocidade de execução se compararmos a uma classe que invoca os próprios métodos;

· Maior dependência entre módulos - sendo que os objetos da classe Figura e

Display referenciariam estas classes intermediárias, a única forma de inseri-las em

um novo contexto seria customizá-las manualmente para alterar ou talvez remover estas referências;

· Dificuldade de restrição de acesso - nada impediria que um objeto da classe

Círculo invocasse uma operação de navegação para um objeto Retangulo.

Por outro lado a modularização destas RCE em aspectos traz as seguintes vantagens:

· Maior performance - a operação, quando exigida pelo contexto, pode ser introduzida diretamente na classe possibilitando que o lookup seja sempre relativo a métodos da própria classe;

· Inexistência de dependência entre módulos - não existe qualquer forma de dependência entre o aspecto e a classe possibilitando que esta possa ser introduzida em outro contexto sem necessidade de customizações manuais;

· Total restrição ao acesso - um aspecto pode introduzir membros privados em uma classe, restringindo assim o acesso a estes membros.

E cabe ainda frisar uma das maiores vantagens obtidas: as RCE podem ser agregadas apenas quando são realmente requeridas afetando apenas determinadas

(28)

Tabulação RCE Classe : Registrador LISTA DE CONTEXTOS OPERAÇÕES 1 (C1) 2 (C2) 3 4 ... 5 ... 6 ... 7 ... 8 ... 9 ... 10 ... TAO 1 OPERAÇÕES DE PROTEÇÃO DO REGISTRO X 50% 2 OUTRAS OPERAÇÕES DO REGISTRO DOS OBJETOS

X X 100%

Figura 5.11 – Tabulação RCE da Classe Registrador

Com a aplicação da tabela RCE sobre a classe Registrador é obtido como resultado que as operações de proteção do registro não são aplicadas ao conjunto total de contextos C1 e C2. Em acordo com a simples convenção aqui adotada isto implica nos seguintes fatos:

· Os métodos e atributos relativos à estas operações são caracterizados como RCE; · Serão então modularizados na forma de aspectos.

A determinação da TAO das operações implementadas por estas classes para os contextos C1 e C2 descritos anteriormente gera o seguinte resultado:

· Nas subclasses de Figura as operações do esquema de navegação não são aplicadas a todos os contextos;

· Na classe Display as operações de suporte aos esquemas de colisão, conexão e navegação não são aplicadas a todos os contextos;

· As operações de proteção do registro implementadas na classe Registrador só se aplicam ao contexto C1.

Conforme dita o padrão de conduta aqui assumido para condução do processo de classificação das RCE, estas operações passarão a ser modularizadas em aspectos. As demais serão mantidas nas classes como parte de sua estrutura primária.

(29)

· Os métodos e atributos relativos à estas operações são caracterizados como RCE; · Serão então modularizados na forma de aspectos;

· A fig. 5.10 mostra a aplicação da tabela RCE sobre a classe Display. A TAO para as operações podem ser facilmente visualizadas.

Tabulação RCE Classe : Display

LISTA DE CONTEXTOS OPERAÇÕES 1 (C1) 2 (C2) 3 4 ... 5 ... 6 ... 7 ... 8 ... 9 ... 10 ... TAO 1 OPERAÇÕES DE TRATAMENTO DE COLISÃO X 50% 2 OPERAÇÕES DO ESQUEMA DE NAVEGAÇÃO X 50% 3 OPERAÇÕES DO ESQUEMA DE CONEXÕES X 50% 4 OUTRAS OPERAÇÕES DE MANIPULAÇÃO DOS DADOS

X X 100%

Figura 5.10 – Tabulação RCE da Classe Display

Com a aplicação da tabela RCE sobre a classe Display é obtido como resultado que as operações do esquema de deslizamento, navegação e colisão não são aplicadas ao conjunto total de contextos C1 e C2. Em acordo com a convenção aqui adotada isto implica no seguinte fato: os métodos e atributos relativos à estas operações são caracterizados como RCE.

Serão então modularizados na forma de aspectos. A fig. 5.11 mostra a aplicação da tabela RCE sobre a classe Registrador. A TAO para as operações podem ser facilmente visualizadas.

(30)

No caso específico do aplicativo Figuras Flutuantes as operações de deslizamento, colisão e conexão determinam o fator de reusabilidade das classes do sistema porém tornam-se obsoletas em função da inserção de suas instâncias no contexto C2. Será então conduzido o processo de modularização das operações de deslizamento, colisão e conexão na forma de aspectos, visto que elas assumem a característica de serem responsabilidades do tipo RCE. Como forma de obter uma visualização mais facilitada da taxa de aplicabilidade destas operações ao conjunto total de contextos é aplicado sobre estas classes a tabulação RCE sugerida anteriormente no cap 4. Vide fig. 5.9 a seguir.

Tabulação RCE Classe : Circulo, Retangulo,

Triangulo LISTA DE CONTEXTOS OPERAÇÕES 1 (C1) 2 (C2) 3 4 ... 5 ... 6 ... 7 ... 8 ... 9 ... 10 ... TAO 1 OPERAÇÕES DE PINTURA X X 100% 2 OPERAÇÕES DO ESQUEMA DE NAVEGAÇÃO X 50% 3 OUTRAS OPERAÇÕES DE MANIPULAÇÃO DOS DADOS X X 100%

Figura 5.9 – Tabulação RCE das Classes Circulo, Retangulo e Triangulo

A fig. 5.9 apresenta a aplicação da convenção de classificação sugerida sobre as classes Display, Circulo, Triangulo, Retangulo e Registrador. Ela torna-se útil para que se possa observar a taxa de aplicação das operações das classes com base nos contextos C1 e C2. A figura acima mostra a aplicação da tabela RCE sobre as

subclasses de Figura. É obtido como resultado que as operações do esquema de

navegação não são aplicadas ao conjunto total de contextos C1 e C2. Em acordo com a convenção aqui adotada sto implica nos seguintes fatos:

(31)

Como pôde ser visto na descrição das características do aplicativo as instâncias das classes do sistema podem ser eventualmente inseridas no contexto particular C1. Pôde ser verificado que as figuras são conectadas entre si por linhas à medida que são criadas, flutuam em alguma direção por algum tempo e são apagadas do plano quando colidem umas com as outras ou expira seu tempo de vida. Foi verificado, também, que as instâncias das classes do sistema quando criadas podem também vir a serem inseridas num contexto diferenciado de C1 que é o contexto C2.

Pôde ser verificado que neste outro contexto os requisitos são totalmente diferenciados do primeiro nos seguintes termos:

· As figuras não flutuam e são apenas entidades estáticas no plano e por conseqüência não irão colidir entre si como acontece no contexto C1;

· Não há linhas que as conectem a outras figuras já existentes no plano no momento de sua criação;

· O tempo de vida das figuras não é limitado, de modo que após criadas elas permanecem pintadas de forma definitiva sobre o plano.

Como conseqüência as operações que tratam do deslizamento, colisão e conexão destas figuras no plano tornam-se obsoletas no contexto C2. Se observarmos a classe Display nos deparamos com uma situação semelhante à anterior. O plano projetado para o aplicativo tem como função básica suportar a pintura das figuras. Entretanto esta classe implementa também operações que possibilitam o tratamento da colisão e da conexão.

É ineressante frisar que foram projetados apenas dois contextos diferenciados para as classes do sistema Figuras Flutuantes. Mas sem dúvida as possibilidades são inúmeras e novas operações são implementadas e excluídas à medida que torna-se necessário ampliar ou restringir o aspecto de reusabilidade das classes. Porém conforme mencionado à medida que novos contextos se abrem para a classe o conjunto de operações que ela passa a implementar pode se tornar muito extenso.

(32)

Circulo.navega(...):" + e); } after(Retangulo rt) throwing(Exception e) : Retangulo.erroNavegando(rt) { System.out.println("Erro no método Retangulo.navega(...):" + e); } after(Display ds) throwing(Exception e) : Display.erroNavegando(ds) { System.out.println("Erro no método Display.manipulaNavegacao(...):" + e); }

//**advices para tratamento de colisao after(Display ds) throwing(Exception e) : Display.erroDetectandoColisao(ds) { System.out.println("Erro no método Display.detectaColisao(...):" + e); } after(Display ds) throwing(Exception e) : Display.erroManipulandoColisao(ds) { System.out.println("Erro no método Display.manipulaColisao(...):" + e); }

//**advices para tratamento da leitura do registrador after(Display ds, Figura[] lgf) throwing(Exception e) : Display.erroLendoRegistrador(ds, lgf)

{

System.out.println("Erro lendo registrador...->" + e); }

}

Figura 5.8 – Aspecto trataExcecao

5.3.2. A Modularização das RCE

Para a identificação das RCE das classes foram escolhidas as classes

Display, Círculo, Retangulo, Triangulo e Registrador. Esta escolha foi dirigida pelo

fato destas classes estarem diretamente ligadas às operações que diferenciam os contextos C1 e C2 descritos anteriormente.

(33)

package ContextoC1; aspect trataExcecao {

//**advices para tratamento dos procedimentos de pintura after(Circulo cr) throwing(Exception e) : Circulo.erroPintando(cr) { System.out.println("Erro no método Circulo.pintaFigura(...):" + e); } after(Triangulo tr) throwing(Exception e) : Triangulo.erroPintando(tr) { System.out.println("Erro no método Triangulo.pintaFigura(...):" + e); } after(Retangulo rt) throwing(Exception e) : Retangulo.erroPintando(rt) { System.out.println("Erro no método Retangulo.pintaFigura(...):" + e); } after(Display ds) throwing(Exception e) : Display.erroPintandoLinha(ds) { System.out.println("Erro no método Display.atualizaLinhas(...):" + e); } after(Display ds) throwing(Exception e) : Display.erroPintando(ds) { System.out.println("Erro no método Display.manipulaPintura(...):" + e); }

//**advices para tratamento dos procedimentos de navegação after(Triangulo tr) throwing(Exception e) : Triangulo.erroNavegando(tr) { System.out.println("Erro no método Triangulo.navega(...):" + e); } after(Circulo cr) throwing(Exception e) : Circulo.erroNavegando(cr) { System.out.println("Erro no método

(34)

exceções seriam facilmente visualizados em um único aspecto. Entretanto importante lembrar que a todo momento novas operações são implementadas e novas cláusulas de tratamento de erros são incluídas no código das classes do sistema.

Realmente nada impediria que estas novas operações passassem desapercebidas na manutenção dos aspectos e deixassem de ser incluídas. Por considerar este motivo como maior desvantagem – embora não profundamente estudada aqui - decidimos por descartar a abordagem centralizada e optar pela segunda hipótese.

Considerando o problema de manutenção acima mencionado a segunda opção parece realmente mais vantajosa. Ao contrário da opção anterior totalmente centralizada, cada classe declararia o seu próprio conjunto de pontos de corte representativos às suas próprias cláusulas de tratamento de erros. Surge então uma concordância com o ponto de vista de (ALWIS et al, 2000) que afirma haver uma visualização mais fácil do conjunto de pontos de junção de cada classe.

É plausível presumir que, à medida que novas operações forem incluídas, estes pontos de corte possam realmente ser alterados com menor probabilidade de esquecimento por parte do programador - embora não haja garantias quanto a isso.

Também é vantajoso do ponto de vida da clareza do código de aspectos se a nomenclatura dos pontos de corte for clara no que se refere à sua finalidade. A versão orientada a aspectos do aplicativo Figuras Flutuantes implementa a modularização do tratamento de exceções em um único aspecto chamado trataExcecao. Este aspecto implementa um conjunto de 12 advices onde cada advice é destinado a um tipo específico de exceção.

A justificativa para a adoção desta diretriz diz respeito somente à legibilidade do código do aspecto. Acumular em um único ou em poucos advices os inúmeros pontos de corte representativos ao tratamento de erros geraria maior complexidade do código do aspecto. A fig. 5.8 apresenta parte do código do aspecto

(35)

É possível observar que as classes replicam a implementação das operações de tratamento de erros conforme pode ser visto nos segmentos de código da fig 5.7. Nela são mostrados os métodos de pintaFigura() e navega() declarados na classe Circulo. As classes Retangulo e Triangulo logicamente herdam estes métodos e os

implementam.

Public class Circulo extends Figura {

void pintaFigura(Graphics g, double xPos, double yPos) { try {...} catch(Exception erroPintando) {...} } void navega() { try{...} catch(Exception erroNavegando) {...} } }

Figura 5.7 – Tratamento de Exceções das Classes do Sistema

No que tange à modularização do tratamento de exceções do sistema com a utilização de aspectos, podem ser aplicadas várias abordagens diferenciadas. Dentre várias possibilidades cogitadas as duas consideradas mais coerentes são enumeradas logo abaixo:

1) A implementação de um único aspecto concreto que declararia todos os pontos de

corte sob uma abordagem centralizada;

2) A implementação de um único aspecto concreto que utilizaria os pontos de corte declarados sob uma abordagem per-class.

A primeira opção seria interessante do ponto de vista da facilidade de manutenção visto que todas os pontos de junção representativos ao tratamento de

(36)

que o conjunto de recursos exigidos pelo contexto C2. São exigidos a mais pelo contexto C1:

· Duas bibliotecas de recursos que são as bibliotecas math e util; · Trinta variáveis;

· Sete métodos.

Do ponto de vista da reutilização seria interessante se os atributos e métodos relacionados a contextos específicos fossem agregados somente quando requerido pelo contexto corrente. Sob esta proposta a próxima seção descreve a migração do aplicativo Figuras Flutuantes para uma versão orientada a aspectos. Serão descritos os aspectos que foram implementados sob a influência da convenção de classificação das RCE descrita no cap. 4. Os resultados obtidos e as conclusões finais serão descritos posteriormente.

5.3. A Versão POA do Aplicativo

Na versão POA foram mantidas as classes anteriormente descritas em sua versão OO. Entretanto foram adicionados ao sistema um total de seis aspectos onde cada um implementa uma RCE identificada no sistema.

Inicialmente será feita a identificação e modularização das responsabilidades comuns identificadas. Num segundo momento será aplicada a convenção sugerida cap. 4 para a classificação das RCE do sistema. Em paralelo seguirão as justificativas para as decisões determinaram o surgimento dos aspectos e os ganhos obtidos com a modularização das RCE.

5.3.1. A Modularização das Responsabilidades Comuns

Analisando o código do aplicativo é possível observar a existência de operações recorrentes dentro do sistema. Elas fazem referência ao tratamento de exceções, o que pode ser considerado como o exemplo mais típico de responsabilidade comum.

(37)

que são obsoletos quando a instância for inserida no contexto C2. Este conjunto de operações é descrito a seguir :

Classe Display

Importação de bibliotecas de recursos

import java.math.*; import java.util.*;

Declaração de atributos

private int displayWidth; private int displayHeight;

private static Color vermelho = Color.red; private static Color branco = Color.white; private static Color verde = Color.green; Graphics grafico; Image imagem; Registrador registrador; Figura[] listaDeFiguras; Linha linha; Implementação de métodos

public void atualizaLinhas(Graphics g, Figura rect, Figura proxRect, Color cor)

public void manipulaNavegacao(Graphics g) public void detectaColisao(Graphics g)

static boolean ocorreuColisao(Figura a, Figura b)

private void manipulaColisao(Graphics g, Figura a, Figura

Classe Registrador

Implementação de métodos

public synchronized Figura[] pegaFiguras()

Classe Figura

Importação de bibliotecas de recursos import java.math.*;

Declaração de atributos

int tempoVida = 500;

double maxXPos, minXPos, maxYPos, minYPos, maxZPos, minZPos,xPos, yPos, zPos;

int coordX, coordY, larg, alt;

boolean navegaDireita, navegaEsquerda,navegaAcima, navegaAbaixo, navegaParaFundo,

navegaParaSuperficie;

Implementação de métodos abstract void navega();

void morre(Registrador registrador)

Por meio da enumeração descrita acima pode ser observado que o conjunto de recursos exigidos para que as instâncias possam executar no contexto C1 é maior do

(38)

5.2.2.2. Herança de Operações Obsoletas ao Contexto C2

O resultado final da versão OO para o aplicativo Figuras Flutuantes foi um conjunto de classes que, criadas para serem executadas em dois contextos distintos C1 e

C2, foram implementadas de forma genérica.

Estas classes, independentemente de quaisquer dos dois contextos onde possam estar inseridas, agregam de forma permanente o conjunto de operações de deslizamento, conexão e colisão. A fig. 5.6 representa o ambiente de execução para a versão OO do aplicativo.

Figura 5.6 – Classes do Sistema sem a Modularização das RCE

D

iversas operações como importação de bibliotecas de recursos, declaração de atributos e implementação de métodos das classes são aplicáveis somente ao contexto C1 onde as operações de deslizamento, conexão e colisão são exigidas, mas

(39)

de métodos que são os métodos navega() e pintaFigura(), contribuindo também para o aumento de volume do código das classes conforme fig. 5.4. Outro fator negativo detectado na versão OO foi a ocorrência de referências entre as classes do sistema. A fig. 5.5 apresenta parte do código fonte da classe Display.

Ela referencia:

· Na linha 11 a classe Linha em seu método pintaLinha();

· Na classe Registrador na linha 18 em seu método pegaFiguras().

Estes métodos estão relacionados ao conjunto de operações utilizadas somente no contexto C1. Logo estas referências são obsoletas quando as instâncias estão inseridas no contexto C2 forçando a compilação constante de todo o conjunto de operações de deslizamento, colisão e conexão. Vide fig. 5.5 a seguir.

1 Import java.math.*; 2 Import java.awt.*; 3 Import java.lang.*; 4 Import java.util.*; 4

5 Public class Display extends Canvas 6 {

7 ... 8

9 public void atualizaLinhas(Graphics g, Figura rect, Figura proxRect, Color cor)

10 {

11 linha.pintaLinha(g, rect.xPos, rect.yPos, proxRect.xPos, proxRect.yPos, cor);

12 } 13

14 ... 15

16 public void manipulaNavegacao(Graphics g) 17 { 18 listaDeFiguras = registrador.pegaFiguras(); 19 ... 20 } 21 22 ... 23 }

(40)

- As instâncias quando inseridas no contexto C2 herdam o pool de operações dos

esquemas de deslizamento, conexão e colisão que para elas é obsoleta neste momento mas que são exigidas pelo contexto C1.

Nas próximas seções será feita a demonstração de segmentos de código implementados no aplicativo Figuras Flutuantes e que foram diretamente afetados pelas deficiências apontadas acima.

5.2.2.1. Entrelaçamento de Código

O entrelaçamento de código nas classes do sistema foi evidenciado de duas formas :

· Replicação constante do código referente ao tratamento de exceções(fig. 5.4);

· Dependência entre as classes do sistema pela referência no código de umas às outras.

1 Public class Circulo extends Figura 2 {

3 ... 4

5 void pintaFigura(Graphics g, double xPos, double yPos) 6 { 7 try 8 {...} 9 catch(Exception erroPintando) 10 {...} 11 } 12 13 void navega() 14 { 15 try 16 {...} 21 catch(Exception erroNavegando) 22 {...} 23 ... 24 }

Figura 5.4 - Replicação de Código para Tratamento de Exceções

O tratamento de exceções pode ser visto na implementação de várias classes do sistema. O modelo OO realmente não permite que este tipo de responsabilidade seja modularizado de uma forma natural. Por este motivo a classes Círculo, Triangulo e

(41)

b) Recuperar uma referência a um objeto Figura; c) Excluir uma referência a um objeto Figura.

· Classe SWFrame: esta classe representa a interface com o usuário, capturando os eventos que permitem a interação com o aplicativo;

· Classe Display: esta classe implementa o seguinte conjunto de responsabilidades: a) Suportar o esquema de deslizamento das figuras pela implementação do método

manipulaNavegacao();

b) Suportar o esquema de conexões das figuras pela implementação do método

atualizaLinhas();

c) Suportar o esquema de tempo de vida das figuras pela implementação dos métodos detectaColisao(), ocorreuColisao() e manipulaColisao();

d) Suportar a repintura das figuras com a invocação dos métodos de sua superclasse

Canvas.

5.2.2. As Deficiências Detectadas

A análise do código do aplicativo em sua versão OO evidenciou um conjunto de deficiências que caracterizam um menor grau de otimização de algumas classes do sistema em função dos seguintes fatores:

· Entrelaçamento de código:

- Replicação de código referente ao tratamento de exceções aumentando o

volume e a complexidade do código fonte;

- Ocorrência de referências entre as classes do sistema pela invocação de métodos

de outras classes;

(42)

É interessante frisar novamente que foram desconsideradas a aplicação de recursos mais sofisticados como a implementação de interfaces ou a aplicação de padrões de projeto que poderiam contribuir para a melhoria da qualidade da arquitetura do sistema. A arquitetura deste aplicativo, obviamente muito simples, procura apenas avaliar as possíveis contribuições do modelo orientado a aspectos no desenvolvimento de projetos de software reutilizáveis.

5.2.1. As Responsabilidades para as Classes do Sistema

Segue abaixo a descrição das responsabilidades para as classes do sistema em sua versão OO. As classes definem, além de suas responsabilidades primárias, uma série de responsabilidades secundárias que serão comentadas mais adiante.

· Classe Figura: implementa um conjunto de métodos abstratos que serão herdados por suas subclasses Circulo, Retangulo e Triangulo. São eles os método pintaFigura(), navega() e também o método morre(). É a representação abstrata de

uma figura no plano;

· Classes Circulo, Triangulo e Retangulo: as responsabilidades destas classe são: a) Encapsular atributos relacionados à sua posição atual no plano;

b) Implementar seu próprio método de pintura com a sobreposição do método abstrato pintaFigura() herdado de sua superclasse Figura;

c) Implementar sua própria forma de deslocamento no plano pela sobreposição do método navega() herdado de sua superclasse Figura;

· Classe Linha: encapsula atributos relacionadas às coordenadas de início e fim da linha no plano e também o seu desenho no plano;

· Classe Registrador: esta classe tem como responsabilidade a manutenção da estrutura que armazena as referências aos objetos Figura instanciados durante o tempo de execução. Ela implementa os métodos que possibilitam:

(43)
(44)

O contexto C1 permite a criação de um conjunto de figuras num plano e realiza algumas operações sobre estas figuras como possibilitar sua flutuação numa determinada direção, sua conexão com as demais figuras de mesmo tipo e determinar o esgotamento do seu tempo de vida. Será visto posteriormente que o contexo C2 é um contexto onde existe a exigência de um número mais reduzido de operações.

5.1.2. O Contexto C2

Neste contexto a interface do aplicativo permanece inalterada. Ela também apresenta um plano no espaço onde são criadas figuras geométricas de três tipos que podem ser círculos, retângulos ou triângulos.

As figuras continuam sendo criadas à partir da iteração do usuário com o aplicativo. A interface apresentada é a mesma e disponibiliza três botões para criação de figuras que à medida que são pressionados criam novas figuras que flutuam no plano. Cada botão é destinado à criação de um dos três tipos de figura disponíveis. Estão disponíveis um botão para criação de círculos, um botão para criação de triângulos e um botão para criação de retângulos. A interface pôde ser vista anteriormente na fig. 5.1.

A diferença entre este contexto e o contexto C1 visto anteriormente se dá ao nível das operações exigidas por cada um. Enquanto no contexto C1 as operações do esquema de deslizamento, conexão e colisão são requisitadas, no contexto C2 elas são obsoletas. Neste contexto as figuras criadas no plano são entidades estáticas, não flutuam logo não colidem. As linhas de conexão entre as figuras agora não são exigidas. As classes do sistema no entanto são as mesmas implementadas para o contexto C1 e declaram todo um conjunto de operações que permitem o seu reuso em ambos os contextos. A estrutura das classes do sistema poderá ser vista em detalhes na próxima seção.

5.2. A Versão OO do Aplicativo

Este aplicativo em sua versão puramente orientada a objetos foi concebido com a declaração de um total de oito classes. A classe abstrata Figura deriva as classes

Circulo, Triangulo e Retangulo. São declaradas ainda as classes Linha, Registrador, Display e SWFrame, conforme pode ser visto na fig. 5.3.

(45)

Figura 5.1 - Esquema de Conexões do Aplicativo

Esta exigência do contexto C1 determina o esquema de sobrevivência das figuras. A fig. 5.2 mostra o aplicativo no momento da colisão entre figuras.

Referências

Documentos relacionados

E é justamente por uma doença respiratória, sistema do qual a boca faz parte, que a personagem morre, sendo a boca um dos primeiros objetos da sexualidade

Nesse sentido, entende-se que escola deveria procurar desenvolver um trabalho baseado em brincadeiras, incentivando as crianças por meio do brincar, pois seria um passo

Kulčar 40 , encontrou benefícios semelhantes (Tabela 3) e, além disso, ao acompanhar os membros permanentes do grupo por um período de 10 anos, constatou uma

A origem do nome Açaí é que nós justamente tivemos o trabalho né, foi o processo foi feito com o SEBRAE né, foi dado as aulas pra nós, aí então, lá no curso ela pediu pra

A função gerente de obras torna-se cada vez mais necessária na construção civil, pois o setor está cada vez mais desenvolvendo e aprimorando a área de coordenação

Na Nova Zelândia em sistemas pastoris as vacas produzem em média 17 litros de leite ao dia, enquanto nos produtores analisados neste estudo a média de

Após a colheita, normalmente é necessário aguar- dar alguns dias, cerca de 10 a 15 dias dependendo da cultivar e das condições meteorológicas, para que a pele dos tubérculos continue

Para preparar a pimenta branca, as espigas são colhidas quando os frutos apresentam a coloração amarelada ou vermelha. As espigas são colocadas em sacos de plástico trançado sem