UMA ABORDAGEM PARA CRIAR REFATORAÇÕES PARA O KDM
4.3 Exemplo de uso da abordagem de criação das refato rações
4.3.1 Criar Refatoração Push Down Attribute
Nesta seção, a refatoração Push Down Attribute é criada seguindo os passos descritos neste capítulo. Essa refatoração é utilizada para remover a generalização de atributos, ou seja, um atributo é apenas utilizado em algumas subclasses, assim, não é interessante manter o atributo na superclasse, uma vez que cada subclasse pode definir um comportamento para o atributo (FOWLER, 1999).
4.3.1.1 Identificar Elementos Estruturais
O primeiro passo da abordagem consiste na identificação do elemento estrutural a ser refatorado. Pelo nome da refatoração é possível identificar que o elemento estrutural a ser refatorado é um atributo (do inglês - attribute). Dessa forma, utilizando o artefato de mapeamento entre KDM e POO (ver Tabela 3) é possível identificar que um atributo em KDM é representado
pela metaclasseStorableUnit.
4.3.1.2 Identificar Operações
No segundo passo da abordagem, o engenheiro de modernização deve identificar as ope- rações atômicas que compõem a refatoração a ser criada. Na Figura 27, duas instâncias simplifica- das do KDM são ilustradas, a parte superior ilustra a instância antes da realização da refatoração Push Down Attribute e a parte inferior representa o resultado da refatoração. Como observado, o primeiro passo da refatoração Push Down Attribute é selecionar um específicoStorableUnit (ver Figura 27 ). Em seguida, deve-se selecionar as subclasses que realmente utilizam esse StorableUnit para move-lo (ver Figura 27 À). Posteriormente, o {StorableUnitSelecionado} é movido para as sub-ClassUnitSelecionadas, como ilustrado na parte inferior da Figura 27 Õ. É visto que a instância daClassUnit em que havia o {StorableUnitSelecionado} não possui mais sua instância (ver Figura 27 Ã). Observando a Figura 27 é possível concluir que a refato- ração Push Down Attribute pode ser criada por meio da combinação das seguintes operações atômicas: (i)add e (ii) delete.
Figura 27 – Instância simplificada do KDM antes e depois da refatoração Push Down Attribute.
name = model : Package isAbstract = false name = ClassA : ClassUnit name = name Type = String : StorableUnit isAbstract = false name = ClassB : ClassUnit isAbstract = false name = ClassC : ClassUnit to = ClassA [ClassUnit] from = ClassB [ClassUnit]
: Extends
to = ClassA [ClassUnit] from = ClassC [ClassUnit]
: Extends name = model : Package isAbstract = false name = ClassA : ClassUnit isAbstract = false name = ClassB : ClassUnit isAbstract = false name = ClassC : ClassUnit to = ClassA [ClassUnit] from = ClassB [ClassUnit]
: Extends
to = ClassA [ClassUnit] from = ClassC [ClassUnit]
: Extends Antes Depois 1 2 2 name = name Type = String : StorableUnit name = name Type = String : StorableUnit 4 4 3
4.3.1.3 Implementar Operações
Após identificar as operações que compõem a refatoração a ser criada, o próximo passo consiste na implementação das operações. O terceiro passo da abordagem é apoiado por um conjunto de templates que auxilia o engenheiro de modernização a implementar as operações. As operações atômicas identificadas para implementar a refatoração Push Down Attribute foram implementadas em ATL utilizando os templates apresentados nos Códigos-fontes 4 e 6. A combinação desses templates resulta nos Códigos-fontes 20 e 21.
Código-fonte 20: ATL representando a operação atômica add.
1 r u l e c r e a t e S t o r a b l e U n i t {
2 from
3 s o u r c e : MM! C l a s s U n i t ( s o u r c e . name = “{sub-ClassUnitSelecionada}”
4 to
5 t a r g e t : MM! C l a s s U n i t (
6 codeElement s o u r c e . codeElement! i n c l u d i n g ( newElement )
7 ) ,
8 newElement : MM! S t o r a b l e U n i t (
9 name {StorableUnitSelecionado.name}
10 )
11 }
Código-fonte 21: ATL representando a operação atômica delete.
1 r u l e d e l e t e S t o r a b l e U n i t {
2 from
3 s o u r c e : MM! S t o r a b l e U n i t ( s o u r c e . name = {StorableUnitSelecionado.name} and s o u r c e . r e f I m m e d i a t e C o m p o s i t e ( ) . name = {ClassUnit.name} )
4 to
5 drop
6 }
4.3.1.4 Agrupar Operações
Após implementar as operações atômicas seguindo os templates apresentados neste capítulo, o próximo passo consiste em agrupar tais operações. Dessa forma, um template para guiar o agrupamento das operações atômicas também foi definido neste capítulo (ver Código- fonte 10). O agrupamento das operações atômicas apresentadas nos Códigos-fontes 20 e 21 resulta na refatoração apresentada no Código-fonte 22.
Código-fonte 22: ATL da refatoração Push Down Attribute.
2 c r e a t e OUT : MM r e f i n i n g IN : MM; 3 r u l e c r e a t e S t o r a b l e U n i t { 4 from 5 s o u r c e : MM! C l a s s U n i t ( s o u r c e . name = “{sub-ClassUnitSelecionada}” 6 to 7 t a r g e t : MM! C l a s s U n i t (
8 codeElement s o u r c e . codeElement! i n c l u d i n g ( newElement )
9 ) , 10 newElement : MM! S t o r a b l e U n i t ( 11 name {StorableUnitSelecionado.name} 12 ) 13 } 14 r u l e d e l e t e S t o r a b l e U n i t { 15 from
16 s o u r c e : MM! S t o r a b l e U n i t ( s o u r c e . name = {StorableUnitSelecionado.name} and s o u r c e . r e f I m m e d i a t e C o m p o s i t e ( ) . name = {ClassUnit.name} )
17 to
18 drop
19 }
4.3.1.5 Definir Restrições
Após identificar as operações que compõem a refatoração e implementar a refatoração utilizando os templates definidos na abordagem, o próximo passo consiste na definição de asserções (pré- e pós-condições) da refatoração. Para cada operação atômica identificada no segundo passo da abordagem, templates são disponibilizados para auxiliar o engenheiro de modernização a criar tais asserções. No Código-fonte 23, é apresentada a pré-condição criada para a refatoração Push Down Attribute, a qual foi criada usando uma combinação dos templates apresentados nos Códigos-fontes 11 e 14.
Código-fonte 23: Pré-condição da refatoração Push Down Attribute.
1 c o n t e x t S t o r a b l e U n i t : : preCond ( newName : S t r i n g )
2 pre : C l a s s U n i t . a l l I n s t a n c e s > s e l e c t ( e : C l a s s U n i t | a . name = “{sub- ClassUnitSelecionada}” and not S t o r a b l e U n i t . refImmediateComposite ( ) . codeElement! e x i s t ( e : S t o r a b l e U n i t | e . name = newName )
3 and C l a s s U n i t . a l l I n s t a n c e s > s e l e c t ( e : C l a s s U n i t | a . name =
{ClassUnit.name}) and S t o r a b l e U n i t . refImmediateComposite ( ) . codeElement ! e x i s t ( e : S t o r a b l e U n i t | e . name = newName )
Similarmente, no Código-fonte 24, é apresentada a pós-condição criada para a refatoração Push Down Attribute.
1 c o n t e x t S t o r a b l e U n i t : : preCond ( newName : S t r i n g )
2 post : C l a s s U n i t . a l l I n s t a n c e s > s e l e c t ( e : C l a s s U n i t | a . name = “{sub- ClassUnitSelecionada}” and S t o r a b l e U n i t . refImmediateComposite ( ) .
codeElement! e x i s t ( e : S t o r a b l e U n i t | e . name = newName ) 3 and C l a s s U n i t . a l l I n s t a n c e s > s e l e c t ( e : C l a s s U n i t | a . name =
{ClassUnit.name} ) and not S t o r a b l e U n i t . refImmediateComposite ( ) . codeElement! e x i s t ( e : S t o r a b l e U n i t | e . name = newName )
4.3.1.6 Documentar Refatoração
Para os exemplos apresentados neste capítulo, escolheu-se especificar as refatorações criadas seguindo o template apresentado na Seção 4.2.6.
1. Especificação Informal:
a) Nome: Push Down Attribute; b) Definição:
• StorableUnitSelecionado - um atributo que será movido para subclasses; • ClassUnit - uma classe na qual o {StorableUnitSelecionado} é definido; • sub-ClassUnitSelecionadas - subclasses de {ClassUnit}.
c) Objetivo: Mover um {StorableUnitSelecionado} para as {sub-ClassUnitSelecionadas}. d) Descrição (opcional): {StorableUnitSelecionado} é utilizada em apenas algumas
subclasses. e) Pré-condição:
• {StorableUnitSelecionado} não existe nas sub-ClassUnitSelecionadas; • {StorableUnitSelecionado} existe na ClassUnit.
f) Pós-condição:
• {StorableUnitSelecionado} existe nas sub-ClassUnitSelecionadas; • {StorableUnitSelecionado} não existe na ClassUnit.
g) Mecanismo: move um atributo de uma classe para todas suas subclasses; h) Algoritmo:
• para cada sub-ClassUnitSelecionadas que realmente usa o {StorableUnitSelecionado} - sub-ClassUnitSelecionadas.add({StorableUnitSelecionado})
• {ClassUnit}.delete({StorableUnitSelecionado}). 2. Especificação Formal:
a) Pré-condição: a pré-condição da refatoração Push Down Attribute é apresentada no Código-fonte 23;
b) Algoritmo: a ATL responsável por realizar a refatoração Push Down Attribute é apresentada no Código-fonte 22
c) Pós-condição: a pós-condição da refatoração Push Down Attribute é apresentada no Código-fonte 24;
4.3.2 Criar Refatoração Extract Class
A refatoração Extract Class deve ser utilizada quando uma determinada classe está fazendo o trabalho que deveria ser realizado por duas classes (FOWLER, 1999). Dessa forma, nesta seção, a refatoração Extract Class é criada seguindo todos os passos da abordagem.
4.3.2.1 Identificar Elementos Estruturais
A refatoração Extract Class basicamente consiste na criação de uma nova classe, e em sequência deve-se mover todos os atributos relevantes de uma classe para essa nova classe. Dessa forma, as construções da linguagem OO utilizadas na refatoração são: (i) classes e (ii) atributos. Utilizando o artefato apresentado na Tabela 3, é possível identificar que as metaclasses em KDM
que representam essas construções em OO sãoClassUnit e StorableUnit, respectivamente.
4.3.2.2 Identificar Operações
No segundo passo da abordagem deve-se identificar as operações atômicas que compõem a refatoração a ser criada. Na Figura 28, são apresentadas duas instâncias simplificada do KDM, uma representa a instância antes da refatoração e a outra representa a instância após a aplicação da refatoração.
Figura 28 – Instância simplificada do KDM antes e depois da refatoração Extract Class.
name = model : Package isAbstract = false name = ClassA : ClassUnit name = att1 Type = String : StorableUnit name = model : Package isAbstract = false name = ClassA : ClassUnit isAbstract = false name = ClassB : ClassUnit Antes Depois 1 name = att1 Type = String : StorableUnit name = att2 Type = String : StorableUnit 1 name = att2 Type = String : StorableUnit 2 3 3 name = att3 Type = String : StorableUnit name = att3 Type = String : StorableUnit
Fonte: Elaborada pelo autor.
O primeiro passo da refatoração Extract ClassUnit é selecionar um conjunto deStorableUnits que será adicionado em uma nova instância de metaclasseClassUnit, no exemplo ilustrado na Figura 28 , duas instâncias deStorableUnits são selecionadas, att1 e att2. Em seguida, uma instância da metaclasseClassUnit é criada e adicionada ao mesmo Package que a instân-
na Figura 28 Ã. Em seguida, todos {StorableUnitSelecionados} são adicionados nessa nova instância, como representado na Figura 28 À. Além disso, os {StorableUnitSelecionados} devem ser deletados da {ClassUnitSelecionada}. Observando a Figura 28 é possível identi- ficar que é a refatoração Extract Class pode ser criada por meio da combinação das seguintes operações atômicas: (i)add e (ii) delete.
4.3.2.3 Implementar Operações
No passo anterior identificou-se que as operações atômicasadd e delete quando combi- nadas podem compor e criar a refatoração Extract Class. Dessa forma, essas operações atômicas foram implementadas em ATL utilizando os templates apresentados nos Códigos-fontes 4 e 6. A combinação desses templates resultou nos Códigos-fontes 25, 26 e 27.
Código-fonte 25: ATL representando a operação atômica add ClassUnit da refatoração Extract ClassUnit.
1 r u l e c r e a t e C l a s s U n i t {
2 from
3 s o u r c e : MM! Package ( s o u r c e . name = “{Package}”)
4 to
5 t a r g e t : MM! Package (
6 codeElement s o u r c e . codeElement! i n c l u d i n g ( newElement )
7 ) ,
8 newElement : MM! C l a s s U n i t (
9 name “{newName}”
10 )
11 }
Código-fonte 26: ATL representando a operação atômica add StorableUnit da refatoração Extract ClassUnit. 1 r u l e c r e a t e S t o r a b l e U n i t { 2 from 3 s o u r c e : MM! C l a s s U n i t ( s o u r c e . name = “{newName}” ) 4 to 5 t a r g e t : MM! C l a s s U n i t (
6 codeElement s o u r c e . codeElement! i n c l u d i n g ( newElement )
7 ) ,
8 newElement : MM! S t o r a b l e U n i t (
9 name “storableUnitName”
10 )
Código-fonte 27: ATL representando a operação atômica delete StorableUnit da refatora- ção Extract ClassUnit.
1 r u l e d e l e t e S t o r a b l e U n i t {
2 from
3 s o u r c e : MM! S t o r a b l e U n i t ( s o u r c e . name = “{StorableUnit}Selecionado” and s o u r c e . r e f I m m e d i a t e C o m p o s i t e ( ) . name = “{ClassUnit}Selecionado” )
4 to
5 drop
6 }
4.3.2.4 Agrupar Operações
Após implementar as operações atômicas seguindo os templates apresentados neste capítulo, o próximo passo consiste em agrupar tais operações. Dessa forma, um template para guiar o agrupamento das operações atômicas também foi definido neste capítulo (ver Código- fonte 10). O agrupamento das operações atômicas apresentadas nos Códigos-fontes 25, 26 e 27 resulta na refatoração apresentada no Código-fonte 28.
Código-fonte 28: ATL da refatoração Extract ClassUnit.
1 module e x t r a c t C l a s s U n i t ;
2 c r e a t e OUT : MM r e f i n i n g IN : MM; 3 r u l e c r e a t e C l a s s U n i t {
4 from
5 s o u r c e : MM! Package ( s o u r c e . name = “{Package}” )
6 to
7 t a r g e t : MM! Package (
8 codeElement s o u r c e . codeElement! i n c l u d i n g ( newElement )
9 ) , 10 newElement : MM! C l a s s U n i t ( 11 name “{newName}” 12 ) 13 } 14 r u l e c r e a t e S t o r a b l e U n i t { 15 from 16 s o u r c e : MM! C l a s s U n i t ( s o u r c e . name = “{newName}” ) 17 to 18 t a r g e t : MM! C l a s s U n i t (
19 codeElement s o u r c e . codeElement! i n c l u d i n g ( newElement )
20 ) , 21 newElement : MM! S t o r a b l e U n i t ( 22 name “storableUnitName” 23 ) 24 } 25 r u l e d e l e t e S t o r a b l e U n i t {
26 from
27 s o u r c e : MM! S t o r a b l e U n i t ( s o u r c e . name = “{StorableUnit}Selecionado” and s o u r c e . r e f I m m e d i a t e C o m p o s i t e ( ) . name = “{ClassUnit}Selecionado” )
28 to
29 drop
30 }}
4.3.2.5 Definir Restrições
Após identificar as operações e implementar a refatoração, o próximo passo consiste na definição das pré- e pós-condições da refatoração. Os templates apresentados neste capítulo foram utilizados para criar as asserções da refatoração Extract Class. O Código-fonte 29 apresenta a pré-condição criada para a refatoração. Essa pré-condição foi criada utilizando os templates apresentados nos Códigos-fontes 11 e 14. Similarmente, o Código-fonte 30 apresenta a pós- condição criada para a refatoração Extract ClassUnit.
Código-fonte 29: Pré-condição da refatoração Extract Class.
1 c o n t e x t S t o r a b l e U n i t : : preCond ( newName : S t r i n g )
2 pre : C l a s s U n i t . a l l I n s t a n c e s > s e l e c t ( e : C l a s s U n i t | a . name = {ClassUnitSelecionada}) and S t o r a b l e U n i t . refImmediateComposite ( ) .
codeElement! e x i s t ( e : S t o r a b l e U n i t | e . name = {StorableUnitSelecionado} ) 3 and Package . a l l I n s t a n c e s > s e l e c t ( e : Package | a . name = “{Package}” and not
C l a s s U n i t . r e f I m m e d i a t e C o m p o s i t e ( ) . codeElement! e x i s t ( e : C l a s s U n i t | e . name = newName )
4 and C l a s s U n i t . a l l I n s t a n c e s > s e l e c t ( e : C l a s s U n i t | a . name = newName and not S t o r a b l e U n i t . r e f I m m ed i a t e C o mp o s i t e ( ) . codeElement! e x i s t ( e : S t o r a b l e U n i t | e . name = {StorableUnitSelecionado} . name )
Código-fonte 30: Pós-condição da refatoração Extract ClassUnit.
1 c o n t e x t S t o r a b l e U n i t : : preCond ( newName : S t r i n g )
2 post : C l a s s U n i t . a l l I n s t a n c e s > s e l e c t ( e : C l a s s U n i t | a . name = {ClassUnitSelecionada}) and not S t o r a b l e U n i t . refImmediateComposite ( ) .
codeElement! e x i s t ( e : S t o r a b l e U n i t | e . name = {StorableUnitSelecionado} . name )
3 and Package . a l l I n s t a n c e s > s e l e c t ( e : Package | a . name = “{Package}” and C l a s s U n i t . r e f I m m e d i a t e C o m p o s i t e ( ) . codeElement! e x i s t ( e : C l a s s U n i t |
e . name = newName )
4 and C l a s s U n i t . a l l I n s t a n c e s > s e l e c t ( e : C l a s s U n i t | a . name = newName and S t o r a b l e U n i t . r e f I m m e d i a t e C o m p o s i t e ( ) . codeElement! e x i s t ( e :
4.3.2.6 Documentar Refatoração
O último passo da abordagem é a especificação da refatoração criada. Esse passo é opcional e fica a critério do engenheiro de modernização realizar esse passo. Para a refatoração Extract ClassUnit escolheu-se especificar a refatoração seguindo o template apresentado na Seção 4.2.6.
1. Especificação Informal:
a) Nome: Extract ClassUnit; b) Definição:
• Package - uma instância da metaclasse Package para adicionar a nova ClassUnit; • ClassUnitSelecionada - a classe que contém os atributos e métodos que devem
ser movido para a nova classe;
• novoNome - um novo nome para a nova classe a ser criada;
• StorableUnitSelecionado - atributo selecionado para ser movido para a nova classe.
c) Objetivo: Criar uma novaClassUnit e mover o StorableUnitSelecionado para
essa nova instância.
d) Descrição (opcional):ClassUnitSelecionada está realizando o trabalho que deveria ser realizado por duas classes.
e) Pré-condição:
• {StorableUnitSelecionado} existe na {ClassUnitSelecionada}; • nova ClassUnit não existe no Package;
• {StorableUnitSelecionado} não existe na nova ClassUnit. f) Pós-condição:
• {StorableUnitSelecionado} não existe na {ClassUnitSelecionada}; • nova ClassUnit existe no Package;
• {StorableUnitSelecionado} existe na nova ClassUnit.
g) Mecanismo: Deve-se criar uma nova classe e mover os atributos selecionados; h) Algoritmo:
• addNewClassUnit({novoNome});
• adiciona essa nova instância dentro de um Package;
• para cada {StorableUnitSelecionado} - add({newClassUnit}, {StorableUnit- Selecionado});
• para cada {StorableUnitSelecionado} - delete({ClassUnitSelecionada}, {Storable- UnitSelecionado});
2. Especificação Formal:
a) Pré-condição: a pré-condição da refatoração Extract Class é apresentada no Código- fonte 29;
b) Algoritmo: a ATL responsável por realizar a refatoração Extract Class é apresentada no Código-fonte 28;
c) Pós-condição: a pós-condição da refatoração Extract Class é apresentada no Código- fonte 30;