This watermark does not appear in the registered version - http://www.clicktoconvert.com
106
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;
}
106
This watermark does not appear in the registered version - http://www.clicktoconvert.com
105
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
Descritores Primitivos Relacionados ao Texto
105
This watermark does not appear in the registered version - http://www.clicktoconvert.com
104
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
Id)
or
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
Id)
or
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
Id, ...)
or
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
junção baseados no controle de fluxo do programa.
104
This watermark does not appear in the registered version - http://www.clicktoconvert.com
103
TIPO
Handler(Tipo)
DEFINIÇÃO
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
AdviceExecution()
DEFINIÇÃO
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:
1) pointcut valorInt(int x): call(Linha.*(int)) && args(x);
103
This watermark does not appear in the registered version - http://www.clicktoconvert.com
102
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();
}
}
102
This watermark does not appear in the registered version - http://www.clicktoconvert.com
101
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();
}
}
101
This watermark does not appear in the registered version - http://www.clicktoconvert.com
100
ANEXO 1
Modelo Aspectj para Pontos de Junção
Nome
Method
Definição
quando um método é chamado
call
Method
quando o corpo do método está sendo executado
executio
n
Construc
quando o construtor do objeto está sendo chamado
tor call
Construc
quando o corpo do construtor está sendo executado. Nenhum valor é retornado
tor
deste tipo de ponto de junção
executio
n
Static
quando um inicializador estático para a classe é executado. Nenhum valor é
initiali
retornado deste tipo de ponto de junção
zer
executio
n
Field
para campos do tipo não constante. Campos do tipo constante não são pontos de
referenc
junção em função do Java os utilizar no processo de inline
e
Handler
Quando um manipulador de exceção executa. Este tipo de ponto de junção
executio
requer um parâmetro que é o tipo de exceção manipulada. Nenhum valor retorna
n
deste tipo de ponto de junção
Advice
quando o corpo de um advice é executado.
executio
n
100
This watermark does not appear in the registered version - http://www.clicktoconvert.com
99
ANEXOS
99
This watermark does not appear in the registered version - http://www.clicktoconvert.com
98
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.
98
This watermark does not appear in the registered version - http://www.clicktoconvert.com
97
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://wwwi2.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.
97
This watermark does not appear in the registered version - http://www.clicktoconvert.com
96
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.
96
This watermark does not appear in the registered version - http://www.clicktoconvert.com
95
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.
95
This watermark does not appear in the registered version - http://www.clicktoconvert.com
94
·
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.
94
This watermark does not appear in the registered version - http://www.clicktoconvert.com
93
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:
93
This watermark does not appear in the registered version - http://www.clicktoconvert.com
92
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)
92
This watermark does not appear in the registered version - http://www.clicktoconvert.com
91
·
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
91
This watermark does not appear in the registered version - http://www.clicktoconvert.com
90
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:
90
This watermark does not appear in the registered version - http://www.clicktoconvert.com
89
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á
89
This watermark does not appear in the registered version - http://www.clicktoconvert.com
88
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
ThisJoinPoint indicará a assinatura para o ponto de junção encontrado.
88
This watermark does not appear in the registered version - http://www.clicktoconvert.com
87
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.
87
This watermark does not appear in the registered version - http://www.clicktoconvert.com
86
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.
86
This watermark does not appear in the registered version - http://www.clicktoconvert.com
85
·
call(Graphics
double)):
Figura+.pintaFigura(Graphics,
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
85
This watermark does not appear in the registered version - http://www.clicktoconvert.com
84
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;
84
This watermark does not appear in the registered version - http://www.clicktoconvert.com
83
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
do tipo introdução.
83
This watermark does not appear in the registered version - http://www.clicktoconvert.com
82
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.
82
This watermark does not appear in the registered version - http://www.clicktoconvert.com
81
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()
{...}
}
Figura 5.12 – O Aspecto Navegacao
81
This watermark does not appear in the registered version - http://www.clicktoconvert.com
80
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
80
This watermark does not appear in the registered version - http://www.clicktoconvert.com
79
Classe : Registrador
Tabulação RCE
LISTA DE CONTEXTOS 1
1
OPERAÇÕES
(C1)
OPERAÇÕES DE PROTEÇÃO
X
2
(C2)
3
4
5
6
7
8
9
10
...
...
...
...
...
...
...
TAO
50%
DO REGISTRO
2
OUTRAS OPERAÇÕES DO
X
X
100%
REGISTRO DOS OBJETOS
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.
79
This watermark does not appear in the registered version - http://www.clicktoconvert.com
78
·
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.
Classe : Display
Tabulação RCE
LISTA DE CONTEXTOS 1
1
2
(C2)
3
4
5
6
7
8
9
10
...
...
...
...
...
...
...
TAO
OPERAÇÕES
(C1)
OPERAÇÕES DE
X
50%
OPERAÇÕES DO ESQUEMA DE X
50%
TRATAMENTO DE COLISÃO
2
NAVEGAÇÃO
3
50%
OPERAÇÕES DO ESQUEMA DE X
CONEXÕES
4
OUTRAS OPERAÇÕES DE
X
X
100%
MANIPULAÇÃO DOS DADOS
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.
78
This watermark does not appear in the registered version - http://www.clicktoconvert.com
77
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.
Classe : Circulo, Retangulo,
Tabulação RCE
Triangulo
LISTA DE
1
2
3
4
5
6
7
8
9
10
...
...
...
...
...
...
...
TAO
CONTEXTOS
(C1) (C2)
OPERAÇÕES
1
OPERAÇÕES DE
X
X
100%
PINTURA
2
OPERAÇÕES DO
50%
X
ESQUEMA DE
NAVEGAÇÃO
3
OUTRAS
X
X
100%
OPERAÇÕES DE
MANIPULAÇÃO DOS
DADOS
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:
77
This watermark does not appear in the registered version - http://www.clicktoconvert.com
76
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.
76
This watermark does not appear in the registered version - http://www.clicktoconvert.com
75
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.
75
This watermark does not appear in the registered version - http://www.clicktoconvert.com
74
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
74
This watermark does not appear in the registered version - http://www.clicktoconvert.com
73
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
trataExcecao.
73
This watermark does not appear in the registered version - http://www.clicktoconvert.com
72
É 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
72
This watermark does not appear in the registered version - http://www.clicktoconvert.com
71
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
responsabilidades comuns identificadas. Num segundo momento
das
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.
71
This watermark does not appear in the registered version - http://www.clicktoconvert.com
70
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
70
This watermark does not appear in the registered version - http://www.clicktoconvert.com
69
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
Diversas 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
69
This watermark does not appear in the registered version - http://www.clicktoconvert.com
68
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
2
3
4
4
5
6
7
8
9
Import
Import
Import
Import
java.math.*;
java.awt.*;
java.lang.*;
java.util.*;
Public class Display extends Canvas
{
...
10
11
12
13
14
15
16
17
18
19
20
21
22
23 }
public void atualizaLinhas(Graphics g, Figura rect, Figura
proxRect, Color cor)
{
linha.pintaLinha(g, rect.xPos, rect.yPos, proxRect.xPos,
proxRect.yPos, cor);
}
...
public void manipulaNavegacao(Graphics g)
{
listaDeFiguras = registrador.pegaFiguras();
...
}
...
Figura 5.5 – Referências entre as Classes do Sistema
68
This watermark does not appear in the registered version - http://www.clicktoconvert.com
67
-
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
Retangulo replicam o código referente ao mesmo tipo de exceção no mesmo conjunto
67
This watermark does not appear in the registered version - http://www.clicktoconvert.com
66
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;
·
Permanente herança das operações de deslizamento, conexão e colisão:
66
This watermark does not appear in the registered version - http://www.clicktoconvert.com
65
É 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:
a) Armazenar uma referência a um objeto Figura;
65
This watermark does not appear in the registered version - http://www.clicktoconvert.com
64
Figura 5.3 - Diagrama de Classes do Sistema
64
This watermark does not appear in the registered version - http://www.clicktoconvert.com
63
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.
63
This watermark does not appear in the registered version - http://www.clicktoconvert.com
62
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.
Figura 5.2 - Colisão Entre Figuras
62
This watermark does not appear in the registered version - http://www.clicktoconvert.com
61
de comportamento do aplicativo para este contexto: os três tipos diferentes de figuras
não se misturam no momento das conexões. Este critério determina o esquema de
conexões entre as figuras que é determinado da seguinte forma:
·
Círculos podem se conectar somente a outros círculos, não podendo se conectar a
retângulos ou triângulos;
·
Retângulos podem se conectar somente a outros retângulos, não podendo se
conectar a círculos ou triângulos;
·
Triângulos podem se conectar somente a outros triângulos, não podendo se conectar
a retângulos ou círculos.
A fig. 5.1 mostra o aplicativo no momento em que o plano é povoado por
diversos círculos, retângulos e triângulos, caracterizando o esquema de conexões do
contexto C1 descrito anteriormente.
O esquema de deslizamento e o esquema de conexões mencionados
anteriormente são duas exigências do contexto C1 e podem ser observadas durante a
execução do aplicativo. Uma terceira exigência deste contexto diz respeito ao tempo de
sobrevivência das figuras. As figuras criadas neste contexto não permanecem flutuando
no plano por tempo indeterminado mas sim por um tempo pré-determinado. Expirando
este tempo as figuras criadas são apagadas.
Eventualmente, em caso de colisão, elas podem também ser apagadas antes
mesmo deste tempo expirar. À medida que figuras de tipos diferentes flutuam podem
ocorrer colisões, visto que o esquema de deslizamento determina que estas se deslocam
em direções diferentes. Estas colisões, quando ocorrem, determinam o fim precoce do
tempo de vida das figuras envolvidas na colisão. As figuras que colidem são então
apagadas do plano.
61
This watermark does not appear in the registered version - http://www.clicktoconvert.com
60
De acordo com a implementação atual, as classes do sistema podem ser
inseridas em dois contextos diferenciados. O primeiro deles foi nomeado como C1 e
implementa uma série de operações peculiares que serão descritas em detalhes a seguir.
O segundo contexto é nomeado como C2 e é mais simplificado que o primeiro pois não
requer o mesmo conjunto de operações exigidas pelo anterior. As seções a seguir
apresentam a descrição das características destes dois contextos onde as classes do
sistema podem ser inseridas.
5.1.1. O Contexto C1
O contexto C1 requer uma série de operações que são exigidas das classes
do sistema e que não são exigidas no contexto C2 que será visto logo adiante. Este
conjunto de operações é relacionado à atividades de deslizamento, conexão e colisão
entre as figuras e serão descritos no decorrer desta seção.
Neste contexto uma das características de comportamento do aplicativo
determina que as figuras criadas flutuem em sentidos diferentes no plano. A direção na
qual cada figura flutua no plano se dá em função de seu tipo, constituindo assim o
esquema de deslizamento das figuras. O esquema de deslizamento é definido da
seguinte forma:
·
Os círculos devem flutuar no sentido diagonal, avançando ao mesmo tempo nos
eixos x e y;
·
Os triângulos devem flutuar na vertical, avançando somente no eixo y;
·
Os retângulos devem flutuar na horizontal, avançando somente no eixo x.
Na forma como o aplicativo se apresenta, o mesmo tipo de figura pode ser
criado diversas vezes. Assim, em determinado momento, o plano pode ser povoado por
vários círculos, triângulos e retângulos.
Outra característica do contexto C1 é que as figuras, à medida que são
criadas, são conectadas por linhas. Estas linhas deslizam no plano, acompanhando o
deslizamento das figuras mantendo a noção de que estas se mantêm constantemente
conectadas. Esta conexão não é feita ao acaso. É feita com base em outra característica
60
This watermark does not appear in the registered version - http://www.clicktoconvert.com
59
Capítulo V
Um Projeto de Software Reutilizável Utilizando POA –
Uma Abordagem Otimizada da Orientação a Aspectos
Como forma de avaliar a aplicação de aspectos no desenvolvimento de
projetos de software reutilizáveis foi desenvolvido um aplicativo gráfico em duas
versões. A primeira utilizando uma abordagem totalmente OO e a segunda sob o
paradigma da orientação a aspectos. Ao longo do desenvolvimento deste capítulo é feita
a descrição detalhada do aplicativo Figuras Flutuantes com os seguintes tópicos:
·
As características gerais de comportamento do aplicativo nos dois contextos
propostos;
·
A estrutura do aplicativo em sua primeira versão numa abordagem puramente OO
com suas classes e seus comportamentos;
·
A migração para o modelo orientado a aspectos visando a otimização das classes do
sistema;
·
Conclusão a respeito dos resultados obtidos.
5.1. Características Gerais do Aplicativo
Figuras Flutuantes é um aplicativo gráfico simples que 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 são criadas à partir da iteração do usuário com o aplicativo. A
interface apresentada 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, conforme fig. 5.1.
59
This watermark does not appear in the registered version - http://www.clicktoconvert.com
58
contexto Cb
acessoDados
{controle de concorrência}
{acesso a dados (gravação)}
{acesso a dados (leitura)}
contexto Cc
{comunicação remota}
{ colaboração com outros objetos}
{ sincronismo}
contexto Ca
Figura 4.10 – Nova Configuração de Contextos para a Classe acessaDados
No próximo capítulo é conduzida a implementação e a restruturação do
aplicativo Figuras Flutuantes para uma versão POA. O critério de classificação das RCE
anteriormente sugerida como convenção didática será aplicada sobre as classes do
sistema e os resultados serão comentados em seguida.
58
This watermark does not appear in the registered version - http://www.clicktoconvert.com
57
corrente. Poderíamos então fatorar as operações genéricas e complexas da classe
acessaDados em um conjunto de operações específicas e dirigidas a contexto. Os
recursos de controle de concorrência por exemplo só seriam aplicados à classe
acessaDados em contextos onde este controle fosse efetivamente exigido, evitando
assim algum overhead provocado por estas operações. Se fosse necessário algum tipo
de iteração com outras classes do sistema, estas operações seriam então agregadas e
assim por diante.
Isto contudo sem aumentar o grau de complexidade e entrelaçamento dos
componentes do sistema – muitos métodos ou classes intermediárias o que gera
interdependência entre módulos, diminui o grau de reusabilidade e exige um número
maior de customizações manuais – o que é o efetiva contribuição da POA.
É interessante observar que um ponto crítico à convenção de classificação
das RCE aqui apresentada, é a ocorrência de manutenção da classe tabulada. À medida
que novos contextos se abrem ou se fecham para a classe e novas operações são
inseridas/removidas, a tabela RCE para a classe pode ter seus valores de TAO alterados.
Este fato por certo exigirá a manutenção dos aspectos pois novas RCE surgirão ou serão
removidas. Esta abordagem simplificada no entanto não considera este fato. A fig. 4.10
mostra uma nova possível configuração de contextos para a classe acessaDados.
A partir desta nova configuração de contextos para a classe acessaDados, as
operações de controle de concorrência passam a ser exigidas no conjunto total de
contextos para a classe. Logo haveria uma importante alteração na sua Tabela RCE
original pois a TAO destas operações adquiriria um novo valor, subindo de 33% para
100%. Isto justificaria, em acordo com a simples convenção aqui adotada, que esta
operação fosse então modularizada em um aspecto. Entretanto estas questões não são o
foco deste trabalho e como tal não serão discutidas.
57
This watermark does not appear in the registered version - http://www.clicktoconvert.com
56
Figura 4.9 – Instâncias da Classe acessaDados e as RCE Agregadas
A fig. 4.9 apresenta três contextos diferenciados nomeados como C1, C2 e
C3. Pode ser observado que as instâncias i1, i2 e i3 da classe acessaDados agregam
apenas as RCE relativas ao seu próprio contexto resultando na seguinte configuração:
·
Instância i1 herda as operações de leitura e gravação implementadas na classe
acessaDados e agrega também as RCE para tratamento de sincronismo
implementadas no aspecto trataSincronismo caracterizando o contexto C1;
·
Instância i2 herda as operações de leitura e gravação implementadas na classe
acessaDados e agrega também as RCE para tratamento de acesso remoto e
sincronismo implementadas nos aspectos acessoRemoto e trataSincronismo
caracterizando o contexto C2;
·
Instância i3 herda as operações de leitura e gravação implementadas na classe
acessaDados e agrega também as RCE para tratamento de sincronismo
implementadas no aspecto trataSincronismo caracterizando o contexto C3.
Identificar e modularizar as RCE na forma de aspectos permitirá que a
classe acessaDados implemente apenas as operações que representam sua estrutura
primária. Desta forma, cada instância desta classe, quando necessário, agregará o
apenas conjunto de operações especializadas realmente aplicáveis ao seu contexto
56
This watermark does not appear in the registered version - http://www.clicktoconvert.com
55
duas novas classes denominadas como Sub1 e Sub2 e mostra a agregação diferenciada
de operações pela agregação de RCE modularizadas em aspectos.
Figura 4.8 – Classe acessaDados Agregando RCE
Como pode ser visto a superclasse acessaDados agrega as operações de
comunicação remota modularizadas no aspecto acessoRemoto. As suas subclasses Sub1
e Sub2 no entanto agregam apenas operações de sincronismo modularizadas no aspecto
trataSincronismo. Em comum as classes terão apenas as operações de leitura e gravação
originalmente implementadas na superclasse acessaDados. Concluindo, as operações de
acesso remoto agregadas pela superclasse não serão herdadas pelas suas subclasses.
O que garante tal fato é o tecedor que implementado sob a abordagem
dinâmica garante a permanência da classe original gerando a classe tecida. Esta,
conforme já mencionado na seção 3.6, assume o caráter de aspin que é a classe
costurada ao aspecto acessoRemoto.
Estando claro o conjunto de RCE a ser agregado pela classe acessaDados
em cada contexto especifico, é possível garantir que um aspecto que implemente uma
determinada RCE necessária a este contexto venha a afetar a apenas determinadas
instâncias desta classe. Assim, é possível aplicar a cada instância, individualmente, o
conjunto de operações RCE relativas ao contexto onde a instância particular estará
inserida.
55
This watermark does not appear in the registered version - http://www.clicktoconvert.com
54
métodos conecta() e transmite() nas linhas 9 e 12 são introduzidos na classe por meio
do mecanismo de introduções.
1 aspect acessoRemoto
2 {
3
private socket acessaDados.skt;
4
private int acessaDados.porta;
5
6
after/before/around(): (...)
7
{...}
8
9
public void acessaDados.conecta()
10
{...}
11
12
public void acessaDados.transmite()
13
{...}
14}
Figura 4.6 – Aspecto acessoRemoto
O tecedor poderia então ser invocado para que o aspecto acessoRemoto
fosse costurado a alguma instância da classe acessaDados ou de alguma subclasse caso
alguma operação de acesso remoto fosse exigido pelo contexto corrente. A sintaxe
AspectJ poderia ser aplicada nesta chamada conforme fig. 4.7.
Class Principal
{
boolean exigeAcessoRemoto;
...
public Principal()
{
...
if exigeAcessoRemoto then
%ajweaver acessoDados.ajava acessoRemoto.ajava;
acessaDados aD = new acessaDados(...)
...
}
...
}
Figura 4.7 – Tecendo o Aspecto acessoRemoto
Havendo então estruturado a classe acessaDados com base na convenção
aqui adotada, suas instâncias ou as instâncias de suas subclasses poderão herdar apenas
o conjunto de operações fundamentais que neste caso são as operações de leitura e
gravação. As demais operações poderão ser agregadas à medida do necessário pela
chamada do tecedor. A fig.4.8 apresenta a especialização da classe acessaDados em
54
This watermark does not appear in the registered version - http://www.clicktoconvert.com
53
CLASSE : acessaDados
ESTRUTURA PRIMÁRIA
CONJUNTO RCE
Atributos :
atr1, atr3, atr4.
Métodos:
Atributos :
Atr2, atr5, atr6, atr7, atr8,
atr9.
Métodos:
{acesso a dados (leitura)}
{acesso a dados (gravação)}
{colaboração}
{ comunicação remota}
{ concorrência}
{sincronismo}
Figura 4.4 – Identificação das RCE da Classe acessaDados
Conforme pôde ser visto na fig 4.3 as operações de colaboração,
comunicação remota, sincronismo e concorrência cujos TAO obtidos foram menores
que 100% são desligadas da estrutura primária da classe. Serão modularizadas como
aspectos conforme pode ser visto na fig. 4.5.
aspecto acessoRemoto
aspecto trataConcorrencia
Atr5, atr6
Atr7
{ operações de comunicação
remota}
{operações de concorrência}
acessoDados
atr1, atr3, atr4
{operações de acesso a dados (gravação)}
{operações de acesso a dados (leitura)}
aspecto trataColaboracao
aspecto trataSincronismo
Atr2
Atr8, atr9
{operações de colaboração}
{operações de sincronismo}
Figura 4.5 – Classe acessaDados Restruturada
A fig. 4.6 mostra
o segmento de código que poderia representar a
implementação em detalhe do aspecto acessoRemoto. Ele foi implementado com base
na RCE de comunicação remota acima mencionada. Os atributos skt e porta e os
53
This watermark does not appear in the registered version - http://www.clicktoconvert.com
52
Classe : acessoDados
Tabulação RCE
LISTA DE
1
2
3
4
5
6
7
8
9
10
(Ca)
(Cb)
(Cc)
...
...
...
...
...
...
...
TAO
CONTEXTOS
OPERAÇÕES
1
COMUNICAÇÃO
X
33%
REMOTA
2
ACESSO À BASE DE
X
X
X
100%
X
X
X
100%
DADOS (LEITURA)
3
ACESSO À BASE DE
DADOS (GRAVAÇÃO)
4
CONTROLE DE
X
33%
CONCORRÊNCIA
5
SINCRONISMO
X
33%
6
COLAB. COM OUTROS
X
33%
OBJETOS
Figura 4.3 – Tabulação RCE da Classe acessaDados
A tabulação RCE vista acima permitiu a determinação da TAO para classe
acessaDados considerando o conjunto total de contextos onde ela possa vir a ser
inserida(fig. 4.1). A seguinte situação pode ser observada :
·
As operações de leitura e gravação alcançaram taxa de aplicação de 100% pois são
agregadas em todos os contextos que são Ca, Cb e Cc;
·
As operações de sincronismo, controle de concorrência, acesso remoto e
colaboração alcançaram uma taxa de apenas 33% pois são exigidas apenas em
contextos específicos.
Consultando a tabela RCE para a classe acessaDados vista na fig 4.3 é
possível então classificar o conjunto RCE da classe separando-o de sua estrutura
primária. O resultado desta separação de responsabilidades para a classe pode ser visto
na fig. 4.4.
52
This watermark does not appear in the registered version - http://www.clicktoconvert.com
51
implementados na classe, de modo a obter a visualização da frequência de aplicação das
operações implementadas.
Sugere-se que esta medição seja feita relacionando-se as operações da classe
ao conjunto total de contextos onde a classe possa vir a executar. Como resultado final
deve ser obtido algum valor numérico que indique a taxa de aplicação das operações
durante o período de execução das instâncias da classe.
Será convencionado neste trabalho que, executada a medição da taxa de
aplicação das operações(TAO), somente as operações que sejam aplicáveis a todo o
conjunto de contextos para a classe sejam codificadas como sua estrutura primária. As
demais operações ficam caracterizadas como sendo RCE a serem modularizadas em
aspectos.
Este trabalho sugere que o procedimento de medição da TAO possa ser
realizado com o auxílio de uma ferramenta aqui nomeada como Tabela RCE. A tabela
RCE foi idealizada como uma estrutura simples cuja única função é facilitar a
visualização da TAO para as operações da classe. Ela disponibiliza:
·
Um conjunto de linhas numeradas que discrimina o conjunto total de operações que
a classe realiza;
·
Um conjunto de colunas numeradas que determina o conjunto total de contextos
para a classe por meio da combinação do conjunto de operações necessários àquele
contexto;
·
Uma coluna que determina o percentual de aplicação das operações com base no
conjunto total dos possíveis contextos.
Como exemplo será utilizda a classe acessaDados vista anteriormente na
fig. 4.1. A tabulação RCE para esta classe resultará na fig. 4.3 que pode ser vista logo
adiante.
51
This watermark does not appear in the registered version - http://www.clicktoconvert.com
50
Quanto à Aplicabilidade ao Conjunto Total de Contextos
·
Responsabilidade Comum: pode ser aplicável ao conjunto total de
contextos como por exemplo o tratamento de exceções. Entretanto pode vir a
ser aplicável a apenas uma parte deste conjunto como por exemplo o
controle de concorrência;
·
RCE: é caracterizada pela aplicação a apenas parte do conjunto tal de
contextos onde a classe possa vir a ser inserida.
Pode ser observado pelas características enumeradas acima que as
semelhanças entre as responsabilidades comuns e as RCE de fato existem o que as torna
até certo ponto semelhantes. Entretanto existem duas diferenças fundamentais entre
elas:
·
Ao contrário da responsabilidade comum, a RCE não é recorrente dentro das classes
do sistema;
·
Ao contrário da responsabilidade comum, a RCE é sempre modularizável.
A característica da RCE, conforme já mencionado, é o fato de que ela pode
realmente ser modularizada na classe mas em determinados contextos ela se
transformará em uma operação obsoleta e não aplicável. Este é o fato que justifica sua
modularização em aspectos.
4.3. Uma Convenção para Identificação das RCE
Conforme já mencionado não existem métricas definidas para a
identificação das responsabilidades comuns. Tampouco este trabalho desenvolve algum
formalismo científico para isso. O foco aqui é apenas a aplicação de aspectos como
ferramenta de desenvolvimento de projetos de software reutilizáveis.
Este capítulo formaliza uma convenção a ser seguida para que possa ser
feita a identificação das responsabilidades do tipo RCE nas classes do sistema. Como
procedimento padrão sugere-se que se faça uma medição sobre os métodos
50
This watermark does not appear in the registered version - http://www.clicktoconvert.com
49
Observando a fig. 4.2 é possível descrever as semelhanças e diferenças entre
uma RCE e uma responsabilidade comum. Vejamos então:
Quanto ao Tipo(Responsabilidade Primária/Secundária)
·
Responsabilidade comum: por definição ela não se encaixa sob o conceito de
responsabilidade primária. Sua característica principal que é a recorrência a
define sempre como uma responsabilidade secundária nas classes do sistema.
Ex: o tratamento de exceções;
·
RCE: pode representar uma responsabilidade secundária da classe como é o
caso do método trataColisao() da classe Display implementada no cap. 5 deste
trabalho. Mas também pode representar uma responsabilidade primária como é o
caso do método pintaFigura() implementado nas subclasses de Figura e pode
ser visto em detalhes no cap. 5.
Quanto à Possibilidade de Modularização
·
Responsabilidade comum: Pode não ser modularizável como é o caso do
tratamento de exceções. Cabe observar que da mesma forma que o tratamento de
exceções, que pode ser considerado como o exemplo mais típico de
responabilidade comum, qualquer operação recorrente dentro das classes do
sistema pode ser considerada como tal visto que não existem métricas bem
definidas que determinem sua classificação;
·
RCE: Uma RCE é sempre modularizável pois o que a caracteriza não é a
recorrência mas sim o fato de ser uma operação que se aplica a apenas parte do
conjunto total de contextos onde a classe possa vir a ser inserida.
Quanto à Recorrência
·
Responsabilidade comum: por definição ela é sempre recorrente dentro das
classes do sistema;
·
RCE: não é recorrente. A recorrência a classificaria como responsabilidade
comum.
49
This watermark does not appear in the registered version - http://www.clicktoconvert.com
48
4.2. Responsabilidade Comum x RCE
O modelo orientado a aspectos oferece grande ênfase na conceituação e na
modularização das responsabilidades comuns o que aliás é sua origem, embora não
proponha qualquer formalismo que conduza a sua classificação. A proposta de
(BOOLERT, 2000) derivou inúmeras discussões relativas a como produzir aspectos
legíveis, reusáveis e mesmo propostas para representação dos aspectos em tempo de
projeto entre outros. Entretanto a ênfase foi mantida sempre em torno do termo
responsabilidade comum. Uma RCE não se enquadra estritamente sob o conceito da
responsabilidade comum. Uma RCE é tipicamente caracterizada como uma operação
que só será aplicada -seja em instâncias da própria classe ou de suas subclasses - a
determinados contextos o que as torna obsoletas em outros.
Assim, se for considerado o conjunto total dos possíveis contextos onde a
classe acessaDados possa vir ser inserida seja ele Ca, Cb ou Cc, as RCE desta classe
serão identificadas como aquelas operações que se aplicarão a apenas a um ou no
máximo uma parte deste conjunto total de contextos.
A análise de fatores que caracterizam as responsabilidades comuns e a sua
comparação com os fatores que caracterizam as RCE resultou na fig. 4.2. Ela é um
comparativo entre RCE e responsabilidades comuns procurando detectar semelhanças e
diferenças entre elas.
Responsabilidade Comum
RCE
Resp. Primária
Não
Sim/Não
Operação Genérica
Sim/Não
Sim/Não
Modularizável
Não
Sim
Recorrente
Sim
Não
Aplica-se ao Conj. Total de
Sim/Não
Não
Contextos
Figura 4.2 - Responsabilidades Comuns x RCE
48
This watermark does not appear in the registered version - http://www.clicktoconvert.com
47
·
Apenas as operações de leitura e gravação são comuns aos três contextos
apresentados;
·
Operações de comunicação remota, sincronismo e colaboração são aplicadas apenas
ao contexto Ca;
·
Operações de controle de concorrência são aplicadas apenas ao contexto Cb.
O efeito imediato é que toda instância da classe acessaDados ou qualquer
instância de suas subclasses herdarão deliberadamente todo o pool de operações
declarados nesta classe. Este fato determina a seguinte situação:
·
Instâncias inseridas no contexto Ca herdam operações aplicadas especificamente aos
contextos Cb;
·
Instâncias inseridas no contexto Cb herdam operações aplicadas especificamente ao
contextos Ca;
·
Instâncias inseridas no contexto Cc herdam operações aplicadas especificamente aos
contextos Ca e Cb.
Surgem então dois fatores que determinam um grau menor de otimização da
classe acessaDados. O primeiro deles diz respeito ao tamanho do código executável
visto que mesmo as operações não necessárias ao contexto serão sempre compiladas
fazendo com que a instância arraste consigo vastas biblioteca de recursos, atributos e
métodos que não serão utilizados.
O segundo deles diz respeito à velocidade de execução que corre o risco de
tornar-se reduzida. Tome-se como exemplo o contexto Cc descrito acima. Neste
contexto são previstas apenas operações básicas de acesso a dados, no entanto as
operações de controle de concorrência herdadas podem gerar maior overhead pois serão
aplicadas sem necessidade eminente.
Algum benefício poderia ser obtido se as operações aplicadas apenas a um
contexto particular fossem agregadas pelas instâncias da classe somente quando estas
instâncias estivessem realmente inseridas neste contexto.
47
This watermark does not appear in the registered version - http://www.clicktoconvert.com
46
contexto Cb
acessoDados
{controle de concorrência}
{acesso a dados (gravação)}
{acesso a dados (leitura)}
contexto Cc
{comunicação remota}
{ colaboração com outros objetos}
{ sincronismo}
contexto Ca
Figura 4.1 – Contextos Aplicados à Classe acessaDados
Observando a classe acessaDados descrita na fig. 4.1 é possível perceber
que ela implementa operações básicas de acesso a dados como leitura e gravação. Ela
implementa também operações mais sofisticadas como controle de concorrência,
sincronismo, transmissão remota de dados e operações de colaboração com outras
classes do sistema.
Logo a classe acessaDados pode ser vista como um exemplo típico de
classe reusável, visto que pode ser aplicada aos três contextos diferenciados Ca, Cb e Cc
com a necessidade de poucas ou talvez nenhuma customização.
Entretanto, considere-se uma instância desta classe inserida em um contexto
específico seja ele Ca, Cb ou Cc. Conforme pode ser visto na fig. 4.1, certas operações
herdadas podem não ser necessárias num contexto particular. Todas as instâncias da
classe acessaDados herdarão uma gama de operações que, havendo sido declaradas
como fator determinante de reusabilidade, serão subtilizadas ou mesmo não utilizadas
levando-se em conta um contexto particular. Sob este enfoque as operações
implementadas na classe acessaDados se distribuem entre os três contextos
apresentados conforme segue:
46
This watermark does not appear in the registered version - http://www.clicktoconvert.com
45
Para que a classe acessaDados seja eficiente e reusável nos três contextos
definidos na fig. 4.1 logo adiante, ela deve implementar todas as funcionalidades
requeridas por eles. Definimos assim um exemplo típico de classe reusável.
Mas cabe mencionar que a complexidade da classe tem tendência a
aumentar à medida em que ela avança como uma solução mais geral.
Esta
complexidade é pouco desejável do ponto de vista da manutenção e os recursos às vezes
necessários para suportar esta generalidade muitas vezes afetam a performance de
execução. Podem ser considerados como exemplos destes recursos bibliotecas de
funções, estruturas de dados ou operações genéricas que provocam maior overhead do
que operações especializadas.
Uma alternativa para a classe acessaDados talvez fosse a modularização
destas operações em classes separadas mas o primeiro efeito negativo seria o
entrelaçamento de código pelo aumento de interdependência entre os módulos o que
afetaria a reusabilidade. O modelo OO nos deixa então duas escolhas a serem feitas:
·
Uma classe reusável que implemente todas as operações e seja independente porém
mais complexa;
·
Uma classe menos complexa mas que seja dependente de outras classes que
implementem partes de suas operações.
O primeiro ponto a considerar é que a dependência entre módulos é algo
difícil de gerenciar. Logo pensar nesta classe como um componente independente
dentro do sistema é algo sem dúvida muito vantajoso. A fig 4.1 permite visualizar a
posição da classe acessaDados ente os três supostos contextos Ca, Cb e Cc.
45
This watermark does not appear in the registered version - http://www.clicktoconvert.com
44
atributos e métodos declarados por uma classe. Como resultado implica que todas as
instâncias de uma classe e também todas as instâncias de suas subclasses herdarão todo
um conjunto de operações de forma deliberada.
O modelo OO não prevê mecanismos que permitam a distinção entre as
operações que realmente vão ser utilizadas por uma instância de classe em um contexto
particular daquilo que pode ser considerado como uma ‘herança inútil’. O termo
herança inútil pode ser entendido como uma referência a um atributo ou um método
declarado na classe e que foi herdado pela sua instância, mas não se aplica ao contexto
onde esta instância se encontra inserida num determinado momento.
O mecanismo de herança representa algo de muito vantajoso visto que não
precisamos gastar tempo refazendo operações que já foram codificadas uma vez. São
obtidas então modularidade, reusabilidade e toda a gama de vantagens oferecidas pelo
modelo OO. Entretanto as RCE estão relacionadas à parte menos vantajosa do
mecanismo de herança que é a sua efetividade nos termos descritos no parágrafo
anterior.
Como forma de exemplificar tome-se então uma classe de acesso a dados
chamada acessaDados. Esta classe foi projetada para ser executada em três contextos
diferenciados aqui nomeados como Ca, Cb e Cc. Cada um destes contextos requer da
classe um determinado conjunto de funcionalidades. O conjunto total de operações
requeridas pelos três contextos são :
·
Acesso a dados (leitura e gravação);
·
Controle de concorrência;
·
Comunicação remota;
·
Sincronismo;
·
Operações de colaboração com outros objetos do sistema.
44
This watermark does not appear in the registered version - http://www.clicktoconvert.com
43
Capítulo IV
Desenvolvimento de Projetos de Software Reutilizáveis
– Uma Visão Diferenciada do Modelo Orientado a
Aspectos
O modelo de aspectos permite de fato a modularização das
responsabilidades comuns de uma forma natural, eliminando a replicação de código que
é seu maior objetivo. A contribuição deste trabalho no entanto está em lançar uma visão
diferenciada sobre a POA, objetivando a aplicação do modelo orientado a aspectos no
desenvolvimento de projetos de software reutilizáveis.
Desta forma, ao invés de aplicar a POA apenas como um mero recurso que
permite modularização das responsabilidades comuns, aplica-la também como uma
ferramenta que possa ser empregada na fatoração da classe em um conjunto de RCE
visando aumento do seu grau de reusabilidade. O que se espera como resultado final
são classes que mantenham o seu grau de generalidade pela agregação de operações
específicas para um determinado contexto na forma de aspectos.
4.1. O Conceito de RCE
O conceito de responsabilidade comum se justifica
à partir de uma
característica do modelo OO: as propriedades recorrentes dentro do sistema e que
extrapolam as fronteiras da classe. O que caracteriza as RCE não é a recorrência dentro
das classes do sistema, mas sim o fato de que são aplicáveis a apenas uma parte do
conjunto total de contextos onde a classe possa vir a ser inserida. Este fato as torna
obsoletas em outros contextos.
As RCE justificam-se a partir de uma característica intrínseca do modelo
OO: o mecanismo de herança. Este mecanismo é efetivo, ou seja, é aplicado a todos os
43
This watermark does not appear in the registered version - http://www.clicktoconvert.com
42
Este tratará da sincronização e então invocará o método original m1 na
classe C. Caso esta mensagem não venha a requerer sincronismo mecanismo de lookup
fará diretamente a invocação do método original m1 em C. O diagrama de estados para
o exemplo acima é dado por (BOOLERT, 2000) e está representado na figura 3.17.
Figura 3.17 – Diagrama de Estados da Classe Tecida C’ - Fonte (BOOLERT, 2000)
Este capítulo finaliza a apresentação da implementação AspectJ para o
modelo de aspectos. A próxima seção apresentará a implementação do aplicativo
Figuras Flutuantes, desenvolvido em duas versões. Uma primeira numa abordagem
totalmente OO e uma segunda versão agora com a migração para o modelo de aspectos
com a modularização das RCE.
42
This watermark does not appear in the registered version - http://www.clicktoconvert.com
41
domínio. Na terminologia POA as classes sob o domínio do aspecto é o conjunto de
classes que o aspecto afeta. Uma diferença marcante entre as abordagens estática e
dinâmica é que enquanto a primeira afeta a classe, a segunda afeta somente
determinadas instâncias da classe (HIGHLEY et al, 2000).
Conforme mencionado anteriormente na abordagem dinâmica o aspecto é
tratado de forma equivalente à classe, visto que é instanciado sob a forma de aspin. A
cada aspin é adicionado um novo e importante membro: um vetor onde constam todos
os objetos sob seu domínio. A estes objetos do mesmo modo é adicionado um vetor
onde constam todos os aspins que têm o objeto sob seu domínio.
A fig. 3.16 é fornecida por (BOOLERT, 2000) demonstra de forma sintética
o trabalho do tecedor de aspectos. Ela apresenta o surgimento da classe tecida,
identificada como C’. O método identificado como m1 é o método tecido gerado a partir
da costura do aspecto a .
Figura 3.16 – Classe e Método Tecidos – Fonte (BOOLERT, 2000)
A fig. 3.16 exemplifica a abordagem de classes tecidas supondo um aspecto
de sincronismo envolvendo as classes C e C’ e seus métodos. Quando a classe tecida
C’ receber uma mensagem destinada ao método costurado m1’ e esta mensagem
requerer sincronismo o mecanismo de lookup invocará o método tecido.
41
This watermark does not appear in the registered version - http://www.clicktoconvert.com
40
Uma Segunda forma de tecimento estático pode ser visto na fig. 3.15 e é
chamado de Composição Explícita. Neste método o processo de inline não é adotado.
Ao invés disto a classe afetada pelo aspecto recebe um atributo que o referencia. Esta é
uma forma estática de se trabalhar com os aspins, pois o novo membro da classe é
introduzido em tempo de compilação e referencia o aspin, que é uma instância de
aspecto (HIGHLEY et al, 2000).
APONTADOR PARA O
ASPIN
ASPIN
CLASSE
ORIGINAL
Figura 3.15 – Tecimento Estático por Composição Explícita
A abordagem dinâmica por sua vez não altera o código original das classes
do sistema. Ao contrário, utiliza o mecanismo de herança para especializar as classes
existentes com as estruturas especializadas dos aspectos (BOOLERT, 1999, HIGHLEY
et al, 2000). De forma resumida o procedimento é o seguinte: suponhamos que um
aspecto Asp afeta métodos de uma classe Ca. O tecedor declara uma nova classe como
subclasse desta designada classe tecida (Cavw). Na subclasse Cavw são sobrescritos os
métodos afetados pelo aspecto Asp, substituindo-os pelos chamados métodos tecidos.
No momento da execução quando uma mensagem é enviada à classe Ca,
esta classe é normalmente localizada e o método envolvido na mensagem é executado.
O tecedor então procura pela classe tecida Cavw e executa o método tecido
correspondente. Desta forma a classe Ca apresentará, além de seu comportamento
original, o comportamento adicionado pelo aspecto Asp.
No mecanismo de tecimento dinâmico a ligação do aspin com a classe é
feita em tempo de compilação. O aspecto, por meio dos métodos específicos
addObject() e removeObject() adiciona ou remove um determinado objeto de seu
40
This watermark does not appear in the registered version - http://www.clicktoconvert.com
39
Em um programa desenvolvido sob a abordagem POA, as classes
representam apenas a estrutura primária do sistema. Os aspectos por sua vez assumem o
papel de estruturas funcionais especializadas que determinam as responsabilidades
comuns do sistema. Um aspecto geralmente refere-se a pontos específicos do fluxo de
execução. Estes pontos são os chamados pontos de junção e podem referir-se a um
método, um construtor, atribuição de valores a variáveis e outros.
Na abordagem estática o tecedor costura novos atributos e métodos às
classes do sistema. O aspecto pode ser meramente compilado com a classe, introduzindo
nesta novos atributos, métodos e também advices. Este processo se dá em tempo de
compilação e o resultado é que todo objeto desta classe assumirá as alterações
provocadas pelo aspecto. O aspecto sofre um processo de inline dentro da classe. O
resultado gerado à partir da tecimento da classe ao aspecto é definido na literatura como
aspin ou classe costurada (BOOLERT, 1999, HIGHLEY et al, 2000).
A abordagem estática pode ser vista na fig. 3.14 e impede que o nível
adicional de abstração introduzido no sistema pelos aspectos tenha impacto negativo no
que diz respeito ao quesito performance. Entretanto como ponto negativo a este
processo de inline torna-se difícil distinguir os aspectos da estrutura original do
programa. Nada muito significativo até o momento em que se tenta manipular o ‘código
de aspectos’ dinamicamente. Sob a abordagem estática esta tarefa pode tornar-se muito
difícil ou mesmo impossível (BOOLERT, 2000).
CLASSE
ORIGINAL
+
ASPECTO
=
CLASSE
CLASSE
‘COSTURADA’
Figura 3.14 – Tecimento Estático Aplicando inline
39
This watermark does not appear in the registered version - http://www.clicktoconvert.com
38
[<private> <public> <abstract>] aspect nomeAspecto
{
[<declaração de atributos Java ordinários>]
[<declaração de atributos introduzidos>]
[<especifcação dos pontos de corte nomeados>]
[<especificação dos advices >]
[<implementação de métodos Java ordinários>]
[<implementação de métodos introduzidos>]
}
Figura 3.13 – Anatomia do Aspecto
Um aspecto é uma unidade similar a uma classe pois é declarado de forma
semelhante a ela. Declara atributos, implementa métodos e possui instâncias. O aspecto,
entretanto, apresenta um recurso a mais que é o advice (HIGHLEY et al, 2000).
E o que seria uma instância de aspecto. Elas são denominadas sob o termo
aspin e estão presentes na abordagem de tecimento dinâmico a ser vista com maiores
detalhes na próxima seção.
O AspectJ trata objetos e aspins como entidades equivalentes considerando
que o aspin tem uma característica adicional: ele pode eventualmente encapsular
advices. Logo, um aspin sem advices é simplesmente uma classe. De forma similar a
um objeto, cada aspin tem o conjunto de atributos e métodos declarados em seu aspecto
correspondente mas cada aspin possui seu próprio conjunto de valores para estes
atributos.
3.6. Tecedor de Aspectos e Classes – Aspect Weaver
Vários trabalhos definem como centro das discussões o mecanismo de
tecimento de aspectos e classes. São comentadas as formas estática e dinâmica de
trabalho do tecedor e são relatadas vantagens e desvantagens nas duas abordagens
(BOOLERT, 1999, HIGHLEY et al, 2000, SUZUKI & YAMAMOTO, 1999).
38
This watermark does not appear in the registered version - http://www.clicktoconvert.com
37
Este valor fica armazenado na variável num declarada na linha linha 3. Este
valor é então analisado e sendo maior que zero o fluxo de execução segue normalmente
caso contrário uma mensagem de aviso é emitida (linhas 4 a 7). No cap. 5 pode ser
observada a implementação do aspecto reduzTempoDeVida. Este aspecto implementa
um advice do tipo around() que altera o contexto de execução do objeto afetado.
3.4.1. A Ordem de Precedência dos Advices
Não é atípica a situação em que, dada uma aplicação, diversos advices
façam referência ao mesmo conjunto de pontos de junção. Para estes casos o AspectJ
estabelece algumas regras que definem a ordem de precedência deste conjunto de
advices.
Dados dois aspectos concretos A e B que declaram respectivamente os
advices a1 a2 referentes a um mesmo ponto de junção pj as regras são descritas a
seguir:
1) se o aspecto A tem a precedência explícita sobre o aspecto B feita com o uso da
declaração precedence, então o advice a1 será executado antes do advice a2;
2) se o aspecto B é um subaspecto de A, então o advice a1 tem precedência sobre o
aspecto a2;
3) se B não for subaspecto de A e a declaração precedence não for aplicada a ordem de
precedência é então desconhecida.
3.5. Aspectos
Conhecendo os modelos de ponto de junção, ponto de corte, advices e
introduções oferecidos pelo AspectJ é possível então tratar especificamente da
implementação dos aspectos. Um aspecto em AspectJ é, conforme especifica o conceito,
uma unidade funcional que modulariza as responsabilidades comuns da aplicação.
Um aspecto em AspectJ pode conter apenas advices, apenas introduções,
ambos ou mesmo nenhum destes elementos, podendo conter apenas declarações
ordinárias da linguagem Java. A declaração geral pode ser vista na fig 3.13.
37
This watermark does not appear in the registered version - http://www.clicktoconvert.com
36
3.4. Os Advices
O AspectJ permite a implementação das responsabilidades comuns sob duas
formas distintas (KICKZALES et al, 2001). A primeira delas é descrita como aditiva
pois permite que algum código adicional seja executado a partir do momento em que
um ponto de corte é encontrado.
Esta abordagem determina a natureza dinâmica do AspectJ, visto que
acontece em tempo de execução. A segunda forma é pela inclusão de novos membros às
classes do sistema e caracteriza a natureza estática do AspectJ, visto que acontece em
tempo de compilação através do mecanismo de introduções.
A diferença reside no fato de que enquanto os advices before() ou after()
podem apenas receber valores de retorno do contexto de execução do ponto de junção, o
advice around() pode introduzir novos valores neste contexto de execução ou mesmo
alterar o fluxo de execução deste contexto (KICKZALES et al, 2001). A fig 3.12
apresenta uma situação onde a execução dos advices é condicionada ao valor de retorno
produzido pela chamada do ponto de junção.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void around(Ponto pt) : target(pt) && call(void setX(int))
{
int num = pt.getX();
if num = 0 then
System.out.println(“Valor inválido”)
else
proceed;
}
void around(Linha ln) : target(ln) && call(void setP1(Ponto))
{
ponto pt = ln.getP2();
if pt = null then
System.out.println(“Valor inválido”)
else
proceed;
}
Figura 3.12 – Advice around()
No primeiro advice, implementado entre as linhas 1 e 8, a primitiva target
garante uma referência ao objeto que recebeu a chamada do método especificado como
ponto de junção pela primitiva call (linha 1). Esta referência fica armazenada na
variável pt e é utilizada para ler um valor do contexto de execução do objeto.
36
This watermark does not appear in the registered version - http://www.clicktoconvert.com
35
·
private boolean Ponto.cor = clred – esta declaração introduz na classe
Ponto um campo privado chamado cor e o inicializa com o valor clred. Pelo fato
deste campo ter sido declarado como private apenas o código definido no aspecto
pode ter acesso a ele;
·
public int Ponto.getX() { return x; } – esta declaração introduz um
método chamado getX() na classe Ponto. Este método retorna um inteiro e não
recebe qualquer argumento. Pelo fato de ter sido declarado como public qualquer
código pode acessá-lo;
·
public Ponto.new(int x, int y) {this.x = x; this.y = y;} –
esta declaração introduz um construtor na classe Ponto. Este construtor possui como
pode ser observado dois argumentos do tipo inteiro e seu corpo é this.x = x; this.y =
y. Um exemplo completo pode ser observado na fig. 3.11. Ele apresenta a
especificação do aspecto monitoraY. Estes aspecto introduz na classe Ponto os
seguintes membros:
·
Linha 3 : um atributo inteiro privado yAntigo;
·
Linhas 9 a 11 : um método cuja assinatura é somaNovoY(inty);
·
Linhas 12 a 14 : um método cuja assinatura é guardaYAntigo(inty).
1
2
3
Aspect monitoraY
{
private int Ponto.yAntigo;
4
after(Ponto p) returning(int y): target(p) && (call(int
getY(int)))
{
p.guardaYAntigo(y);
p.somaNovoY(y)
}
5
6
7
8
9
10
11
12
13
14
15 }
public void Ponto.somaNovoY(int y) {
y ++;
}
public void Ponto.guardaYAntigo(int y) {
yAntigo = y;
}
Figura 3.11 – Introduzindo Novos Membros na Classe Ponto
35
This watermark does not appear in the registered version - http://www.clicktoconvert.com
34
Neste caso um objeto do tipo Ponto e um valor inteiro estarão disponíveis
quando os pontos de junção forem encontrados. Se forem observados os eventos
definidos como pontos de junção é constatado que o objeto Ponto retornado é o objeto
que recebe a invocação do método e que o valor inteiro é o argumento que consta na
assinatura do método invocado.
Entretanto, há uma regra geral a ser seguida que é a seguinte: quando os
eventos definidos como pontos de junção acontecem, todos os parâmetros do ponto de
corte devem ser vinculados a algum valor. Deste modo, a definição mostrada na fig 3.10
resultará em erro de compilação.
Pointcut capturaPontos(Ponto p1, Ponto p2):
(target(p1) && call(void setX(int)))
||
(target(p2) && call(void setY(int)));
Figura 3.10 – Regra Geral de Parametrização
Aqui o ponto de corte define como pontos de junção os seguintes eventos:
um método setX(int) invocado em um objeto Ponto qualquer ou um método setY(int)
invocado de um outro objeto Ponto qualquer. O que ocorre aqui é o seguinte: na
definição de parâmetros do ponto de corte há a tentativa de obter o retorno de dois
objetos Ponto diferentes (p1 e p2) ao mesmo tempo.
Supondo que o ponto de junção setX(int) seja encontrado em um objeto
Ponto qualquer, haverá então disponível na variável p1 uma referência ao objeto
origem do evento. Não haverá outro objeto Ponto para vincular ao parâmetro p2 do
ponto de corte. Neste caso o parâmetro p2 é dito não vinculado gerando assim um erro
de compilação.
3.3. Introduções
As introduções (anexo 3) permitem introduzir novos membros nas classes
do sistema, bem como alterar a hierarquia das classes por meio de declarações especiais.
As classes Ponto e Linha apresentadas anteriormente na fig. 2.1 podem ser utilizadas
para descrever algumas construções do tipo introdução :
34
This watermark does not appear in the registered version - http://www.clicktoconvert.com
33
Vejamos outro exemplo que nos permite avaliar a flexibilidade do modelo de
parametrização de pontos de corte oferecido pelo AspectJ. Considere-se o ponto de
corte nomeado que pode ser visto na fig. 3.7.
pointcut testaIgualdade(Ponto p): target(Ponto) &&
args(p) &&
call(boolean equals(Object));
Figura 3.7 – Ponto de Corte com Retorno do Objeto Passado como Parâmetro
Similarmente ao anterior, este ponto de corte captura também um parâmetro
do tipo Ponto quando os eventos relacionados aos pontos de junção ocorrerem. Mas
neste caso, se for observado o lado direito da declaração, constatamos que o objeto
nomeado no parâmetro da chamada da função equals() não é o objeto Ponto que recebe
a chamada. Ele é um outro objeto passado como parâmetro à função. Eventualmente
pode-se querer ter acesso a ambos os objetos. O ponto de corte deverá ser declarado da
forma mostrada na fig. 3.8.
Pointcut testaIgualdade(Ponto p1, Ponto p2):
target(p1) &&
args(p2) &&
call(boolean
equals(Object));
Figura 3.8 – Ponto de Corte com Retorno de Dois Objetos
Levando em conta a flexibilidade do modelo, pode-se voltar ao ponto de
corte chamado atribuidor definido inicialmente e considerar uma variação na sua
construção de modo a obter como retorno, além do objeto onde o ponto de junção foi
encontrado, um valor inteiro referente ao parâmetro recebido por este ponto de junção.
Vejamos então a fig. 3.9.
Pointcut atribuidor(Point p, int newval): target(p) &&
args(newval) &&
(call(void setX(int))
||
call(void setY(int)));
Figura 3.9 – Ponto de Corte com Retorno de Um Objeto e Um Valor Inteiro
33
This watermark does not appear in the registered version - http://www.clicktoconvert.com
32
sofrer o processo de overloading. Logo, declarar dois pontos de corte com o mesmo
nome na mesma classe ou aspecto acarreta um erro.
3.2.2. Parametrização dos Pontos de Corte
Os aspectos podem ter acesso a partes privadas das classes. Este acesso,
contudo, não compromete o encapsulamento esperado entre as diferentes classes do
sistema (VOELTER, 2000). Os pontos de corte podem de alguma forma expor partes
do contexto de execução dos pontos de junção. Esta exposição se dá através de seu
modelo de parametrização. Este modelo permite que algum valor seja retornado ao
advice quando o ponto de junção é encontrado e o ponto de corte é executado.
Considere-se o seguinte ponto de corte que será nomeado como atribuidor e pode ser
visto na fig. 3.5.
pointcut atribuidor(): target(Ponto) &&
(call(void setX(int)) ||
call(void setY(int)));
Figura 3.5 – Ponto de Corte sem Retorno de Valor
O lado direito da declaração determina como pontos de junção as chamadas
aos métodos setX(int) ou setY(int). A primitiva target garante que sejam executadas em
alguma instância da classe Ponto. O lado esquerdo da declaração define um ponto de
corte de nome atribuidor e nenhum retorno é esperado. Considere-se agora a seguinte
declaração para o mesmo ponto de corte a ser dada na fig 3.6.
pointcut atribuidor(Ponto p): target(p) &&
(call(void setX(int)) ||
call(void setY(int)));
Figura 3.6 – Ponto de Corte com Retorno do Objeto Chamado
Esta versão define exatamente os mesmos pontos de junção mas o ponto de
corte captura um parâmetro do tipo Ponto. Como efeito prático, esta declaração permite
que quando os eventos relativos aos pontos de junção ocorrerem, uma referência ao
objeto Ponto que originou o evento estará disponível na variável p. A primitiva target
garante que o objeto que originou o evento seja realmente um objeto da classe Ponto.
32
This watermark does not appear in the registered version - http://www.clicktoconvert.com
31
membro comum da classe. Desta forma, pode também assumir os modificadores public
ou private.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
abstract aspect operacoesEmX
{
abstract pointcut escreveuX();
abstract pointcut leuX();
}
aspect lerX extends operacoesEmX
{
pointcut leuX(): call(public Ponto.getX());
after(): leuX()
{
System.out.println(“R”);
}
}
aspect escreverX extends operacoesEmX
{
pointcut escreveuX(): call(public Ponto.setX(int));
after(): escreveuX()
{
System.out.println(“W”);
}
}
Figura 3.4 – Pontos de Corte Abstratos
Seguindo este raciocínio os pontos de corte, da mesma forma que os
métodos, podem ser do tipo final ou abstract. Para eles vale a mesma regra aplicada aos
métodos ou seja, pontos de corte abstratos só podem ser declarados em aspectos
abstratos.
Quando necessário eles podem ser estendidos e implementados do mesmo
modo que um método de uma classe abstrata. A fig. 3.4 mostra o aspecto abstrato
operacoesEmX implementado entre as linhas 1 e 5. Ele declara dois pontos de corte
abstratos nomeados como escreveuX() e leuX() implementados nas linhas 3 e 4.
O aspectos concretos declarados nas linhas 7 e 16 estendem o aspecto
abstrato operacoesEmX e sobrescrevem os pontos de corte abstratos especificando
agora o conjunto de pontos de junção desejado (linhas 9 e 18).
Para complementar podem também ser definidos como final. Entretanto há
um ponto importante a ser considerado. Apesar dos pontos de corte poderem ser
declarados e estendidos em sub-aspectos como se fossem métodos eles não podem
31
This watermark does not appear in the registered version - http://www.clicktoconvert.com
30
Eles podem ser separados em grupos que de certa forma determinam o
gênero destes pontos de junção. Estes descritores são aplicados para selecionar pontos
de junção de um determinado tipo – chamada de método, chamada de construtor,
execução de método, etc (LOPES, 2002). O modelo de pontos de corte do AspectJ pode
ser visto no anexo 2 onde são apresentados os descritores primitivos seguidos de
explicações e exemplos.
3.2.1. A Nomeação dos Pontos de Corte
Existem outras questões a serem consideradas no que diz respeito ao modelo
de pontos de corte. O AspectJ define no seu modelo de pontos de corte que estes
possam ser declarados de forma anônima ou nomeada.
Um ponto de corte anônimo é a simples composição dos pontos de junção
diretamente associados ao advice sem qualquer identificador que possa lhe atribuir um
nome único. Quando ao ponto de corte é submetido um identificador, diz-se que este
ponto de corte é do tipo nomeado.
O primeiro efeito prático em se nomear um ponto de corte é relativo à sua
reusabilidade, conforme pode ser visto na fig. 3.3.
1
2
3
4
5
Class Ponto
{
//**Outras declarações Java
public pointcut escreveuX(): call(public setX(int);
}
6
7
8
9
10
11
12
aspect exemplo
{
after(): escreveuX()
{
System.out.println(“W”);
}
}
ponto de corte nomeado
Figura 3.3 – Ponto de Corte Nomeado Declarado como Membro de Classe
O AspectJ permite que um ponto de corte seja declarado tanto em um
aspecto como em uma classe ordinária. Neste último caso ele é tratado como um
30
This watermark does not appear in the registered version - http://www.clicktoconvert.com
29
nível de projeto, ou seja, o código entrelaçado (BLAIR & BLAIR, 1998). O weaving
será apresentado com maiores detalhes ao longo deste trabalho.
3.1. O Modelo de Pontos de Junção
Conforme já mencionado o conceito de ponto de junção diz respeito a
pontos dentro da aplicação onde uma determinada ação é realizada. Eles dizem respeito
então a algum tipo de evento que pode ocorrer em algum ponto da aplicação em algum
momento.
O AspectJ implementa o seu modelo de pontos de junção com base num
conjunto de onze eventos distintos. Um dos eventos mais comuns do conjunto de pontos
de junção do AspectJ é a chamada de método. A lista completa dos eventos passíveis de
constituírem pontos de junção são mostrados neste trabalho (anexo 1).
3.2. O Modelo de Pontos de Corte
Conforme já citado um ponto de corte é uma estrutura capaz de agrupar um
ou mais pontos de junção, determinando os termos da execução do advice. No AspectJ
a estrutura de um ponto de corte é definida por duas declarações separadas pelo
caractere ‘:’. A parte à esquerda de ‘:’ determina a nomeação do ponto de corte e a parte
à direita especifica os eventos que relacionam os pontos de junção, como pode ser
observado no segmento de código da fig. 3.2.
1-<pointcut Exemplo> : 2-<Ponto.setX(int)> ||
3<Linha.setP1(Ponto)>
{
4-<System.out.println(“W”);>
}
1) nome
4)corpo
2,3)
pontos
de
junção
Figura 3.2 – Ponto de Corte AspectJ
O modelo de pontos de corte do AspectJ fornece um conjunto de 26
descritores de tipo primitivos, os chamados pointcut descriptors. Estes descritores de
tipo têm como objetivo determinar o critério de seleção para os pontos de junção
definidos no ponto de corte.
29
This watermark does not appear in the registered version - http://www.clicktoconvert.com
28
Orientado a aplicação
AML
Orientado a Domínio
RG
Orientado a responsabilidade
Propósito geral
RIDL
COOL
talk
AspectJ
Figura 3.1 – AspectJ como Solução de Propósito Geral
O AspectJ é uma extensão da linguagem de programação Java e tal
característica foi planejada com o intuito de atingir a comunidade de programadores
visto que o Java é largamente utilizado (KICKZALES et al, 2001). Esta decisão levou
ao desenvolvimento de quatro diretrizes que caracterizam a ferramenta da seguinte
forma:
·
Compatibilidade de código executável – um programa Java é um programa
AspectJ compatível;
·
Compatibilidade de plataforma - todo programa AspectJ pode ser executado em
uma JVM;
·
Compatibilidade de ferramentas – uma IDE que suporta a programação Java
suporta também a programação orientada a aspectos;
·
Compatibilidade de declarações – a programação com AspectJ deve ser
compatível com a forma de construir programas em Java.
O compilador do AspectJ apresenta uma fase preliminar de tecimento ou
weaving. Em uma primeira fase da compilação ele resolve de forma não ambígua as
capacidades comuns entre classes e aspectos. Em uma segunda fase o compilador
tradicional Java é invocado para resolver as declarações Java ordinárias. O resultado do
processo de tecimento no nível do código compilado é aquilo que se tenta evitar no
28
This watermark does not appear in the registered version - http://www.clicktoconvert.com
27
·
Nível de implementação – deve oferecer uma organização adequada de modo que
as responsabilidades possam ser isoladas umas das outras (LOPES, 2002).
O AspectJ possui um conjunto de diferenças significantes diante das suas
predecessoras que são as seguintes:
·
O conceito da coordenação como elemento de primeira ordem na linguagem foi
deixado de lado. AspectJ declara aspectos e estes podem contemplar questões
relativas à coordenação;
·
Diferentemente de DJ, uma de suas predecessoras, o AspectJ oferece manipuladores
para instâncias de aspectos através da operação AspectOf().
Entretanto existe também a preservação de características significantes
diante das suas predecessoras que são as seguintes:
·
Conceito de ponto de corte - já havia sido identificado nas linguagens DJ e RG,
mas estas apresentavam apenas pontos de corte para envio e recepção de mensagens
pelos objetos do sistema. O AspectJ teve seu conjunto de pontos de corte largamente
expandido;
·
Referências temporais - as declarações before/after oferecidas pela linguagem DJ
foram mantidas;
·
Introduções – o recurso introdução foi apresentado inicialmente pelas linguagens
COOL e CLOS e foram mantidas pelo AspectJ.
A fig. 3.1 posiciona o AspectJ dentre algumas soluções desenvolvidas sob o
enfoque da modularização das responsabilidades comuns. O AspectJ pode ser
considerado como uma solução de propósito geral enquanto suas predecessoras são
posicionadas como soluções orientadas a domínio. Dentre elas pode-se mencionar
linguagens como RIDL para transmissão de dados, COOL para sincronização, RG para
processamento de imagem e AML para processamento de matrizes) (LOPES &
KICKZALES, 1998).
27
This watermark does not appear in the registered version - http://www.clicktoconvert.com
26
Capítulo III
Projeto Orientado a Aspectos com Aspectj
A abordagem POA é um conceito e não está restrito a uma linguagem ou
paradigma de programação. Pode ser aplicado em auxílio às deficiências de qualquer
linguagem(procedural, OO ou funcional) que use decomposição hierárquica. Neste
capítulo será visto especificamente o AspectJ.
O AspectJ é uma ferramenta desenvolvida pela Xerox PARC aplicada
especificamente sobre Java. Os elementos de linguagem do AspectJ são descritos aqui
com base nas definições de Gregor Kickzales (KICKZALES, 2001), pesquisador da
Xerox PARC e um dos idealizadores da POA. São abordados aqui de forma sucinta o
modelo AspectJ para pontos de junção, pontos de corte, advices e aspectos bem como
seu funcionamento e pequenos exemplos explicativos.
O AspectJ é uma linguagem de propósito geral onde podem ser
especificados aspectos relativos a aplicações distribuídas e não distribuídas, controle de
concorrência, protocolos inter-classe e otimizações. Permite que os aspectos sejam
facilmente ligados e desligados da aplicação, bastando para isso invocar o weaver
(LOPES & KICKZALES, 1998).
Se fosse necessário tecer o aspecto afetaPontoELinha visto na fig. 2.6 à
classe Ponto a sintaxe a ser aplicada seria: %
ajweaver
Ponto.ajava
Linha.ajava afetaPontoELinha.ajava.
O AspectJ atinge as duas premissas básicas que permitem a modularização
das responsabilidades comuns. Estas duas premissas atingem os níveis conceitual e de
programação onde:
·
Nível conceitual – deve oferecer um nível de abstração suficiente de modo que
cada responsabilidade comum seja definida como um conceito individual;
26
This watermark does not appear in the registered version - http://www.clicktoconvert.com
25
·
a primitiva target determina que os pontos de junção quando encontrados
sejam provenientes de um objeto da classe Linha;
·
chamadas de métodos com a mesma assinatura dos pontos de junção mas
provenientes especificamente de outra classe que não a classe Linha são
desconsiderados.
O operador OU, representado pela palavra reservada || faz a junção dos dois
segmentos acima determinando que o advice será executado seja encontrando pontos de
junção do primeiro ou do segundo segmento. O advice do aspecto afetaLinha faz uso
das mesmas primitivas e pode ser analisado da mesma forma.
Os elementos apresentados neste capítulo determinam a base do modelo
orientado a aspectos. Será visto na próxima seção o implementação AspectJ para
programação orientada a aspectos e a forma pela qual os aspectos, advices, pontos de
junção e pontos de corte são tratados.
25
This watermark does not appear in the registered version - http://www.clicktoconvert.com
24
Figura 2.10 - Relação Aspecto-Classe
O advice implementado no aspecto afetaPontoELinha combina as
primitivas target e call resultando em um advice que pode ser analisado mais facilmente
se dividido em dois segmentos :
1) (target(Ponto) && call(setX(int) || setY(int)) )
·
a primitiva call determina como pontos de junção chamadas aos métodos
setX() ou setY();
·
a primitiva target determina que os pontos de junção quando encontrados
sejam provenientes especificamente de um objeto da classe Ponto;
·
chamadas de métodos com a mesma assinatura dos pontos de junção mas
provenientes de outra classe que não a classe Ponto são desconsiderados.
2) (target(Linha) && call(setP1(Ponto) || setP2(Ponto)) )
·
a primitiva call determina como pontos de junção chamadas aos métodos
setP1() ou setP2() ;
24
This watermark does not appear in the registered version - http://www.clicktoconvert.com
23
execução. O aspecto, por sua vez, apresenta um relacionamento dinâmico com as
classes do sistema.
Conforme já mencionado um aspecto é um segmento de código que
representa uma unidade funcional recorrente dentro do sistema. Ele modulariza as
responsabilidades comuns e pode referenciar diversas classes ao mesmo tempo.
Ambos os advices implementados na fig. 2.9 referenciam apenas pontos de
junção da classe Ponto (linhas 3 e 8). Já os advices implementados no aspecto
afetaPontoELinha (linhas 15 e 20) declaram como pontos de junção os métodos setX() e
setY() da classe Ponto mas também os métodos setP1() e setP2() da classe Linha.
1
2
3
4
5
6
7
8
9
10
11
12
aspect afetaPonto
{
before() : Ponto.setX(int) || Ponto.setY(int)
{
System.out.println(“W”);
}
after() : Ponto.getX() || Ponto.getY()
{
System.out.println(“R”);
}
}
13 aspect afetaPontoELinha
14 {
15
before() : Ponto.setX(int) || Ponto.setY(int) ||
16
Linha.setP1(Ponto) || Linha.setP2(Ponto)
17
{
18
System.out.println(“W”);
19
}
20
before() : Ponto.getX() || Ponto.getY() ||
21
Linha.getP1() || Linha.getP2()
22
{
23
System.out.println(“R”);
24
}
25 }
Figura 2.9 –Aspecto Referenciando Duas Classes
O relacionamento aspecto-classe pode ser definido em acordo com a fig.
2.10. Ela apresenta uma visão conceitual deste relacionamento com base no aspecto
implementado na fig. 2.9. O campo de influência do aspecto sobre a classe se mostra à
medida que os advices referenciam pontos de junção contidos nestas classes.
23
This watermark does not appear in the registered version - http://www.clicktoconvert.com
22
primeiro momento. Para compreender melhor esta noção é interessante primeiro falar a
respeito da programação como é conhecida atualmente. Para se construir um aplicativo
é possível utilizar a programação estruturada, onde são especificados alguns blocos de
código que são conectados para construir sistemas mais complexos. É notório que, em
algum momento, haverá um correspondente em código objeto para cada um dos blocos
de código fonte implementados. Este é um tipo de mapeamento onde um segmento de
código fonte corresponde diretamente a um segmento de código objeto.
É possível também utilizar a programação OO para desenvolver este mesmo
aplicativo imaginário. Neste tipo de abordagem é especificado um conjunto de classes
que, encapsulando algum comportamento, colaborarão entre si de modo a atingir um
objetivo comum. Estas classes serão instanciadas em algum momento em vários ou
talvez em dezenas de objetos. A classe, em sua forma estática, terá correlação direta
com suas instancias, os objetos. A representação conceitual do relacionamento classeobjeto é mostrada na fig. 2.8 logo abaixo.
AMBIENTE DE EXECUÇÃO
CLASSES
Ponto
Linha
P1
P4
L1
P2
L2
L3
L4
P3
INSTÂNCIAS DE CLASSE
Figura 2.8 – Relacionamento Classe-Objeto
É possível afirmar que o tipo de correlação entre código fonte e código
objeto nas abordagens procedural e OO é clara e é estática ao longo do tempo de
22
This watermark does not appear in the registered version - http://www.clicktoconvert.com
21
Um aspecto pode afetar diversos componentes do sistema e o conjunto de
componentes afetados é determinado nos termos dos pontos de junção declarados nos
advices. Compreender a forma pela qual o aspecto se relaciona com a classe é relevante
diante dos conceitos apresentados. Na próxima seção será apresentado o relacionamento
entre o aspecto e o conjunto de classes por ele afetadas.
2.5. O Relacionamento Aspecto – Classe
Para que se possa contextualizar é necessário falar algo a respeito de classe
e objeto apresentando idéias largamente aceitas atualmente. Uma classe é um modelo
abstrato, possui atributos e métodos e implementa algum comportamento. Uma classe
possui mecanismos que escondem/protegem sua estrutura interna. Ela
pode ser
especializada através do mecanismo de herança e sua subclasse apresentará, além do
comportamento de sua superclasse, algum comportamento adicional (novos atributos e
métodos).
Uma classe pode ser instanciada na forma de objetos e estes objetos serão
instâncias de uma mesma classe. Mas como ter certeza a respeito de quais objetos
pertencem a uma mesma classe sendo que cada objeto é uma entidade que possui um
estado próprio? Cada objeto possui um conjunto de valores próprios para seus atributos
sim, e isto determina o estado do objeto em um determinado momento. Mas cada
instância de classe possui também o conjunto de métodos declarados na sua classe
correspondente. Esta característica define o conjunto de mensagens as quais um objeto
tem condições de responder.
Logo, todos os objetos capazes de enviar e responder ao mesmo conjunto
de mensagens são considerados como pertencentes a uma mesma classe.
O
relacionamento classe-objeto é claro e apoiado pela vasta literatura disponível nos dias
de hoje. Mas o relacionamento aspecto-classe difere deste.
Neste tipo de relacionamento um segmento de código fonte não mapeia
diretamente um segmento de código compilado. Em contrário, mapeia todas as
instâncias de classe onde um determinado aspecto é aplicado. Mudar apenas uma linha
de código poderá refletir as mudanças para toda a aplicação (ASPECT-ORIENTED
PROGRAMMING (AOP), 2000). Esta afirmativa pode não parecer muito clara em um
21
This watermark does not appear in the registered version - http://www.clicktoconvert.com
20
Os advices são os componentes do modelo orientado a aspectos que são
encapsulados pelos aspectos. Pode ser afirmado que o advice define sob quais critérios
um aspecto afetará as classes do sistema. Os aspectos serão discutidos em maiores
detalhes a seguir.
2.4.4. O Aspecto
Conforme mencionado anteriormente o aspecto é uma unidade funcional
que modulariza as responsabilidades comuns dos componentes do sistema. Os aspectos
encapsulam advices. Os advices determinam sob quais critérios o aspecto afetará um
determinado conjunto de componentes. Estes critérios são definidos pelos pontos de
corte e pelos pontos de junção.
A fig. 2.7 mostra que os métodos set() e get() das classes Ponto e Linha
foram determinados como pontos de junção
dos advices declarados no aspecto
afetaPontoeLinha.Logo a execução destes métodos é o critério que determina quando e
se o aspecto virá a afetar estas classes. Se estes métodos não forem invocados diz-se que
os pontos de junção que eles representam não foram encontrados. Logo o advice que os
encapsula não será executado e por consequência o aspecto onde este advice está
contido também não será executado.
O modelo orientado a aspectos está para a modularização das
responsabilidades comuns assim como a OO está para o encapsulamento e a herança
porque oferece mecanismos que permitem capturar estas responsabilidades
(KICKZALES et al, 2001). Pode ser afirmado que o aspecto é uma unidade modular
diferenciada dos demais componentes do sistema. Um aspecto tem a capacidade de
encapsular advices, isto é uma verdade. Mas um aspecto pode simplesmente encapsular
declarações ordinárias do modelo orientado objetos e nada mais, não declarando advice
algum e possuindo o comportamento de uma classe ordinária.
Sob este enfoque, um aspecto pode declarar variáveis e métodos, mas
nenhum advice. Há de se considerar que talvez não faça sentido algum implementar
aspectos que não encapsulem advices, mas isto serve ao menos para reforçar o caráter
da POA em estender o modelo OO e não substituí-lo.
20
This watermark does not appear in the registered version - http://www.clicktoconvert.com
19
advice é
executado
Ponto de
corte é
executado
Ponto de
junção é
encontrado
ADVICE
PONTO DE CORTE
PONTO
DE
JUNÇÃO
Figura 2.6 – Visão Conceitual do Advice
Resta considerar um detalhe adicional. Uma noção temporal pode ser
agregada ao advice (LESIECKI, 2002). Esta noção temporal determina que o
comportamento adicional acrescentado pelo advice poderá ocorrer antes, depois ou
mesmo concorrentemente aos pontos de corte quando os pontos de junção são
encontrados. De forma objetiva, a característica temporal deve implicar que a execução
do corpo do advice poderá ocorrer ‘antes de’, ‘depois de’ou ‘paralelamente a’ em
relação ao corpo do ponto de junção. As noções ‘antes de’ e ‘depois de’ serão
apresentados agora. A terceira noção será vista mais adiante com a aplicação direta da
sintaxe AspectJ. Pode ser vista também no cap. 5. A fig. 2.7 apresenta esta noção
temporal com base na anatomia do advice vista anteriormente na fig. 2.5.
Aspecto afetaPontoeLinha;
{
Antes de : Ponto.setX(), Ponto.setY(), ...
{
O CORPO DO ADVICE É EXECUTADO ANTES DO CORPO DO PONTO DE
JUNÇÃO
}
Depois de : Linha.getP1(), Linha.getP2(), ....
{
O CORPO DO ADVICE É EXECUTADO DEPOIS DO CORPO DO PONTO DE
JUNÇÃO
}
}
Figura 2.7 – Noção Temporal do Advice
19
This watermark does not appear in the registered version - http://www.clicktoconvert.com
18
componentes afetados pelo aspecto. A próxima seção explora com maiores detalhes este
importante elemento da POA.
2.4.3. Advices
O advice é um elemento do modelo orientado a aspectos que pode agrupar
um ou mais pontos de corte. O conjunto de pontos de corte relacionados em um advice
é que define em quais termos este advice será executado e quais classes ele irá afetar
(KICKZALES et al, 2001). Ocorrendo a execução do advice algum comportamento
adicional pode ser inserido podendo afetar diversas classes da aplicação. O conjunto
exato destas classes é definido no advice nos termos dos pontos de corte nele contidos.
A anatomia do advice é dada na fig. 2.5.
1-<antes, depois> :
{
2-<pj1, pj2, .... pjn>
3-<Algum comportamento adicional aqui>
}
1) advice tipo
2) ponto de corte
3)corpo
Figura 2.5 – Anatomia do Advice
Em uma visão conceitual, o advice pode ser considerado como o elemento
mais externo aos pontos de corte e pontos de junção respectivamente. Sob este enfoque,
advices podem ser definidos como segmentos de código que encapsulam pontos de
corte que por sua vez encapsulam pontos de junção. A fig. 2.6 logo abaixo a
representação desta visão conceitual.
18
This watermark does not appear in the registered version - http://www.clicktoconvert.com
17
diz-se que o ponto de junção foi encontrado. Quando um ponto de junção é encontrado
o ponto de corte onde ele está contido é finalmente executado. Os pontos de junção
definem os termos dos pontos de corte.
2.4.2. Pontos de Corte
Os pontos de corte são mencionados na literatura sob o termo pointcut. Um
ponto de corte pode ser definido como uma construção que descreve o agrupamento,
sob um determinado critério, de um conjunto de pontos de junção. Os pontos de corte
são executados a partir do momento em que os pontos de junção que o compõem são
encontrados. Determinam desta forma os termos pelos quais o aspecto é inserido na
aplicação (KICKZALES et al, 2001).
Como forma de ilustrar tome-se como exemplo as classes Ponto e Linha já
vistas na fig. 2.1. O conjunto de métodos implementados nestas classes podem ser
considerados como sendo pontos de junção, pois determinam alguma ação sendo
executada em algum lugar da aplicação. Logo podem ser agrupados de modo a
especificar pontos de corte. A fig. 2.4 apresenta a caracterização de ponto de corte.
Pontos de junção
Ponto.setX(int)
Ponto.SetY(int)
ponto
de corte
Linha.setP1(Ponto)
Linha.getP2(Ponto)
Figura 2.4 – Pontos de Corte
O ponto de corte mostrado na figura acima será executado somente quando
algum dos eventos relacionados como pontos de junção forem encontrados. Por isso
diz-se que os pontos de junção definem os termos dos pontos de corte.
Havendo tomado consciência do termo ponto de corte estamos então
preparados para lançar olhares sobre outro elemento essencial na definição do modelo
orientado a aspectos : o advice. Este elemento é definido dos termos dos pontos de corte
e, de forma resumida, determina algum comportamento adicional a ser adicionado aos
17
This watermark does not appear in the registered version - http://www.clicktoconvert.com
16
Desta maneira, nada que impediria que um objeto passível de invocar uma mensagem
do tipo m1 invocasse um método que emitisse uma mensagem do tipo m2 e vice-versa.
Os aspectos podem então ser aplicados na modularização destas
responsabilidades comuns, evitando a replicação de código e a interdependência entre
módulos o que caracteriza o entrelaçamento de código. Podem ser aplicados como
forma de manter estas classes limpas, ou seja, portadoras apenas da estrutura primária
do sistema. Estariam então livres das responsabilidades secundárias e desta forma
concebidas sob um alto grau de modularização.
2.4. Os Elementos do Modelo Orientado a Aspectos
Esta seção trata o conjunto e elementos que define o modelo orientado a
aspectos. Serão vistos nesta ordem a definição de ponto de junção, ponto de corte,
advice, introdução e aspecto.
2.4.1. Pontos de Junção
Os pontos de junção são mencionados na literatura sob o termo join points.
Eles são um elemento essencial no modelo orientado a aspectos. Determinam pontos
definidos à partir dos quais uma operação qualquer é executada no sistema. De forma
objetiva, são caracterizados por eventos que ocorrem
em tempo de execução
(KICKZALES et al, 2001).
Podem ser considerados como exemplos típicos de pontos de junção os
seguintes eventos:
·
Chamada de um método ou construtor;
·
Execução do corpo de um método ou construtor;
·
Execução de blocos de controle de exceções;
·
Atribuição de valores a variáveis.
O conjunto exato de pontos de junção disponíveis é diretamente dependente
da linguagem utilizada. Quando um evento relativo a um ponto de junção é executado,
16
This watermark does not appear in the registered version - http://www.clicktoconvert.com
15
aplicativo e utilizar recursos gráficos mais aprimorados como uma janela sofisticada por
exemplo.
Figura 2.3 - Modularização do Código Entrelaçado
Como primeira opção bastaria alterar os métodos que implementam a
emissão da mensagem. Uma alternativa eficiente mas pouco desejável sob o aspecto da
manutenção à medida que o sistema cresce em complexidade. Em sistemas complexos
talvez seja necessário procurar e alterar dezenas de métodos em dezenas de classes.
Uma segunda opção seria declarar uma nova classe intermediária que
implementasse todos os tipos de mensagens e assim encapsulasse este novo look and
feel do aplicativo. Desta forma, com base no tipo de mensagem recebida dos objetos do
sistema, uma mensagem específica seria emitida. Esta abordagem seria mais razoável
sob o ponto de vista da manutenção, visto que haveria então uma classe responsável
pela emissão de mensagens. Em contrapartida surgem duas novas desvantagens que
podem não compensar o uso de tal estratégia.
A primeira desvantagem e talvez mais óbvia seria a queda de performance
visto que cada objeto afetado, sempre que necessitasse emitir uma mensagem,
provocaria uma chamada de método a outro objeto. A segunda desvantagem é que não
haveria forma de restringir o acesso dos objetos aos membros desta classe intermediária.
15
This watermark does not appear in the registered version - http://www.clicktoconvert.com
14
classes que faz acesso concorrente a dados. Aplicadas a um contexto onde o quesito
concorrência não exista estas operações podem gerar algum overhead.
Figura 2.2 – Entrelaçamento de Código
O termo tangled code, caracterizado logo acima na fig. 2.2, define o oposto
do que é considerado como clean code ou código limpo (LOPES & KICKZALES,
2000). O código limpo pode ser conseguido a partir do momento em que as
responsabilidades comuns são detectadas e agrupadas em algum tipo de módulo
reusável, e que possa ser posteriormente agregado pelas classes do sistema conforme,
fig. 2.3. Conforme argumentado os efeitos mais visíveis do entrelaçamento são
percebidos na forma de
dificuldades na manutenção e o comprometimento da
modularidade (KICKZALES et al, 1997, BÖLLERT, 2000).
A percepção do termo entrelaçamento pode ser apurada à medida que
analisamos situações recorrentes dentro da programação OO. Uma destas situações
pode ser observada pela análise da fig. 2.1 - Classes Ponto e Linha.
Cada método destas duas classes implementa seu próprio código de emissão
de mensagens. Considere-se a hipótese de que um programador desejasse alterar algo a
respeito destas mensagens. Quem sabe, ao invés de usar uma simples saída do tipo
texto (System.out.println()), este programador desejasse alterar o look and feel do
14
This watermark does not appear in the registered version - http://www.clicktoconvert.com
13
Um aspecto pode ser considerado como sendo um segmento de código que
representa uma propriedade recorrente dentro da aplicação. Ë uma abordagem que visa
a eliminação das desvantagens geradas a partir do entrelaçamento de código. Ela
apresenta as características vantajosas da OO mas apresenta também um diferencial que
supera uma grande desvantagem desta: as responsabilidades comuns podem ser escritas
apenas uma única vez e ser utilizadas em qualquer ponto da aplicação.
2.3. As Responsabilidades Comuns e o Entrelaçamento
A separação de responsabilidades é um instrumento importante na
engenharia de software pois é um recurso que permite lidar com a complexidade dos
sistemas (WALKER et al, 2000). Mas as responsabilidades comuns quando codificadas
a partir das abordagens tradicionais de programação(procedural e OO), geram o
entrelaçamento de código, referido da literatura como tangled code (LOPES &
KICKZALES, 2000).
Nas abordagens tradicionais um módulo é representado por um bloco de
código executável. Considere-se então uma aplicação com inúmeros módulos onde
estes compartilham inúmeras responsabilidades comuns. O resultado final será um
amontoado de código duplicado o que gera complexidade no entendimento e
manutenção.
O entrelaçamento está intimamente ligado à responsabilidade comum, visto
que é gerado por ela. O entrelaçamento é tipicamente caracterizado por:
·
Replicação de código – é replicado código com as cláusulas de tratamento de
exceções. Um aspecto poderia contemplar a responsabilidade tratamento de
exceções;
·
Aumento da dependência entre módulos -
a tentativa de implementar as
responsabilidades secundárias em classes intermediárias aumenta a interdependência
entre os módulos o que dificulta sua inserção em outro contexto;
·
Comprometimento da performance - determinado código pode as vezes ser
restrito a contextos particulares. Um bom exemplo é dado por um conjunto de
13
This watermark does not appear in the registered version - http://www.clicktoconvert.com
12
forma como controle de concorrência não é a responsabilidade primária de uma classe
projetada para acesso a dados (ASPECT-ORIENTED PROGRAMMING (AOP), 2000).
Mas como tratar as responsabilidades comuns do sistema? A POA introduz
um módulo reusável denominado Aspecto que encapsula as responsabilidades comuns
das classes da aplicação inibindo a replicação de código. Na próxima seção serão
discutidas as questões relacionadas a este elemento básico da POA.
2.2. O Aspecto como Unidade Funcional da Aplicação
As metodologias de análise e projeto de sistemas evoluíram ao longo do
tempo e representam conhecimento sólido a respeito de como produzir software
reutilizável. Entretanto elas não oferecem abordagens que permitam ao desenvolvedor
tratar o compartilhamento das responsabilidades comuns entre os módulos das
aplicações. Tal característica deve-se ao fato de que estas metodologias foram
desenvolvidas sob a premissa básica de que a unidade funcional do software é o módulo
(ASPECT-ORIENTED PROGRAMMING (AOP), 2000).
A abordagem OO apresenta diversas características vantajosas como
encapsulamento, hierarquia e alto grau de modularidade. Porém como já pôde ser
observado na fig. 2.1, classes não são funcionais no que diz respeito às
responsabilidades sistêmicas que extrapolam suas fronteiras: as responsabilidades
comuns.
A natureza do módulo está em definir e implementar a estrutura primária do
sistema. As responsabilidades secundárias – que podem vir a assumir o caráter de
responsabilidade comum - surgem como um efeito colateral indesejado e muitas vezes
inevitável. Elas acabam então sendo agregadas à estrutura principal do sistema,
aumentando o código em volume e complexidade.
O aspecto pode ser descrito como uma unidade funcional que encapsula um
comportamento comum a diversas classes do sistema (LESIECKI, 2002). Este
comportamento comum é representado pelas responsabilidades comuns, logo o aspecto
é uma unidade que encapsula as responsabilidades comuns das classes da aplicação.
12
This watermark does not appear in the registered version - http://www.clicktoconvert.com
11
responsabilidade comum a ambas que é a impressão de mensagens. Seria possível
modularizar a emissão de mensagens em uma classe intermediária. Entretanto surgiriam
dois efeitos imediatos :
·
Dependência das classes Ponto e Linha para com esta terceira classe o que gera
diminuição do grau de reusabilidade;
·
Maior overhead na chamada de métodos quando uma mensagem “W” ou “R”
precisasse ser impressa.
Outra situação típica do que seria uma responsabilidade comum poderia ser
o controle de exceções. Tome-se uma aplicação composta por inúmeras classes. Para
cada classe são declarados inúmeros métodos que realizam operações diversas(acesso a
dados, comunicação remota, alocação de recursos entre outros). É pertinente presumir
que deverá haver o controle dos erros que poderão vir a ocorrer durante a execução
destas operações. Estes métodos irão declarar suas próprias cláusulas catch e tratarão
seus erros de forma independente sempre que eles ocorrerem. Esta é a forma pela qual
este problema pode ser resolvido no paradigma OO. Então todos os métodos que
realizam operações sobre dados deverão ter a capacidade de tratar os erros decorrentes
do acesso a dados. Também todos os métodos que realizam operações de comunicação
remota deverão ter a capacidade de tratar os erros decorrentes de falha de comunicação
e assim por diante.
A primeira conclusão e talvez a mais óbvia é que responsabilidade comum
significa a constante replicação de segmentos de código. É replicado código para
cláusulas de tratamento de erros, para controle de acesso compartilhado a dados, para
processos de logging e várias outras operações. Esta característica pode ser observada
nas classes Ponto e Linha onde a responsabilidade comum de emissão de mensagens é
caracterizada pela replicação do código relativo a esta operação.
Cabe outra observação importante e não tão óbvia quanto a mencionada
acima. A responsabilidade comum não significa essencialmente responsabilidade
primária. Ao contrário, responsabilidades comuns têm como principal característica o
fato de serem responsabilidades secundárias dentro das classes do sistema. Da mesma
11
This watermark does not appear in the registered version - http://www.clicktoconvert.com
10
1 Class Ponto
2 {
3
int _x = 0;
4
int _y = 0;
5
6
int getX ()
7
{
8
System.out.println(“R”);
9
Return _x;
10
}
11
12
void setX (int x)
13
{
14
System.out.println(“W”);
15
_x = x;
16
}
17
18
void setY (int y)
19
{
20
System.out.println(“W”);
21
_y = y;
22
}
23 }
1 Class Linha
2 {
3
Ponto _P1;
4
Ponto _P2;
5
6
Void setP1 (Ponto)
7
{
8
System.out.println(“W”);
9
_P1 = Ponto;
10
}
11
12
void setP2 (Ponto)
13
{
14
System.out.println(“W”);
15
_P2 = Ponto;
16
}
17
18
Ponto getP2 ()
19
{
20
System.out.println(“R”);
21
Return _P2;
22
}
23}
Figura 2.1 - Classes Ponto e Linha
Para que se possa compreender melhor o conceito vamos observar as classes
Ponto
e Linha descritas acima. Pode ser visto que ambas modularizam suas
responsabilidades primárias que são :
·
A classe Ponto representa pontos no plano;
·
A classe Linha representa uma linha formada a partir da junção de dois pontos.
Entretanto existe uma responsabilidade comun compartilhada entre estas
duas classes que é a impressão de mensagens :
·
Os métodos set...() de ambas as classes, quando invocados, devem emitir uma
mensagem ‘W’;
·
Os métodos get...() de ambas as classes, quando invocados, devem emitir uma
mensagem ‘R’.
Eis então que estas classes, além de implementarem suas responsabilidades
primárias que é representar algo sobre pontos e linhas, implementam também uma
10
This watermark does not appear in the registered version - http://www.clicktoconvert.com
9
Elas são a essência da POA e são referidas na literatura como crosscutting concerns ou
crosscuts (VOELTER, 2000).
A aplicação do termo crosscut define a natureza da responsabilidade comum
como algo ‘passante’, algo que traspassa a estrutura primária das classes do sistema. Ela
não pode ser codificada como uma responsabilidade particular bem definida. Ao
contrário, é uma responsabilidade compartilhada por múltiplas classes dentro da
aplicação. “Ë uma característica que atravessa a aplicação afetando o comportamento
de inúmeras classes não podendo ser codificada como uma responsabilidade bem
definida de uma única classe” (ASPECT- ORIENTED PROGRAMMING (AOP),
2000).
Um dos princípios básicos da OO é a definição das responsabilidades para
as classes do sistema. Cada coisa é feita em um único lugar. Por este motivo a
responsabilidade comum, na sua definição, é um elemento que viola este princípio
básico (VOELTER, 2000). Ao contrário de espalhar o código relativo a uma
responsabilidade do sistema ao longo de diversos componentes a linguagem de
programação deve oferecer a possibilidade de expressar esta responsabilidade em um
único e coerente pedaço de código – uma classe, um módulo, etc (WALKER et al,
2000, ASPECTJ DOCUMENTATION AND RESOURCES, 2002).
À primeira vista a consolidação do conceito responsabilidade comum
aplicado sobre um modelo que prega a divisão de responsabilidades pode parecer difícil
de ser concebido. Pode parecer até mesmo um paradoxo. Mas uma visão mais apurada
pode mostrar que o conceito responsabilidade comum é de fato infligido sobre o modelo
OO e agride o princípio básico da modularidade (LOPES & KICKZALES, 2000).
É interessante observar a fig. 2.1 - Classes Ponto e Linha. Estas classes
possuem uma implementação muito simples onde nas operações set...() é impressa uma
mensagem “W” e nas operações get...() é impressa uma mensagem “R”. O código
referente à impressão destas mensagens pode ser visto nas linhas 8, 14 e 20 destas
classes.
Estes
segmentos de código representam as responsabilidades comuns
implementadas nestas classes.
9
This watermark does not appear in the registered version - http://www.clicktoconvert.com
8
Capítulo II
O Modelo Orientado a Aspectos
A abordagem OO tem se destacado nos últimos anos dando a impressão de
haver substituído de forma completa a abordagem procedural. Sem sombra de dúvida, a
abordagem OO tem muitas vantagens sobre sua precedente. A definição de classes
abstratas induz a um alto grau de modularização. Os objetos possuem responsabilidades
definidas e colaboram entre si de modo atingir um objetivo comum. Há de ser
mencionado também o forte grau de reusabilidade alcançado. De fato o que se espera de
um aplicativo concebido sob a abordagem OO é que o resultado final seja um projeto
modularizado e limpo que nos leve a produzir código também modularizado e limpo. A
modularidade, reusabilidade e definição de responsabilidades que são oferecidos pelo
modelo OO são recursos que certamente contribuem em tempos onde o tamanho e a
complexidade dos artefatos de software cresce a olhos vistos.
Mas existem responsabilidades que, pela sua natureza, não podem ser
definidas e codificadas como responsabilidade de uma única classe. Elas ultrapassam a
fronteira do objeto e necessitam ser tratadas pelo conjunto de classes do sistema. Logo
degradam a noção de modularização defendida pelo modelo OO. Estas
responsabilidades são denominadas como responsabilidades comuns. A POA surge
então como uma nova forma de construir código onde as responsabilidades comuns são
capturadas e modularizadas, podendo ser reutilizadas nos diversos segmentos de código
onde são requeridas.
2.1. Responsabilidades Comuns - Fundamento do Alto Nível de Abstração da
POA
As responsabilidades comuns são responsabilidades que não podem ser
concebidas como pertencentes a uma única classe. Elas afetam diversos componentes da
aplicação e necessitam então ser incluídas em todo o conjunto de componentes afetados.
8
This watermark does not appear in the registered version - http://www.clicktoconvert.com
7
Na segunda versão é aplicada a abordagem proposta no cap. 4, produzindo
assim uma versão otimizada e mais reutilizável. São apresentadas as deficiências
detectadas na primeira versão e os benefícios posteriormente obtidos com a versão
POA do aplicativo.
Capítulo 6
São discutidos os resultados obtidos em relação aos objetivos apresentados na
seção 1.2 e também são feitas sugestões para trabalhos futuros.
7
This watermark does not appear in the registered version - http://www.clicktoconvert.com
6
1.1. Objetivos
Esta dissertação tem como objetivo um estudo sobre a aplicação da POA no
desenvolvimento de projetos reutilizáveis de software sob duas diretrizes básicas que
são:
1) modularização das responsabilidades comuns presentes nas classes do sistema;
2) a modularização das RCE para a validação do modelo orientado a aspectos na
produção de softwares reutilizáveis.
1.2. Organização
Capitulo 2
É apresentada a fundamentação a respeito dos conceitos do modelo orientado a
aspectos. São definidos os conceitos fundamentais do paradigma como aspecto, advice,
ponto de corte, ponto de junção e introduções.
Capítulo 3
É apresentada a linguagem de programação AspectJ, que é uma implementação
para os conceitos da orientação a aspectos.
Capítulo 4
É apresentada uma nova visão do modelo orientado a aspectos que é a
aplicação da POA no desenvolvimento de projetos reutilizáveis de software. Esta nova
visão da aplicação dos aspectos é apresentada na forma uma abordagem definida como
modularização das RCE. É também proposta uma metodologia para o processo de
modularização das RCE e a restruturação do sistema para uma versão mais otimizada
do ponto de vista da reutilização.
Capítulo 5
É apresentado o desenvolvimento do aplicativo Figuras Flutuantes. Este aplicativo
é mostrado em duas versões: a primeira sob uma abordagem totalmente OO e a segunda
versão agora migrando para o paradigma da orientação a aspectos.
6
This watermark does not appear in the registered version - http://www.clicktoconvert.com
5
Como meio de alcançar o objetivo de desenvolvimento de projetos de
software reutilizáveis é proposta uma metodologia para a identificação e modularização
das RCE. As RCE estão relacionadas à efetividade do mecanismo de herança nos
termos descritos acima. Isto porque elas representam o conjunto de operações que,
estando declarados nas classes do sistema como fator de reusabilidade, tornam-se
subutilizadas ou mesmo obsoletas quando a classe se encontra inserida em um contexto
particular.
A modularização das RCE nos permite que as classes do sistema
implementem em sua estrutura apenas as operações comuns aos possíveis contextos
onde o sistema poderá vir a executar.
As operações específicas ao contexto serão agregadas apenas quando
necessário. O resultado final esperado para o aplicativo é a sua adaptabilidade a diversos
contextos porém implementando apenas operações essenciais a todos eles.
Como forma de viabilizar a proposta foi desenvolvido um aplicativo gráfico
simples onde não são aplicados quaisquer recursos sofisticados oferecidos atualmente
pelo modelo OO. Desta foram abolidos propositadamente da modelagem apresentada
neste trabalho a inclusão de padrões de projeto que pudessem eventualmente otimizar a
arquitetura.
Esta decisão foi tomada em função da proposta aqui apresentada que
concentra-se pura e simplesmente na efetividade do mecanismo de herança do modelo
OO, conforme exposto nos parágrafos acima.
O objeto é avaliar os benefícios da POA especificamente no que tange à
possibilidade do tratamento desta efetividade. A aplicação de padrões de projeto ou
outros recursos apenas alargariam o escopo deste trabalho.
Finalmente acredita-se que este trabalho venha ser algo que possa somar aos
inúmeros esforços empreendidos na área de otimização de software. Que possa
contribuir de alguma forma na avaliação da abordagem POA que apesar de recente tem
sido objeto de diversos estudos e que possa ser de algum valor na avaliação das suas
contribuições reais ao modelo OO.
5
This watermark does not appear in the registered version - http://www.clicktoconvert.com
4
Este mecanismo representa algo de muito vantajoso visto que não
precisamos gastar tempo refazendo operações que já foram codificadas uma vez. É
possível reutilizar ou alterar métodos das superclasses existentes bem como incluir
novos membros nas subclasses. São obtidas então modularidade, reusabilidade e toda a
gama de vantagens oferecidas pela abordagem orientada a objetos.
Mas o modelo OO não prevê mecanismos que permitam a distinção entre as
operações que realmente vão ser utilizadas por uma instância de classe em um contexto
particular daquilo que pode ser considerado como uma ‘herança inútil’. O termo
herança inútil pode ser entendido como uma referência a um atributo ou um método
declarado na classe e que foi herdado pela sua instância, mas não se aplica ao contexto
onde esta instância se encontra inserida no momento.
É um mecanismo efetivo porque é aplicado a todos os atributos e métodos
declarados por uma classe. Como resultado implica que todas as suas instâncias e
também todas as instâncias de suas subclasses herdarão todo um conjunto de operações
indiscriminadamente.
De um modo geral se considerarmos uma classe que implementa um grande
número de operações onde algumas são aplicadas somente a contextos específicos,
pode-se chegar a situações onde:
·
Operações não necessárias ao contexto atual estão permanentemente presentes nas
instâncias desta classe gerando algum aumento do código executável;
·
Operações são implementadas de forma genérica para serem aplicadas a todos os
contextos gerando algum overhead.
Seria interessante do ponto de vista da reutilização se as instâncias das
classes herdassem apenas o conjunto de operações necessárias e que realmente vão ser
utilizadas durante seu período de execução. Desta forma, independentemente do perfil
genérico da classe, a instância seria sempre uma entidade especializada para o contexto
onde se encontra inserida.
4
This watermark does not appear in the registered version - http://www.clicktoconvert.com
3
·
Compiladores inteligentes – as compilações JIT, dinâmica e adaptativa promovem
alterações no código executável visando otimização do uso dos recursos de
hardware e aumento do desempenho ( XUE et al, 2001, RICHTER, 2002,
HARDWIK, 1997, HOMEPAGE BY IBM LABS - JIT/400, 1999);
·
Otimização de bytecodes – é possível pensar em melhoramentos da estrutura do
arranjo de bytecodes de Java visando aumento do desempenho em situações
específicas
(HARDWIK, 1997, JENSEN, 2000, JENSEN, 2001, APPLE
COMPUTER INC.
- AUTOMATED CODE OPTIMIZATION, 2001, S5
SYSTEMS INC - BYTE CODE OPTIMIZATION, 2002, SHUDO, 2002).
As técnicas são variadas, mas a motivação central para o estudo e
desenvolvimento de técnicas de otimização giram em torno de duas diretrizes básicas
que são :
a) como diminuir o tamanho do código executável visando consumir menos recursos
de processamento e memória;
b) como tornar sua execução mais rápida.
Circunscrito neste enfoque da otimização surge a POA (Programação
Orientada a Aspectos) idealizada por pesquisadores da Xerox PARC (KICKZALES et
al, 1997). É importante observar que o modelo orientado a aspectos não vêm em
substituição, mas em adição ao modelo OO sob a promessa da modularização das
responsabilidades comuns como forma de obter algum grau de otimização para as
classes do sistema.
O modelo de aspectos permite de fato a modularização das
responsabilidades comuns de uma forma natural, eliminando a replicação de código que
é seu maior objetivo. Entretanto a contribuição deste trabalho está em lançar uma visão
diferenciada sobre a POA, objetivando a aplicação do modelo orientado a aspectos no
desenvolvimento de projetos de software reutilizáveis. A origem da proposta aqui
apresentada concentra-se em uma característica intrínseca do modelo OO e que pode de
alguma forma ser tratada pela orientação a aspectos: o mecanismo de herança.
3
This watermark does not appear in the registered version - http://www.clicktoconvert.com
2
melhor desempenho. Para uma aplicação destinada a resolver um problema em
particular é possível:
·
Aplicar uma linguagem orientada a domínio ao invés de uma linguagem de
propósito geral;
·
Aplicar construções da linguagem que sejam específicas ao domínio do problema ao
invés de aplicar estruturas genéricas de forma indiscriminada.
De modo geral, este tipo de aplicação pode agregar apenas os recursos
estritamente necessários ao domínio do problema em questão. Como consequência
estes aplicativos consomem menos recursos de memória e processador, são mais
simples de serem desenvolvidos e mantidos e, geralmente, têm melhor desempenho. Em
contraponto à vantagem oferecida pela sua especificidade, este tipo de componente de
software pode apresentar uma característica desvantajosa: o seu grau de reusabilidade
pode ser muito reduzida.
Isto talvez torne difícil integrá-lo a outros componentes tornando difícil
adaptá-lo a diferentes contextos a menos que sejam realizadas customizações manuais.
São observadas situações antagônicas onde é preciso escolher uma das seguintes
opções:
a) um componente de bom desempenho, mas com menor reusabilidade;
b) um componente com maior grau de reusabilidade, mas que é mais oneroso em
termos do consumo de recursos.
O ideal perseguido, e talvez utópico, seria classes genéricas e reusáveis que
sejam capazes de alcançar o nível de otimização de classes especializadas sempre que
requisitado por um contexto específico.
Surgem então esforços no desenvolvimento de técnicas que possam
amenizar a queda de desempenho, com o intuito de produzir algum grau de otimização.
Dentre as mais conhecidas encontram-se:
2
This watermark does not appear in the registered version - http://www.clicktoconvert.com
Capítulo I
Introdução
A explosiva evolução do hardware torna-se evidente a cada vez que surgem
processadores mais poderosos, memórias de acesso mais rápido e mídias mais potentes.
A maior disponibilidade de recursos tem determinado uma característica dominante a
respeito dos componentes de software: sua genericidade.
A abordagem OO tem se destacado nos últimos anos dando a impressão de
haver substituído de forma completa a abordagem procedural. Sem sombra de dúvida a
abordagem OO tem muitas vantagens em relação à sua precedente. A definição de
classes abstratas induz a um alto grau de modularização. Os objetos possuem
responsabilidades definidas e colaboram entre si de modo atingir um objetivo comum.
Há de ser mencionado também o alto grau de reusabilidade que pode ser alcançado.
De fato o que se espera de um aplicativo concebido sob a abordagem OO é
que o resultado final seja um projeto modularizado e limpo e que nos leve a produzir
código também modularizado e limpo. A modularidade, reusabilidade e definição de
responsabilidades que são oferecidos pelo modelo OO são recursos que certamente
contribuem em tempos onde o tamanho e a complexidade dos artefatos de software
cresce a olhos vistos.
Um artefato genérico é reusável, capaz de interagir com outros
componentes, executar em diversas plataformas e adaptar-se a diversos contextos
diferentes. As soluções genéricas pelo fato de serem projetadas para um domínio de
aplicações podem arrastar consigo vastas bibliotecas de recursos, interpretadores e
outros mecanismos e construções de uso geral implementados na linguagem. O
resultado final é o aumento natural do custo de memória e processamento.
As soluções projetadas para uma aplicação específica consomem menos
recursos, são mais simples de serem desenvolvidas e mantidas e de modo geral têm
This watermark does not appear in the registered version - http://www.clicktoconvert.com
x
Abstract
This dissertion develops a study on the use of AOP(Aspect Oriented Language)
in the production of reusable software projects. The main project strategy used was the
modularization of CSR(Context Specific Responsabilities) in shape of aspects, so that the
classes implement only de operations related to their primary structure.
A simple graphic software called Floating Pictures was developed. In this
software the CSR were modularizated. This software is constituted of classes that implement
only a small set of operations that are common to both of the distinct contexts where it was
executed. The operations related to the particuarities of these two contexts started to be
agregated by the system classes only when necessary.
The results showed that the some group of classes could be used for different
necessities, achieving with success the objective of using AOP in the development of reusable
software projects.
x
This watermark does not appear in the registered version - http://www.clicktoconvert.com
ix
Resumo
Esta
dissertação
desenvolve
um
estudo
sobre
a
utilização
da
POA(Programação Orientada a Aspectos) na produção de projetos de software
reutilizáveis. A principal estratégia de projeto utilizada foi a modularização das RCE
(Responsabilidades do Contexto Específico) na forma de aspectos, para que as classes
implementem apenas o conjunto de operações relativas à sua estrutura primária.
Desenvolveu-se um software gráfico simples chamado Figuras Flutuantes
no qual as RCE foram modularizadas. Este software constitui-se de classes que
implementam apenas um pequeno conjunto de operações comuns aos dois contextos
distintos onde foi executado. As operações relacionadas às particularidades destes dois
contextos passaram a ser agregadas pelas classes do sistema apenas quando necessárias.
Os resultados mostraram que o mesmo conjunto de classes pôde ser
aplicado a necessiades diferenciadas, atingido com sucesso o objetivo de aplicar a POA
no desenvolvimento de projetos de software reutilizáveis.
Palavras-chave: orientação a aspectos, projeto de software, reutilização, programação.
ix
This watermark does not appear in the registered version - http://www.clicktoconvert.com
viii
Lista de Acrônimos
JIT
Just In Time
JVM
Java Virtual Machine
OO
Orientação a Objetos
POA
Programação Orientada a Aspectos
RCE
Responsabilidades do Contexto Específico
TAO
Taxa de Aplicação das Operações
UML
Unified Modeling Language
viii
This watermark does not appear in the registered version - http://www.clicktoconvert.com
vii
Figura 4.5 – Classe acessaDados Restruturada...............................................................53
Figura 4.6 – Aspecto acessoRemoto................................................................................54
Figura 4.7 – Tecendo o Aspecto acessoRemoto..............................................................54
Figura 4.8 – Classe acessaDados Agregando RCE.........................................................55
Figura 4.9 – Instancias da Classe acessaDados e as RCE Agregadas............................56
Figura 4.10 – Nova Configuração de Contextos para a Classe acessaDados.................58
Figura 5.1 – Esquema de Conexões do Aplicativo..........................................................62
Figura 5.2 – Colisão entre Figuras...................................................................................62
Figura 5.3 – Diagrama de Classes do Sistema.................................................................64
Figura 5.4 – Replicação de Código para Tratamento de Exceções.................................67
Figura 5.5 – Referências entre as Classes do Sistema.....................................................68
Figura 5.6 –Classes do Sistema sem a Modularização das RCE.....................................69
Figura 5.7 – Tratamento de Exceções das Classes do Sistema.......................................72
Figura 5.8 – Aspecto trataExcecao.................................................................................75
Figura 5.9 – Tabulação RCE das Classes Circulo, Triangulo e Retangulo.....................77
Figura 5.10 – Tabulação RCE da Classe Display............................................................78
Figura 5.11 – Tabulação RCE da Classe Registrador.....................................................79
Figura 5.12 – O Aspecto Navegacao...............................................................................81
Figura 5.13 – O Aspecto pintaLinhas..............................................................................83
Figura 5.14 – O Aspecto trataColisao.............................................................................84
Figura 5.15 – O Aspecto reduzTempoDeVida.................................................................86
Figura 5.16 – O Aspecto protecaoDoRegistro................................................................88
Figura 5.17 – Aplicativo Figuras Flutuantes com a Modularização das RCE................92
vii
This watermark does not appear in the registered version - http://www.clicktoconvert.com
vi
Lista de Figuras
Figura 2.1 – Classes Ponto e Linha................................................................................10
Figura 2.2 – Entrelaçamento de Código..........................................................................14
Figura 2.3 – Modularização do Código Entrelaçado................................................... ...15
Figura 2.4 – Pontos de Corte...........................................................................................17
Figura 2.5 – Anatomia do Advice....................................................................................18
Figura 2.6 – Visão Conceitual do Advice........................................................................19
Figura 2.7 – Noção Temporal do Advice.........................................................................19
Figura 2.8 – Relacionamento Classe-Objeto...................................................................22
Figura 2.9 – Aspecto Referenciando Duas Classes.........................................................23
Figura 2.10 – Relação Aspecto-Classe............................................................................24
Figura 3.1 – Aspectj como Solução de Propósito Geral..................................................28
Figura 3.2 – Ponto de Corte AspectJ...............................................................................29
Figura 3.3 – Ponto de Corte Nomeado Declarado como Membro de Classe..................30
Figura 3.4 – Pontos de Corte Abstratos..........................................................................31
Figura 3.5 – Ponto de Corte sem Retorno de Valor........................................................32
Figura 3.6 – Ponto de Corte com Retorno do Objeto Chamado.....................................32
Figura 3.7 – Ponto de Corte com Retorno do Objeto Passado como Parâmetro............33
Figura 3.8 – Ponto de Corte com Retorno de Dois Objetos............................................33
Figura 3.9 – Ponto de Corte com Retorno de Um Objeto e Um Valor Inteiro...............33
Figura 3.10 – Regra Geral de Parametrização.................................................................34
Figura 3.11 – Introduzindo Novos Membros na Classe Ponto....................................... 35
Figura 3.12 – Advice Around()........................................................................................36
Figura 3.13 – Anatomia do Aspecto................................................................................38
Figura 3.14 – Tecimento Estático Aplicando Inline........................................................39
Figura 3.15 – Tecimento Estático por Composição Explícita.........................................40
Figura 3.16 – Classe e Métodos Tecidos.........................................................................41
Figura 3.17 – Diagrama de Estados da Classe Tecida C`...............................................42
Figura 4.1 – Contextos Aplicados a Classe acessaDados...............................................46
Figura 4.2 – Responsabilidades Comuns x RCE.............................................................48
Figura 4.3 – Tabulação RCE da Classe acessaDados.....................................................52
Figura 4.4 – Identificação das RCE da Classe acessaDados..........................................53
vi
This watermark does not appear in the registered version - http://www.clicktoconvert.com
v
Capítulo VI
Conclusão........................................................................................................................95
6.1. Sugestão para Trabalhos Futuros............................................................... 95
Referências Bibliográficas...............................................................................................96
ANEXO 1......................................................................................................................100
ANEXO 2......................................................................................................................101
ANEXO 3......................................................................................................................106
v
This watermark does not appear in the registered version - http://www.clicktoconvert.com
iv
Capítulo IV
Desenvolvimento de Projetos de Software Reutilizáveis – Uma Visão Diferenciada do
Modelo Orientado a Aspectos.........................................................................................43
4.1. O Conceito de RCE...................................................................................... 43
4.2. Responsabilidade Comum x RCE................................................................ 48
4.3. Uma Convenção para Identificação das RCE.............................................. 50
Capítulo V
Um Projeto de Software Reutilizável Utilizando POA – Uma Abordagem Otimizada da
Orientação a Aspectos.................................................................................................... 59
5.1. Características Gerais do Aplicativo............................................................ 59
5.1.1. O Contexto C1.............................................................................. 60
5.1.2. O Contexto C2.............................................................................. 63
5.2. A Versão OO do Aplicativo......................................................................... 63
5.2.1. As Responsabilidades para as Classes do Sistema........................ 65
5.2.2. As Deficiências Detectadas........................................................... 66
5.2.2.1. Entrelaçamento de Código............................................. 67
5.2.2.2. Herança de Operações Obsoletas ao Contexto C2......... 69
5.3. A Versão POA do Aplicativo...................................................................... 71
5.3.1. A Modularização das Responsabilidades Comuns....................... 71
5.3.2. A Modularização das RCE............................................................ 75
5.3.2.1. O Aspecto Navegacao.................................................... 81
5.3.2.2. O Aspecto pintaLinhas................................................... 83
5.3.2.3. O Aspecto trataColisao.................................................. 84
5.3.2.4. O Aspecto reduzTempoDeVida...................................... 85
5.3.2.5. O Aspecto protecaoDoRegistro..................................... 87
5.3.3. Os Benefícios Obtidos.................................................................. 89
5.3.3.1. Benefícios da Modularização das Responsabilidades
Comuns........................................................................................89
5.3.3.2. Benefícios da Modularização das RCE...........................90
5.4. Crítica ao Modelo Orientado a Aspectos..................................................... 93
iv
This watermark does not appear in the registered version - http://www.clicktoconvert.com
iii
Sumário
Capítulo I
Introdução......................................................................................................................... 1
1.1 Objetivos......................................................................................................... 6
1.2 Organização.................................................................................................... 6
Capítulo II
O Modelo Orientado a Aspectos...................................................................................... 8
2.1. Responsabilidades Comuns – Fundamento do Alto Nível de Abstração da
POA...................................................................................................................... 8
2.2. O Aspecto como Unidade Funcional da Aplicação..................................... 12
2.3. As Responsabilidades Comuns e o Entrelaçamento.................................... 13
2.4. Os Elementos do Modelo Orientado a Aspectos......................................... 16
2.4.1. Pontos de Junção.......................................................................... 16
2.4.2. Pontos de Corte............................................................................. 17
2.4.3. Advices.......................................................................................... 18
2.4.4. O Aspecto...................................................................................... 20
2.5. O Relacionamento Aspecto-Classe.............................................................. 21
Capítulo III
Projeto Orientado a Aspectos com Aspectj.................................................................... 26
3.1. O Modelo de Pontos de Junção................................................................... 29
3.2. O Modelo de Pontos de Corte..................................................................... 29
3.2.1. A Nomeação dos Pontos de Corte................................................ 30
3.2.2. Parametrização dos Pontos de Corte............................................ 32
3.3. Introduções.................................................................................................. 34
3.4. Os Advices.................................................................................................... 36
3.4.1. A Ordem de Precedência dos Advices........................................... 37
3.5. Aspectos....................................................................................................... 37
3.6. Tecedor de Aspectos e Classes – Aspect Weaver........................................ 38
iii
This watermark does not appear in the registered version - http://www.clicktoconvert.com
ii
Um Estudo sobre a Utilização de Aspectos no
Desenvolvimento de Projetos Reutilizáveis de Software
Carlos Alberto Barth
Esta Dissertação foi julgada adequada para a obtenção do título de Mestre em Ciência
da Computação Área de Concentração Sistemas de Computação e aprovada em sua
forma final pelo Programa de Pós-Graduação em Ciência da Computação.
________________________________
Prof. Fernando A. Ostuni Gauthier, Dr.
Coordenador
Banca Examinadora
___________________________________
Prof. Rosvelter João Coelho da Costa, Dr.
Orientador
___________________________________
Prof. Mario A. R. Dantas, Dr.
___________________________________
Prof. Roberto Willrich, Dr.
ii
This watermark does not appear in the registered version - http://www.clicktoconvert.com
UNIVERSIDADE FEDERAL DE SANTA CATARINA
PROGRAMA DE PÓS-GRADUAÇÃO EM CIÊNCIA DA
COMPUTAÇÃO
Carlos Alberto Barth
Um Estudo sobre a Utilização de Aspectos no
Desenvolvimento de Projetos Reutilizáveis de Sofware
Dissertação submetida à Universidade Federal de Santa Catarina como parte dos
requisitos para a obtenção do grau de Mestre em Ciência da Computação.
Prof. Rosvelter João Coelho da Costa
Orientador
Florianópolis, Outubro de 2003
Download

Modelo Aspectj para Pontos de Junção