2. KAVRAMSAL ÇERÇEVE
6.4. Araştırmacılar İçin Öneriler
Alguns testes foram realizados para verificar, ap´os o desenvolvimento da solu¸c˜ao pro- posta, os ganhos obtidos com a elimina¸c˜ao de r´eplicas em programas com diferentes usos de adendos de contorno. Esta se¸c˜ao apresenta o benchmark utilizado e, em se-
guida, a redu¸c˜ao no tamanho do c´odigo obtida para cada programa do benchmark pela execu¸c˜ao do programa descrito na Se¸c˜ao 4.1.3.
Singleton
A implementa¸c˜ao em AspectJ do padr˜ao de projeto singleton [GHJV95], proposta por Hannemann e Kiczales em [HK02], utiliza adendos de contorno para substituir chamadas ao construtor de uma classe, e retornar a instˆancia ´unica criada na primeira ativa¸c˜ao do construtor. O c´odigo-fonte de exemplo dessa implementa¸c˜ao6 realiza trˆes
chamadas em seq¨uˆencia ao construtor de uma classe, para demonstrar que as referˆencias retornadas por essas chamadas s˜ao iguais.
A implementa¸c˜ao do padr˜ao singleton em AspectJ, mostrada na Listagem 4.2, de- fine um conjunto de jun¸c˜ao abstrato, protectionExclusions, para permitir a exclus˜ao da aplica¸c˜ao do aspecto em algumas classes, e uma interface vazia Singleton. O adendo de contorno definido nas linhas 5 a 12 captura chamadas a construtores de subclasses de
Singleton, armazenando a primeira referˆencia de cada classe tratada, e retornando esta referˆencia nas demais chamadas ao construtor dessa classe.
1 p u b l i c a b s t r a c t a s p e c t S i n g l e t o n P r o t o c o l { 2 p r i v a t e H a s h t a b l e s i n g l e t o n s = new H a s h t a b l e ( ) ; 3 p u b l i c i n t e r f a c e S i n g l e t o n {} 4 p r o t e c t e d p o i n t c u t p r o t e c t i o n E x c l u s i o n s ( ) ; 5 O b j e c t around ( ) : c a l l ( ( S i n g l e t o n +). new ( . . ) ) 6 && ! p r o t e c t i o n E x c l u s i o n s ( ) { 7 C l a s s s i n g l e t o n = t h i s J o i n P o i n t . g e t S i g n a t u r e ( ) . g e t D e c l a r i n g T y p e ( ) ; 8 i f ( s i n g l e t o n s . g e t ( s i n g l e t o n ) == n u l l ) { 9 s i n g l e t o n s . p u t ( s i n g l e t o n , proceed ( ) ) ; 10 } 11 r e t u r n s i n g l e t o n s . g e t ( s i n g l e t o n ) ; 12 } 13 }
Listagem 4.2: Protocolo do padr˜ao singleton em AspectJ, extra´ıdo de [HK02].
A classe singleton da aplica¸c˜ao de exemplo fornecida com o c´odigo-fonte dos padr˜oes de projeto implementados por Hannemann ´e Printer, cujo c´odigo ´e mostrado na Lis- tagem 4.3. PrinterSubclass, que tamb´em aparece nessa listagem, deve ser exclu´ıda do padr˜ao singleton, ou seja, chamadas ao construtor de PrinterSubclass devem ser execu- tadas sem interferˆencia do aspecto.
6
1 p u b l i c c l a s s P r i n t e r { 2 p r o t e c t e d s t a t i c i n t o b j e c t s S o F a r = 0 ; 3 p r o t e c t e d i n t i d ; 4 p u b l i c P r i n t e r ( ) { 5 i d = ++ o b j e c t s S o F a r ; 6 } 7 p u b l i c v o i d p r i n t ( ) {
8 System . o u t . p r i n t l n ( ”\tMy ID i s ”+i d ) ;
9 } 10 } 11 p u b l i c c l a s s P r i n t e r S u b c l a s s extends P r i n t e r { 12 p u b l i c P r i n t e r S u b c l a s s ( ) { 13 s u p e r( ) ; 14 } 15 }
Listagem 4.3: Classes de exemplo para aplica¸c˜ao do padr˜ao singleton.
O aspecto concreto da Listagem 4.4 determina que Printer ´e um singleton e que
PrinterSubclass deve ser ignorada pelo adendo de contorno de SingletonProtocol.
1 p u b l i c a s p e c t S i n g l e t o n I n s t a n c e extends S i n g l e t o n P r o t o c o l { 2 d e c l a r e p a r e n t s: P r i n t e r implements S i n g l e t o n ;
3 p r o t e c t e d p o i n t c u t p r o t e c t i o n E x c l u s i o n s ( ) : 4 c a l l( ( P r i n t e r S u b c l a s s +). new ( . . ) ) ;
5 }
Listagem 4.4: Implementa¸c˜ao concreta do protocolo definido na Listagem 4.2.
O programa de teste desse padr˜ao de projeto cria trˆes instˆancias de Printer e trˆes instˆancias de PrinterSubclass. Como mostram os testes da Listagem 4.5, as trˆes re- ferˆencias de Printer s˜ao iguais, por´em as referˆencias para PrinterSubclass s˜ao diferentes. Note que, no m´etodo test1 da classe Main, realizam-se trˆes chamadas ao construtor da classe Printer, que s˜ao capturadas pelo adendo de contorno de SingletonProtocol.
1 p u b l i c c l a s s Main {
2 p r i v a t e s t a t i c P r i n t e r p r i n t e r 1 , p r i n t e r 2 , p r i n t e r 3 ; 3 p r i v a t e s t a t i c v o i d t e s t 1 ( ) {
4 System . o u t . p r i n t l n ( ”\ n T e s t 1 : A l l t h r e e p r i n t e r s s h o u l d have t h e ”
6 p r i n t e r 1 = new P r i n t e r ( ) ; 7 p r i n t e r 2 = new P r i n t e r ( ) ; 8 p r i n t e r 3 = new P r i n t e r ( ) ; 9 p r i n t e r 1 . p r i n t ( ) ; 10 p r i n t e r 2 . p r i n t ( ) ; 11 p r i n t e r 3 . p r i n t ( ) ; 12 } 13 p r i v a t e s t a t i c v o i d t e s t 2 ( ) { 14 System . o u t . p r i n t l n ( ”\ n T e s t 2 : A l l t h r e e o b j e c t s s h o u l d ” 15 + ” be i d e n t i c a l ” ) ; 16 System . o u t . p r i n t ( ”\ tThey a r e ” ) ; 17 i f ( ( p r i n t e r 1 == p r i n t e r 2 ) && ( p r i n t e r 1 == p r i n t e r 3 ) ) { 18 System . o u t . p r i n t l n ( ” i d e n t i c a l ” ) ; 19 } 20 e l s e { 21 System . o u t . p r i n t l n ( ” n o t i d e n t i c a l ” ) ; 22 } 23 } 24 p r i v a t e s t a t i c v o i d t e s t 3 ( ) { 25 System . o u t . p r i n t l n ( ”\ n T e s t 3 : E n s u r i n g t h a t s u b c l a s s e s can a c c e s s ” 26 + ” t h e c o n s t r u c t o r ” ) ; 27 System . o u t . p r i n t l n ( ” ( A l l t h r e e o u t p u t s s h o u l d be d i f f e r e n t ) ” ) ; 28 p r i n t e r 1 = new P r i n t e r S u b c l a s s ( ) ; 29 p r i n t e r 2 = new P r i n t e r S u b c l a s s ( ) ; 30 p r i n t e r 3 = new P r i n t e r S u b c l a s s ( ) ; 31 p r i n t e r 1 . p r i n t ( ) ; 32 p r i n t e r 2 . p r i n t ( ) ; 33 p r i n t e r 3 . p r i n t ( ) ; 34 } 35 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) { 36 System . o u t . p r i n t l n ( ” T e s t i n g SINGLETON p a t t e r n ( a s p e c t j ) . . . ” ) ; 37 t e s t 1 ( ) ; 38 t e s t 2 ( ) ; 39 t e s t 3 ( ) ; 40 System . o u t . p r i n t l n ( ”\n . . . done . ” ) ; 41 } 42 }
SpaceWar
O jogo SpaceWar ´e um exemplo de AspectJ, distribu´ıdo com o pacote de ferramentas para desenvolvimento de programas em AspectJ com a IDE Eclipse, AspectJ Develop- ment Tools7 (AJDT). Esse exemplo demonstra v´arios tipos de aplica¸c˜oes de AspectJ,
e, dentre eles, a garantia de um contrato simples na intera¸c˜ao com o usu´ario: uma nave destru´ıda n˜ao pode ser movimentada.
Apenas um adendo de contorno ´e utilizado no c´odigo-fonte dessa aplica¸c˜ao, e seu c´odigo ´e mostrado na Listagem 4.6. O conjunto de jun¸c˜ao referenciado na linha 2 do aspecto EnsureShipIsAlive, declarado na classe Ship, ´e8:
1 p o i n t c u t helmCommandsCut ( S h i p s h i p ) :
2 t a r g e t( s h i p ) && ( c a l l ( v o i d r o t a t e ( i n t ) ) | |
3 c a l l( v o i d t h r u s t ( boolean ) ) | |
4 c a l l( v o i d f i r e ( ) ) ) ;
Embora o c´odigo do adendo implementado em EnsureShipIsAlive seja pequeno, ele ´e aplicado em v´arios pontos das classesPlayer eRobot, que tratam comandos de jogadores humanos e virtuais, respectivamente.
1 a s p e c t E n s u r e S h i p I s A l i v e { 2 v o i d around ( S h i p s h i p ) : S h i p . helmCommandsCut ( s h i p ) { 3 i f ( s h i p . i s A l i v e ( ) ) { 4 proceed( s h i p ) ; 5 } 6 } 7 }
Listagem 4.6: Garantia de contrato: uma nave deve estar “viva” para ser movimentada.
Rin’G e Thread Safety
Rin’G ´e um ambiente para execu¸c˜ao e anima¸c˜ao de algoritmos em grafos [CSST04], que usa a biblioteca Swing para intera¸c˜ao com o usu´ario. Nessa biblioteca, todas as opera¸c˜oes sobre componentes visuais devem ser realizadas na chamada event-dispatching
7
Dispon´ıvel em http://www.eclipse.org/ajdt
8
Nesse exemplo um conjunto de jun¸c˜ao ´e declarado em uma classe do programa (Ship) e usado, no corpo de um aspecto, para definir adendo.
thread, ou thread de despacho de eventos [Mic00]. Laddad, em [Lad03, Cap. 9], iden- tifica a garantia dessa propriedade em um programa como um requisito transversal e oferece uma solu¸c˜ao em AspectJ para esse problema.
O aspecto definido por Laddad garante que quaisquer chamadas a m´etodos da biblioteca Swing s˜ao realizadas na thread adequada. Como esse aspecto ´e de prop´osito geral, ou seja, aplic´avel em qualquer programa Java que utilize a biblioteca, aplicou-se essa solu¸c˜ao ao Rin’G. Como esse programa faz amplo uso de Swing, os dois adendos de contorno do aspecto de thread safety s˜ao aplicados em v´arios pontos do programa: h´a 500 hachuras dos adendos de thread safety espalhadas nas 83 classes do Ring’G. Aplica¸c˜ao da Uni˜ao de Adendos e Hachuras
Cada um dos programas do benchmark foi compilado com abc e ajc, e o c´odigo bytecode resultante de cada compila¸c˜ao foi passado para o programa de elimina¸c˜ao de r´eplicas de adendos e hachuras. Os tamanhos desses programas foram calculados pela soma dos tamanhos dos arquivos gerados durante a compila¸c˜ao. Tabela 4.2 apresenta as medi¸c˜oes obtidas.
Aplica¸c˜ao C´odigo Original (bytes) C´odigo Transformado (bytes) Redu¸c˜ao (%) Singleton abc 8115 7539 7.1 ajc 17403 16667 4.2 SpaceWar abc 150869 145391 3.9 ajc 222446 215995 2.9 Rin’G abc 947179 805162 15 ajc 1212273 1001661 17.4
Tabela 4.2: Tamanho do c´odigo gerado pelos compiladores ajc e abc e otimizado pelo algoritmo proposto
Analisando a natureza dos programas que figuram nessa medi¸c˜ao e das estrat´egias de compila¸c˜ao adotadas pelos compiladores ajc e abc pode-se entender melhor as di- feren¸cas entre os resultados da execu¸c˜ao da uni˜ao de implementa¸c˜oes de adendos e hachuras.
O compilador ajc ´e incremental, ou seja, permite que programas escritos em AspectJ sejam compilados em v´arias etapas independentes. Para que isso seja poss´ıvel, o ajc deve supor que o c´odigo que est´a compilando ´e incompleto e que mesmo m´etodos e atributos n˜ao usados n˜ao podem ser removidos do c´odigo gerado, pois tais estruturas podem ser usadas em itera¸c˜oes subseq¨uentes da compila¸c˜ao. Por esse motivo, c´odigo
gerado para aspectos pelo compilador ajc inclui implementa¸c˜oes de todos os adendos. Durante a costura de c´odigo, o corpo de um adendo ´e especializado em aplica¸c˜oes desse adendo pelo processo de expans˜ao descrito na Se¸c˜ao 2.2.1.1, que gera implementa¸c˜oes de adendos e hachuras nas classes em que aplica¸c˜oes ocorrem.
Uma avalia¸c˜ao anal´ıtica dos resultados obtidos pela aplica¸c˜ao do algoritmo de uni˜ao de implementa¸c˜oes de adendos e hachuras ´e apresentada na Se¸c˜ao 4.3.2, onde se definem as equa¸c˜oes para se determinar, a partir de um programa de entrada e do conjunto de aspectos a serem aplicados a ele, a redu¸c˜ao no tamanho do bytecode a ser obtida pela aplica¸c˜ao do algoritmo.