UNIVERSIDADE ESTADUAL PAULISTA “Júlio de Mesquita Filho” Pós-Graduação em Ciência da Computação Ingrid Marçal Uma abordagem para o apoio à identificação de interesses transversais: diretrizes para a escolha de técnicas de identificação de interesses transversais UNESP 2017 Ingrid Marçal Uma abordagem para o apoio à identificação de interesses transversais: diretrizes para a escolha de técnicas de identificação de interesses transversais Orientador: Prof. Dr. Rogério Eduardo Garcia Dissertação apresentada ao Instituto de Biociências, Letras e Ciências Exatas (IBILCE – UNESP – São José do Rio Preto) como parte dos requisitos para a obtenção do título de mestre em Ciência da Computação. UNESP 2017 i Marçal, Ingrid. Uma abordagem para o apoio à identificação de interesses transversais: diretrizes para a escolha de técnicas de identificação de interesses transversais / Ingrid Marçal . -- São José do Rio Preto, 2017 77 f. : il., tabs. Orientador: Rogério Eduardo Garcia Dissertação (mestrado) – Universidade Estadual Paulista “Júlio de Mesquita Filho”, Instituto de Biociências, Letras e Ciências Exatas 1. Ciência da Computação. 2. Engenharia de Software. 3. Análise de sistemas. 4. Modularização. 5. Transversalidade. I. Universidade Estadual Paulista "Júlio de Mesquita Filho". Instituto de Biociências, Letras e Ciências Exatas. II. Título. CDU – 518.721 Ficha catalográfica elaborada pela Biblioteca do IBILCE UNESP - Câmpus de São José do Rio Preto Ingrid Marçal Uma abordagem para o apoio à identificação de interesses transversais: diretrizes para a escolha de técnicas de identificação de interesses transversais Dissertação apresentada ao Instituto de Biociências, Letras e Ciências Exatas (IBILCE – UNESP – São José do Rio Preto) como parte dos requisitos para a obtenção do título de mestre em Ciência da Computação. Comissão Examinadora Prof. Dr. Rogério Eduardo Garcia UNESP – Presidente Prudente Orientador Prof. Dr. Reginaldo Ré UTFPR – Campo Mourão Prof. Dr. Ives Pola UNESP – Presidente Prudente Presidente Prudente, 26 de Junho de 2017 ii Agradecimentos Faço minhas as palavras de Brendan Pietsch e culpo a todos vocês. Realizar todo o trabalho e escrever esta dissertação foi um exercício de sofrimento. Permito talvez a um leitor casual eximir-se da culpa de tal sofrimento, mas àqueles que tiveram papel importante no prolonga- mento da minha agonia com o apoio e encorajamento indispensáveis... bem, você sabe quem você é, e você me deve uma. Depois de tanto tempo trabalhando sobre o tema desta dissertação, não me é possível es- crever uma lista completa de todos aqueles que de algum modo me ajudaram. São muitos e alguns eu nem mesmo sei o nome, por exemplo aquele cara que postou um ”Não desista, Deus está contigo!” em letras garrafais sob um fundo marítimo. Por isso me perdoem os não citados, serão muitos. Por falar em Deus, obrigada meu Pai e meu amigo que nunca me permitiu permanecer no chão por muito tempo. Sem Ti nenhuma dessas letras teriam sentido. Prossigo por ordem cronológica de culpa. Obrigada mãe, pai e irmã, também conhecidos por Fátima, Lourival, e Fernanda. Vocês são minha base e meu modelo para tudo o que faço. E tudo o que faço é para tentar retribuir ao menos o mínimo do amor e apoio que sempre tive. Obrigada a todos os professores que tive e que contribuíram para a descoberta de tudo o que sei hoje. Em especial ao Ronaldo Celso Messias Corrêa, por me apoiar desde o primeiro momento na universidade. Obrigada Rogério Eduardo Garcia pelos ensinamentos tanto sobre nossa profissão quanto sobre a vida. Você se tornou minha referência de ética e docência, tenho imenso orgulho em ser sua orientanda. Obrigada por tudo que fez por mim durante os últimos vários anos de orientação. Tá pronto!, ou não. Obrigada Jaqueline Batista pela companhia durante a maior parte da jornada. Sozinha teria sido muito mais difícil enfrentar as diversas viagens e o microondas com microorganismos vivos e verdes que usávamos no hotel. Obrigada a todos os meus alunos que ao final de cada aula contribuíram para que eu tivesse certeza de que escolhi uma profissão que vou amar por muito tempo. iii I never saw a wild thing sorry for itself. A small bird will drop frozen dead from a bough without ever having felt sorry for itself. D. H. Lawrence Begin at the beginning, the King said gravely, “and go on till you come to the end: then stop.” Lewis Carroll, Alice in Wonderland iv Sumário Sumário . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vi Lista de Figuras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vii Lista de Tabelas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix Resumo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix Abstract . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . x 1 Introdução 1 1.1 Modularização de interesses . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.2 Identificação de Interesses transversais . . . . . . . . . . . . . . . . . . . . . . 5 1.3 Motivação e Justificativa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 1.4 Formulação do Problema e Objetivos . . . . . . . . . . . . . . . . . . . . . . . 7 1.5 Organização . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2 Interesses Transversais 9 2.1 Sintomas de Transversalidade . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.1.1 Discussão . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.2 Tipos de Interesses Transversais . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.3 Considerações Finais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 3 Técnicas para a identificação de interesses transversais 19 3.1 Análise Fan-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 3.2 Detecção de Clones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 3.2.1 Análise, Comparação, e Combinação de Técnicas . . . . . . . . . . . . 22 3.3 Critérios de Análise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 3.3.1 Análise e Comparação de Técnicas . . . . . . . . . . . . . . . . . . . 25 3.3.2 Combinação de Técnicas . . . . . . . . . . . . . . . . . . . . . . . . . 30 3.4 Considerações finais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 4 Metodologia 33 4.1 Conceitos da Teoria Fundamentada em Dados . . . . . . . . . . . . . . . . . . 33 v Sumário 4.1.1 Categorias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 4.1.2 Codificação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 4.1.3 Comparação Constante . . . . . . . . . . . . . . . . . . . . . . . . . . 34 4.1.4 Amostragem e Saturação Teórica . . . . . . . . . . . . . . . . . . . . 35 4.1.5 O Processo de Análise de Dados . . . . . . . . . . . . . . . . . . . . . 35 4.2 Aplicação da Teoria Fundamentada em Dados Neste Trabalho . . . . . . . . . 37 4.2.1 Amostragem Teórica . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 4.2.2 Codificação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 4.3 Considerações Finais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 5 Diretrizes para a Escolha de Técnicas de Identificação 44 5.1 Contextualização . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 5.2 Diretrizes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 5.2.1 [D1] - Defina o que deve ser identificado . . . . . . . . . . . . . . . . 45 5.2.2 [D2] - Estabeleça o tipo de dado a ser analisado . . . . . . . . . . . . 46 5.2.3 [D3] - Defina o tipo de análise . . . . . . . . . . . . . . . . . . . . . . 46 5.2.4 [D4] - Determine o tempo e o esforço disponíveis . . . . . . . . . . . . 47 5.2.5 [D5] - Relacione as definições de [D1], [D2], [D3], e [D4] . . . . . . 47 5.2.6 [D6] - Escolha a técnica e ferramenta a serem utilizadas . . . . . . . . 48 5.3 Discussão . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 5.3.1 Objetivo da identificação ([D1]) . . . . . . . . . . . . . . . . . . . . . 49 5.3.2 Tipo de dado: Estático, dinâmico, ou histórico ([D2]) . . . . . . . . . . 49 5.3.3 Tipo de análise: Estrutural, comportamental, sintática ou histórica ([D3]) 52 5.3.4 Tempo de análise e esforço manual ([D4]) . . . . . . . . . . . . . . . . 55 5.3.5 Como as diretrizes propostas se relacionam ([D5]) . . . . . . . . . . . 55 5.3.6 Técnica e ferramentas para a identificação de interesses transversais ([D6]) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 5.4 Aplicação das Diretrizes Propostas . . . . . . . . . . . . . . . . . . . . . . . . 58 5.4.1 Escolha do objeto de análise e construção do oráculo . . . . . . . . . . 58 5.4.2 Escolha da Técnica de Identificação . . . . . . . . . . . . . . . . . . . 58 5.4.3 Aplicação da Técnica Selecionada . . . . . . . . . . . . . . . . . . . . 62 5.5 Considerações finais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 6 Conclusão 68 6.1 Contribuições . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 6.2 Limitações . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 6.3 Trabalhos Futuros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 6.4 Produção Bibliográfica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 Referências Bibliográficas 77 vi Lista de Figuras 1.1 Processo de refatoração de interesses trasversais para aspectos. . . . . . . . . . 5 2.1 Relação entre interesses transversais, tipos, sintomas, e técnicas de identificação. 10 2.2 O padrão Observer no sistema HealthWatcher (Adaptado de Da Silva (2009)) . 13 2.3 Representação do sintoma Ovelha negra em diversos módulos de um sistema (Adaptado de (Da Silva, 2009)) . . . . . . . . . . . . . . . . . . . . . . . . . . 16 2.4 Representação do sintoma Polvo em diversos módulos de um sistema (Adaptado de (Da Silva, 2009)) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 2.5 Representação do sintoma Dominador em diversos módulos de um sistema (Adaptado de (Da Silva, 2009)) . . . . . . . . . . . . . . . . . . . . . . . . . . 17 3.1 Etapas do processo de identificação de interesses transversais (Adaptado de Delfim (2013)) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 3.2 Perspectiva específica do processo de identificação de interesses transversais - Análise Fan-in (Adaptado de Delfim (2013)). . . . . . . . . . . . . . . . . . . 21 3.3 Tripla Restrição para Técnicas de Identificação de Interesses Transversais. . . . 28 3.4 As pré-condições assumidas por técnicas de identificação podem afetar o nú- mero de sementes identificadas e o nível de esforço manual requerido. Indire- tamente também afetam a precisão. . . . . . . . . . . . . . . . . . . . . . . . . 30 5.1 Como tem influência direta sobre o recall, a granularidade de uma técnica tam- bém pode impactar no esforço manual e precisão. . . . . . . . . . . . . . . . . 48 5.2 Uso das diretrizes para a escolha de técnicas de identificação de interesses trans- versais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 5.3 Sementes identificadas pela Análise Fan-in . . . . . . . . . . . . . . . . . . . 65 5.4 Os interesses transversais do tipo Consistent Behavior são mais relevantes, pois mostram maior impacto em relação a problemas de alterações em cascata. . . . 66 5.5 As sementes do tipo Consistent Behavior são frequentemente alteradas . . . . . 67 vii Lista de Tabelas 3.1 Técnicas de identificação selecionadas na amostragem teórica. . . . . . . . . . 25 3.2 Tipo de dado de entrada por abordagem adotada pelas técnicas atuais para a identificação de interesses transversais. . . . . . . . . . . . . . . . . . . . . . . 26 3.3 Granularidade de resultados da aplicação de técnicas atuais para a identificação de interesses transversais. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 3.4 Tipo de análise executada nas abordagens adotadas pelas técnicas atuais para a identificação de interesses transversais. . . . . . . . . . . . . . . . . . . . . . . 27 3.5 Sintomas de transversalidade analisados nas abordagens adotadas pelas técnicas atuais para a identificação de interesses transversais. . . . . . . . . . . . . . . . 27 3.6 Esforço manual requerido nas abordagens adotadas pelas técnicas atuais para a identificação de interesses transversais. . . . . . . . . . . . . . . . . . . . . . . 28 4.1 Exemplo de codificação aberta utilizando o método de micro-análise - Adaptado de Allan (2003) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 4.2 Exemplo de codificação aberta utilizando o método de ponto-chave - Adaptado de Allan (2003) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 4.3 Escala utilizada para avaliação dos estudos selecionados . . . . . . . . . . . . 39 4.4 Questões de avaliação de qualidade dos estudos selecionados . . . . . . . . . . 39 4.5 Escala utilizada para avaliação dos estudos selecionados . . . . . . . . . . . . 40 4.6 Quantidade de estudos excluídos por cada filtro aplicado . . . . . . . . . . . . 41 4.7 Número de estudos incluídos na amostragem teórica após a filtragem de acordo com a classificação. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 4.8 Codificação aberta utilizando o método de ponto-chave . . . . . . . . . . . . . 42 4.9 Resultado da codificação axial . . . . . . . . . . . . . . . . . . . . . . . . . . 43 5.1 Definições para as diretrizes [D2], [D3], e [D4] . . . . . . . . . . . . . . . . . 59 5.2 Mapeamento das técnicas de identificação propostas na literatura em relação à suas características . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 5.3 Técnicas de identificação selecionadas na amostragem teórica. . . . . . . . . . 62 viii Resumo Promover a evolução de software sem provocar qualquer degradação em sua arquitetura e projeto é um desafio para a Engenharia de Software. A divisão de código em módulos é um dos mecanismos utilizados por metodologias convencionais para tentar minimizar o grau de acopla- mento entre elementos de software e facilitar a evolução. A modularização dos interesses que compõem o sistema melhora a compreensão de código e reduz a complexidade das atividades de manutenção. Apesar dos esforços para prover a modularização de interesses em sistemas de software, alguns não são facilmente encapsulados e têm sua implementação espalhada por diversos módulos. Isso gera dependências lógicas entre um grande número de elementos de software. Tais interesses são chamados de interesses transversais. Técnicas para a identificação de interesses transversais apresentam baixa precisão nos resultados obtidos, principalmente de- vido a não conformidade dos objetivos de identificação às características da técnica escolhida. Este trabalho propõe um conjunto de diretrizes para apoiar a escolha de técnicas de identifica- ção de interesses transversais. O conjunto de diretrizes colabora para a adequação das técnicas ao seu propósito e, por consequência, para a obtenção de resultados mais significantes. Palavras-chave: Identificação de interesses transversais, modularização, técnicas de iden- tificação ix Abstract Promoting software evolution without causing any degradation in its architecture and design is a challenge for software engineering. The implementation of code into modules is one of the mechanisms used by conventional programming methodologies to try to minimize the degree of coupling between elements of software and facilitate a development and evolution. The mo- dularization of concerns that make up the system improves the source code comprehension and reduces the complexity of maintenance activities. Despite efforts to provide the modularization of concerns in software systems, some are not easily encapsulated and have their implementa- tion spread across several modules. This generates logical dependencies between a large num- ber of software elements. Such concerns are called crosscutting concerns. Techniques for the identification of crosscutting concerns show low precision in the obtained results, mainly due to the nonconformity of the identification objectives to the characteristics of the chosen techni- que. This work proposes a set of guidelines to support the choice of techniques for identifying crosscutting concerns. The set of guidelines helps to adequate the techniques to their purpose and, consequently, to obtain meaningful results. Keywords: crosscutting concern identification, modularization, identification techniques x CAPÍTULO 1 Introdução Uma maneira de evidenciar o entendimento de um sistema de software é explicar o pro- grama, sua estrutura, seu comportamento e suas relações com o domínio da aplicação em termos diferentes daqueles utilizados durante a codificação. Por exemplo, para um ser humano a afir- mação (1) “o programa soma dois números” é diferente da afirmação (2) soma = numero1 + numero2; return soma; (Biggerstaff et al., 1993). A afirmação (1) é uma expressão informal que remete a conceitos do mundo real. A afir- mação (2) é uma expressão formal, restrita e que segue uma gramática predeterminada por uma linguagem de programação. Para que seja possível criar, manutenir, explicar, reutilizar e docu- mentar sistemas de software é necessário que esse possa ser representado em ambas as formas (Biggerstaff et al., 1993). Os conceitos do mundo real relacionados ao domínio de um sistema são chamados de inte- resses (IEEE, 2000). O desenvolvimento de software é a tradução de interesses em estruturas algorítmicas adequadas. Quando o relacionamento entre interesses é complexo, sua representa- ção em código é dificultada. Por isso, o código que implementa um software é decomposto em módulos menores, com interdependência mínima, e que representam um único interesse cada (Chang e Lu, 2009). A programação modular permite que um módulo seja desenvolvido sem ser preciso co- nhecer todo o código do sistema, além de facilitar a reutilização e reescrita de código sem a necessidade de revisar todo o sistema (Parnas, 1972). Para possibilitar a programação modular, vários paradigmas de programação foram desen- volvidos ao longo de mais de 40 anos de história da programação – imperativo, funcional, e orientação a objetos são exemplos. Cada paradigma de programação é baseado em abstrações algorítmicas específicas e representam maneiras diferentes de raciocinar sobre os interesses que compõem um sistema. Por exemplo, o paradigma imperativo permite a implementação de inte- 1 resses em sub-rotinas que são agrupadas em módulos com diferentes níveis de interdependência (acoplamento). O paradigma orientado a objeto permite a implementação de interesses em ob- jetos e classes de objetos que encapsulam dados e operações que descrevem o comportamento dos objetos. No entanto, há interesses que são difíceis de serem modularizados usando paradigmas de programação convencionais. Tais interesses são chamados de interesses transversais. A ati- vidade de identificação de interesses transversais é apresentada na Seção 1.1. Na Seção 1.2 é apresentada a relação entre os paradigmas de programação mais usados atualmente e interesses de difícil modularização, além de uma alternativa para melhorar o encapsulamento dos mesmos. Em seguida são estabelecidos a motivação, justificativa, problema abordado, e objetivos deste trabalho, respectivamente nas Seções 1.3 e 1.4. 1.1 Modularização de interesses Como já mencionado, um sistema de software é composto por diversos interesses e o re- lacionamento entre eles. No início do desenvolvimento, o sistema é decomposto em unidades modulares de modo que cada interesse é representado por um único módulo cuja implementação é minimamente dependente dos demais. O modo como os módulos de um sistema são organi- zados dá origem à estrutura de decomposição do mesmo, que uma vez estabelecida implica que todo novo interesse a ser implementado deve ser compatível à ela. Ao longo das ativida- des de manutenção, interesses já implementados são modificados, ou pode ocorrer a adição de novos interesses cuja implementação deixa de ser compatível com a estrutura modular origi- nal. Quando há a incompatibilidade entre o código que implementa um interesse e a estrutura modular do sistema, o interesse é chamado de transversal (Nguyen et al., 2011). Para exemplificar a ocorrência de interesses transversais em um sistema de software, no Có- digo 1.1 são mostradas duas operações comuns em sistemas bancários, depósito e saque. As operações desbloquear() e bloquear() são usadas para permitir a ocorrência de transa- ções concorrentes sem afetar a integridade do banco de dados da agência bancária. Chamadas a desbloquear() e bloquear() são adicionadas a todas as operações que alteram os dados de uma conta. Como os métodos desbloquear() e bloquear() entrecortam a implementação das funcionalidades básicas depósito e saque eles são chamados de interesses transversais. Código 1.1: As operações de bloqueio e desbloqueio são interesses transversais public class ContaBancaria{ Database db = new Database(); public void deposito(double valor){ db.bloquear(); db.executar(valor); db.desbloquear(); } 2 1.1 Modularização de interesses public void saque (double valor){ db.bloquear(); db.executar(valor); db.desbloquear(); } public static void main(String... args){ ConBancaria depositar = new ContaBancaria(); depositar.deposito(30.0);} } O paradigma de programação orientado a objetos (OO) permite a utilização de classes, obje- tos, e métodos como estruturas algorítmicas para encapsular e abstrair interesses em diferentes níveis de granularidade (Harbulot, 2006). Assim, é possível, por exemplo, implementar o ge- renciamento de contas (depósito e saque) e o controle de concorrência (desbloquear() e bloquear()) em classes diferentes cujo relacionamento se dá por meio do envio de men- sagens entre objetos dessas classes. No exemplo representado pelo Código 1.11 é mostrado que interesses transversais têm rela- cionamentos complexos com outros interesses no sistema de tal modo que é difícil implementá-los como um único objeto ou método. Observa-se que não é possível implementar o interesse controle de concorrência em uma única classe e ao mesmo tempo impedir o espalhamento de chamadas aos métodos desbloquear() e bloquear() por todas as classes que realizam alterações em contas bancárias, como a classe ContaBancaria. Diversos estudos (Eaddy et al., 2008, Filho et al., 2006, Garcia et al., 2005, Greenwood et al., 2007) demonstram em- piricamente que a existência de interesses transversais degrada a qualidade de código e tem impacto negativo sobre métricas de qualidade interna (Khoshgoftaar et al., 1999), por exemplo acoplamento e número de linhas de código, e qualidade externa (Emam, 2000), por exemplo manutenibilidade e número de defeitos observáveis. Para diminuir o impacto negativo da presença de interesses transversais em sistemas de soft- ware, é possível usar a orientação a aspectos que permite implementar interesses transversais em unidades modulares chamadas aspectos. Os aspectos encapsulam o comportamento de um interesse transversal e o adiciona ao comportamento de outros interesses em tempo de com- pilação, e assim elimina o espalhamento e emaranhamento de código (Laddad, 2003). Desse modo, o desenvolvimento de software orientado a aspectos provê melhor separação de interes- ses, o que por sua vez aumenta as oportunidades de reúso de código e a coesão entre módulos (Kiczales e Hilsdale, 2001). Programar orientado a aspectos não é uma tarefa trivial, principalmente para refatorar um software já existente. Antes de refatorar interesses transversais em aspectos, é preciso identificá-los por meio dos sintomas que apresentam. A refatoração para aspectos do exemplo mostrado no 1É importante notar que o exemplo dado é meramente ilustrativo. Atualmente os Sistemas Gerenciadores de Banco de Dados possuem mecanismos automáticos para o controle do grau de isolamento de transações que preservam a integridade dos dados. De modo que é desnecessária a implementação de métodos para bloqueio e desbloqueio em um contexto real. 3 1.1 Modularização de interesses Código 1.1 é mostrada no Código 1.2 e o processo geral para a identificação e posterior refato- ração de interesses transversais para aspectos é ilustrado na Figura 1.1. Código 1.2: Refatoração para aspectos do exemplo mostrado no Código 1.1 public class ContaBancaria{ Database db = new Database() public void deposito(double valor){ db.executar(valor); } public void saque (double valor){ db.executar(valor); } public static void main(String... args){ ConBancaria depositar = new ContaBancaria(); depositar.deposito(30.0); } } public aspect AspectoContaBancaria{ pointcut bloquear() : call(* Database.executar()); pointcut desbloquear() : call(* Database.executar()); before() : bloquear(){ System.out.println("Bloqueou"); } after() : desbloquear(){ System.out.println("Desbloqueou"); } } Observa-se na Figura 1.1 que os interesses transversais #1, #2, e #3 têm sua implementação espalhada pelos módulos M1, M2, e M3 de um sistema orientado a objetos. A identificação de interesses transversais é feita por meio da aplicação de técnicas de identificação que indicam os fragmentos de código (métodos, linhas de código, ou classes) que os implementam. Uma vez identificados, é possível usar os mecanismos oferecidos pela orientação a aspectos para modularizar os interesses transversais: pontos de junção (momento bem definido da execução de um programa), ponto de corte (agrupa um conjunto de pontos de junção), advice (fragmento de código que é executado em cada ponto junção em um ponto de corte). Mais detalhes sobre os mecanismos de programação oferecidos pela orientação a aspectos fogem ao escopo deste trabalho, mas podem ser encontrados em Laddad (2003). A orientação a aspectos permite implementar interesses transversais em um único módulo (aspecto) e separá-los dos demais (M1, M2, M3, e M4). É importante enfatizar que para refatorar interesses transversais é necessário identificar todos os fragmentos de código que os compõem. Por isso, que principalmente para objetivos de refatoração, a precisão da técnica de identificação é de extrema importância. Se a técnica não for capaz de identificar todos os fragmentos de 4 1.1 Modularização de interesses Módulos de um sistema orientado a objetos Identificação de interesses transversais M1 M2 M3 M4 Interesses transversais identificados #1 #2 #3 #4 Refatoração para aspectos M1 M2 M3 M4 #1 #2 #3 #4 Sistema refatorado para aspectos M1 M2 M3 M4 Figura 1.1: Processo de refatoração de interesses trasversais para aspectos. código que correspondem a um interesse transversal, a refatoração do mesmo é mais difícil. 1.2 Identificação de Interesses transversais Por mais de uma década pesquisadores têm desenvolvido técnicas e ferramentas para a iden- tificação de interesses transversais em sistemas que não foram desenvolvidos usando a orien- tação a aspectos (Breu e Krinke, 2004, Marin et al., 2004, Bruntink et al., 2005, Moldovan e Serban, 2006, Zhang e Jacobsen, 2007, Zhang et al., 2008, Cojocar, 2012). Como enfatizado na Seção 1.1 e observado na literatura (Marin et al., 2004), o principal objetivo da identificação de interesses transversais é refatorá-los para aspectos de modo a obter um sistema potencial- mente mais fácil de ser compreendido e manutenido (Cojocar, 2012). No entanto, nem todo interesse transversal pode/deve ser refatorado para aspecto. Há interesses transversais que po- dem ser eliminados por meio de mecanismos de refatoração orientados a objeto, e há aqueles que não impactam negativamente na qualidade de software, se bem documentados (Mulder, 2009). Além disso, os problemas relacionados a interesses transversais podem existir mesmo em sistemas desenvolvidos usando a orientação a aspectos desde o início. Por exemplo, considerando a implementação do gerenciamento de contas bancárias refato- rado para aspectos mostrada no Código 1.2. A implementação de uma operação para a trans- ferência de valores entre contas também requer os mecanismos de bloqueio e desbloqueio para o controle de concorrência. Se os desenvolvedores da nova funcionalidade não souberem sobre a existência do aspecto já existente ou sua relação com a nova função, pode ocorrer a imple- mentação de rotinas redundantes ou a omissão de rotinas importantes, o que pode levar a erros de consistência durante a execução do sistema (Nguyen et al., 2011). Logo, observa-se que a identificação de interesses transversais também pode auxiliar na manutenção, evolução e na 5 1.2 Identificação de Interesses transversais compreensão de programas, pois se identificados é possível analisar e entender os interesses transversais de modo isolado sem a necessidade de analisar código de outros interesses (Roy et al., 2007). As técnicas atuais procuram por sintomas de espalhamento e/ou emaranhamento para iden- tificar interesses transversais. Espalhamento significa que o código que implementa o interesse transversal está espalhado por diversos módulos, e o emaranhamento significa que mais de um interesse é implementado no mesmo módulo sem muita clareza sobre quais fragmentos de código implementam cada interesse (Cojocar, 2012). Os sintomas que caracterizam o espalha- mento e emaranhamento se manifestam em código de modos diferentes, por exemplo múltiplas chamadas ao mesmo método a partir de diferentes módulos. Várias técnicas de identificação têm sido propostas (Breu e Krinke, 2004, Marin et al., 2004, Bruntink et al., 2005, Moldovan e Serban, 2006, Zhang e Jacobsen, 2007, Zhang et al., 2008), e cada uma adota uma abordagem diferente com base em determinadas características de trans- versalidade. Mesmo com o uso de técnicas (semi)automatizadas, a identificação de interesses transversais em código é uma tarefa difícil, suscetível a erros e que toma tempo devido à com- plexidade, tamanho e falta de documentação dos sistemas de software atuais. As técnicas atuais para a identificação de interesses transversais requerem o envolvimento humano para serem aplicadas (Detalhes no Capítulo 3). Mais comumente, o esforço manual exigido está relacionado à análise das sementes resultantes da aplicação da técnica. Isso porque o processo de identificação produz elementos de código, chamados de sementes, que podem ou não fazer parte da implementação de um interesse transversal. Por exemplo, bloquear e desbloquear no exemplo anterior fazem parte da implementação do interesse transversal controle de concorrência, logo, são sementes do mesmo interesse transversal. A análise manual de sementes é necessária para classificá-las ou não como parte da im- plementação de um interesse transversal. Assim, observa-se que sementes identificadas são candidatas a interesse transversal que devem ser submetidas à confirmação por um avaliador humano. Se não confirmadas, as sementes são chamadas de falso-positivos. Há casos em que uma técnica não identifica determinada semente já conhecida, nesse caso a semente não identi- ficada é chamada de falso-negativo. É importante notar que um dos motivos para a existência de falso-negativos pode ser a configuração incorreta da técnica e não sua incapacidade para identificar determinado interesse transversal. Sob o contexto descrito, uma técnica ideal não identifica falso-positivos e extingue falso-ne- gativos. Alcançar tal cenário é o maior desafio das técnicas de identificação atuais, visto que a maioria não apresenta números expressivos em precisão. 1.3 Motivação e Justificativa As técnicas atuais para a identificação de interesses transversais são imprecisas (Mens et al., 2008). A precisão de uma técnica é a razão entre a quantidade de sementes identificadas e a quantidade de sementes identificadas que fazem parte da implementação de um interesse 6 1.3 Motivação e Justificativa transversal. Baixa precisão significa que uma quantidade muito pequena do total de sementes identificadas estão de fato relacionadas a algum interesse transversal. A qualidade do resul- tado de uma técnica ajuda a aliviar o esforço manual requerido para separar falso-positivos e sementes que implementam algum interesse transversal (Zhang et al., 2008). Nesse contexto, este trabalho é motivado pela busca por melhores resultados no processo de identificação de interesses transversais. Esse processo é prejudicado, principalmente pela inconsistência entre as características dos interesses transversais que se deseja identificar e as características de transversalidade que a técnica de identificação escolhida é capaz de analisar. Prover tal consistência permite que os resultados obtidos sejam validados de modo justo, ou seja, de acordo com aquilo que a técnica é capaz de identificar. Como consequência, a precisão também melhora. Um primeiro passo em direção ao melhor entendimento da relação técnica-interesse trans- versal foi dado por Marin et al. (2005) ao propor uma classificação comum para interesses transversais de acordo com suas características. Tal classificação é apresentada na Seção 4.5. Porém, também é preciso compreender as características das técnicas de identificação para que se possa relacionar uma técnica à identificação de determinado sintoma de transversalidade. Compreender as características de uma técnica significa analisar quais sintomas ela consegue ou não identificar e por qual motivo. 1.4 Formulação do Problema e Objetivos A maior parte dos problemas relacionados às técnicas de identificação atuais são devidos à dificuldade em relacionar as capacidades de identificação da técnica ao conjunto de sinto- mas que caracterizam um interesse como transversal. As técnicas de identificação atuais são baseadas em suposições sobre o modo como interesses transversais são implementados. Por isso, elas se tornam especialistas na identificação de determinadas características de transver- salidade, por exemplo padrões de sintaxe ou de execução. No entanto, interesses transversais podem apresentar diferentes conjuntos de características de transversalidade, o que torna impra- ticável identificar todos os interesses transversais em um sistema utilizando apenas uma técnica (Nguyen et al., 2011). Além disso, podem ocorrer problemas como a incompatibilidade entre técnica e sistema analisado (Roy et al., 2007); Assim, este trabalho tem por objetivo oferecer suporte à escolha da técnica de identificação a ser utilizada por meio da elaboração de um conjunto de diretrizes capazes de auxiliar na escolha da técnica ou do conjunto de técnicas mais apropriadas para que seja mantida a consistência entre as características dos interesses transversais que se deseja identificar e as características que a técnica é capaz de identificar. Adicionalmente, é proposto um catálogo de sementes que implementam interesses trans- versais e que foram confirmadas e documentados na literatura. O catálogo auxilia na avaliação da proposta deste trabalho por permitir a comparação e validação de técnicas de identificação escolhidas com o apoio do conjunto de diretrizes elaboradas. 7 1.4 Formulação do Problema e Objetivos Dentre as contribuições deste trabalho, destaca-se também, a análise documentada do com- portamento de interesses transversais e sementes que compõem o catálogo, além da análise detalhada das capacidades e limitações de técnicas atuais para a identificação de interesses transversais. Considera-se que tais contribuições são importantes para a melhoria das técnicas existentes e para a criação de novas técnicas. 1.5 Organização Para discorrer sobre o tema e objetivos deste trabalho, o texto está organizado da seguinte maneira: os conceitos relacionados a interesses transversais, características de transversalidade, e a classificação de interesses transversais são discutidos no Capítulo 2. No Capítulo 3 são apresentadas as principais abordagens utilizadas pelas técnicas de identificação de interesses transversais atuais. Também é feita uma análise das técnicas para identificar os fatores que têm maior impacto no processo de identificação. A metodologia utilizada para a realização da proposta deste trabalho é descrita no Capítulo 4 enquanto que no Capítulo 5 as diretrizes propostas neste trabalho são apresentadas e discutidas. As diretrizes são aplicadas a um sistema de software real e é feita uma discussão sobre as vantagens de seu uso. Por fim, no Capítulo 6 são demonstradas as ameaças ao trabalho proposto e delineadas as conclusões obtidas. Também são elencados os trabalhos futuros e as publicações fruto do trabalho apresentado. 8 CAPÍTULO 2 Interesses Transversais Interesses transversais têm sido classificados, explorados e definidos na literatura por meio de estudos empíricos e teóricos (Marin et al., 2005, Ducasse et al., 2006, Marin et al., 2006, 2007, Figueiredo et al., 2009, da Silva et al., 2009). Compreendê-los é um fator crucial para criar técnicas que os identifiquem, melhorar as técnicas já existentes, e para estabelecer critérios de escolha da técnica a ser utilizada. Para discutir sobre interesses transversais, os sintomas que apresentam e suas classificações, é necessário entender a relação existente entre os conceitos: características de transversalidade, sintomas de transversalidade, interesses transversais, tipos de interesse transversal, sementes e técnicas de identificação. Interesses transversais podem ser classificados por tipos que descrevem o conjunto de sin- tomas que exibem. As técnicas de identificação localizam interesses transversais buscando por tais sintomas, que também podem ser chamados de características de transversalidade ou sin- tomas de transversalidade. Sendo assim, ao longo dos próximos capítulos, os termos sintoma, característica de transversalidade e sintoma de transversalidade são usados como sinônimos. Na Figura 2.1 é ilustrado o relacionamento entre interesses transversais, tipos, sintomas, e técnicas. À esquerda, é representado um arquivo de código fonte de um sistema qualquer. Nesse arquivo, alguns fragmentos do código fonte exibem sintomas de transversalidade (representados pelos padrões em linhas verticais e horizontais), logo são trechos do código fonte que imple- mentam interesses transversais, também conhecidos por sementes. Os sintomas representados na Figura 2.1 são relacionados a interesses transversais classificados como Tipo 1 e Tipo 2, à direita. Ao meio, tem-se uma Técnica A que é capaz de identificar apenas os sintomas represen- tados pelas linhas horizontais. Como a Técnica A é capaz de identificar os sintomas descritos pelo Tipo 1, pode-se dizer que ela é capaz de identificar interesses transversais daquele tipo. Além disso, observa-se que a Técnica A não é capaz de identificar interesses transversais do 9 Tipo 2, pois não identifica nenhum sintoma relacionado ao Tipo 2 (linhas verticais). Há três observações importantes que devem ser consideradas sobre o exemplo da Figura 2.1: (1) vários sintomas diferentes podem coexistir em um sistema; (2) consequentemente, um sis- tema pode conter sementes de interesses transversais classificados como de tipos distintos; (3) e uma técnica de identificação pode não identificar todo sintoma exibido em um sistema, sendo assim ela não é capaz de identificar todos os tipos de interesses transversais que o mesmo im- plementa. Tipo 1 Tipo 2X Técnica A Módulo do sistema Semente Figura 2.1: Relação entre interesses transversais, tipos, sintomas, e técnicas de identificação. Embora não seja objetivo do presente trabalho sumarizar os diversos modos como interesses transversais se manifestam em sistemas de software, optou-se por explorar com algum detalhe a explicação de sintomas, interesses transversais e classificações, pois é importante para a for- mulação das diretrizes propostas nesta dissertação. Inicialmente os sintomas são discutidos e relacionados a dependências entre artefatos de software na Seção 2.1. Em seguida, na Seção 2.2, são apresentadas as classificações de interesses transversais por tipo propostas na literatura. A Seção 2.3 conclui o capítulo. 2.1 Sintomas de Transversalidade O relacionamento entre os interesses implementados em um sistema gera dependências. Quando um interesse é transversal sua relação de dependência com outros interesses é com- plexa, e causa problemas de modularização, entendimento, e manutenção. Sintomas de trans- versalidade refletem relações de dependência problemáticas entre interesses transversais e ou- tros interesses. Há dois tipos de relações de dependência: sintática e lógica. Dependências sintáticas são estabelecidas pela relação entre elementos específicos do código fonte, como instruções, fun- ções/métodos, e classes. Além disso, podem ser referentes a dados ou a relações funcionais, por exemplo, um método A faz chamada a um método B. A dependência lógica (ou acoplamento lógico), por sua vez, é um tipo de dependência implícita e difícil de ser identificada diretamente no código fonte, mas que pode ser observada por meio da análise do relacionamento entre ar- tefatos, por exemplo classes que são frequentemente alteradas juntas tendem a ser logicamente acopladas. 10 2.1 Sintomas de Transversalidade A seguir é feita uma discussão sobre sintomas de transversalidade sob a perspectiva das dependências sintática (ou estrutural) e lógica discutidas anteriormente. 2.1.1 Discussão Fowler et al. (1999) propuseram um catálogo composto por 22 anomalias estruturais de có- digo que prejudicam sua manutenção e compreensão, as considerando, portanto, oportunidades de refatoração. Além disso, os autores elaboraram um guia para a refatoração de tais anomalias utilizando o paradigma orientado a objetos. No entanto, observa-se que alguns dos problemas estruturais documentados no catálogo proposto não são facilmente resolvidos utilizando meca- nismos orientados a objetos. Por exemplo: • Código duplicado: o mesmo código aparece em mais de um lugar no projeto. Por exemplo, a mesma expressão é implementada em dois métodos de uma mesma classe, em duas classes na mesma estrutura de herança, ou em duas classes não relacionadas. Código duplicado pode não corresponder a fragmentos de código idênticos, mas similares, ou diferentes mas que executam a mesma funcionalidade. • Alterações divergentes: caracterizado quando uma classe frequentemente sofre dife- rentes tipos de alterações por diferentes motivos. Por exemplo, um conjunto de n métodos de uma mesma classe são constantemente alterados por motivos distintos. • Cirurgia de rifle: é o oposto de Alterações divergentes, sempre que uma alteração é feita em código, é necessário fazer várias pequenas alterações em classes diferentes para que a estrutura do código seja adaptada à mudança. A duplicação e a alteração frequente de código em decorrência de atividades de manutenção ou adição de novas funcionalidades são sintomas de transversalidade conhecidos na literatura e não são facilmente refatoráveis, pois não há mecanismos específicos que deem suporte à modu- larização total de código transversal (Massicotte et al., 2007). Obviamente, tem-se a orientação a aspectos que ajuda a minimizar os problemas causados por interesses transversais, porém com limitações como discutido na Seção 1.2. Sendo assim, é possível afirmar que a identificação de anomalias estruturais pode levar à identificação de interesses transversais. Bernardi e Di Lucca (2009) concordam que proprieda- des estruturais podem ser exploradas na busca por sintomas de transversalidade, porém é um erro buscar por interesses transversais analisando as propriedades estruturais de um único inte- resse. Isso porque, segundo Bernardi e Di Lucca (2009), a transversalidade só passa a existir quanto é estabelecida uma relação de dependência entre dois interesses, um entrecorta o outro (van den Berg et al., 2006). Logo, a análise dos relacionamentos de dependência entre interesses é uma estratégia mais eficiente para a busca por sintomas de transversalidade. Da Silva (2009) confirmam empiricamente a hipótese de Bernardi e Di Lucca (2009) uti- lizando a estratégia de identificação proposta por Marinescu (2004) para demonstrar que a ex- ploração de sintomas puramente estruturais para identificar interesses transversais é limitante. 11 2.1 Sintomas de Transversalidade Os experimentos executados por Marinescu (2004) são baseados em métricas de modulariza- ção para medir a qualidade estrutural de um sistema de software. Por exemplo, para detectar o sintoma Cirurgia de Rifle, Marinescu (2004) define-se a seguinte regra: Shotgun-Surgery := (CM.topValues(20%) and (CC, HigherThan(5))) CC (Changing Classes) e CM (Changing Method) medem o acoplamento e representam, respectivamente, o número de métodos distintos que fazem chamada a outro método e o número de classes que fazem chamadas a determinado método. Os valores topValues e HigherThen determinam o limite para as métricas CC e CM. Assim, para que a regra definida indique o sintoma Cirurgia de Rifle em determinado método, é necessário que seu valor de CM seja entre os 20% maiores valores para todos os métodos do sistema, e ao menos 5 classes devem fazer chamadas a ele. Da Silva (2009) aplicaram a estratégia de Marinescu (2004) ao sistema web Health Wat- cher. Na Figura 2.2 os componentes em cinza implementam o padrão Observer de tal sistema (Gamma et al., 1995). A aplicação da regra apresentada anteriormente nessa instância de Ob- server resulta em CC = 0 para a interface Subject. Isso indica que nenhuma classe acessa Subject diretamente, logo não é identificada nenhuma anomalia estrutural que se relacione a ela. Entretanto, alterações na interface Subject podem ocasionar modificações nas classes que a implementa. Por exemplo, renomear o método removeObserver ocasiona alterações nas classes Complaint, Employee, e HealthUnit (Da Silva, 2009). A análise do exemplo anterior mostra que os elementos do padrão Observer, que é um inte- resse transversal (Da Silva, 2009, Marin et al., 2004), não são identificados. Isso acontece pois a abordagem de identificação executada é incapaz de descrever um problema de transversali- dade cujo sintoma só é percebido se for analisada a dependência lógica entre os módulos que implementam interesses distintos (Relacionamento entre Subject e as classes HealthUnit, Com- plaint, e Employee). Também é possível observar a importância em manter a consistência entre os sintomas de transversalidade e a abordagem adotada para identificar interesses transversais. A estratégia de detecção de Marinescu (2004) não é errada, e é eficiente na identificação de padrões estruturais em código (dependências sintáticas), porém é incapaz de detectar interesses transversais relacionados ao padrão Observer, que dependem do contexto ao qual pertencem para serem identificados. Na Figura 2.2 a relação de dependência lógica implícita entre as classes HealthUnit, Com- plaint, Employee e Subject poderia ser identificada por outras abordagens, por exemplo a análise de alterações feitas em conjunto. É importante observar que os sintomas de transversalidade gerados por problemas relacio- nados a dependências sintáticas e lógicas variam, por exemplo duplicação de código, alterações em cascata, padrões de chamadas a métodos, entre outros. Assim, interesses transversais podem exibir diversos sintomas diferentes. Para facilitar o entendimento e identificação de interesses transversais, a literatura mostra tentativas em classifica-los de acordo com o conjunto de sinto- 12 2.1 Sintomas de Transversalidade HealthUnit addObserver() removeObserver() notifyObservers() <> Observer update() ... subscribers ... search() insert() remove() ... <> Subject addObserver() removeObserver() notifyObservers() ... search() insert() remove() HealthWatcherFacade update() Employee addObserver() removeObserver() notifyObservers() ... subscribers ... Complaint addObserver() removeObserver() notifyObservers() ... subscribers ... <> RMIFacade Figura 2.2: O padrão Observer no sistema HealthWatcher (Adaptado de Da Silva (2009)) mas que exibem. A seguir são apresentadas as classificações de interesses transversais por tipo propostas na literatura. 2.2 Tipos de Interesses Transversais Marin et al. (2005) propõem a classificação de interesses transversais em tipos que os des- creve e classifica com base em três características: (1) objetivo do interesse; (2) idioma de implementação; e (3) mecanismo de linguagem orientado a aspectos que dá suporte à modula- rização de cada instância do interesse. Os tipos propostos por Marin et al. (2005) são sempre associados à menor unidade que pode ser usada para expressar individualmente e modularizar um interesse transversal. Ou seja, o mecanismo de linguagem orientado a aspectos capaz de modularizar cada semente de um interesse transversal. Consequentemente, a implementação de um interesse transversal pode ser expressa como uma combinação de uma ou mais sementes de um tipo. Marin et al. (2005) definem um novo tipo sempre que: (1) não é possível compor o novo tipo utilizando aqueles já definidos, e (2) o novo tipo não pode ser decomposto em unidades menores. Os autores ressaltam que nem todos os tipos precisam necessariamente ser associados a um mecanismo de linguagem orientado a aspectos, eles podem ser referentes a mecanismos desejados os quais poderiam ajudar na evolução de linguagens de programação. A classificação proposta por Marin et al. (2005) dá um nome para cada tipo para prover uma denominação comum a todas as sementes do interesse transversal correspondente. Além do nome, é descrito o objetivo do tipo em termos de comportamento, estrutura, e/ou requisitos exigidos pela implementação. O idioma de implementação descreve como, geralmente, é a implementação dos interesses transversais que correspondem ao tipo. Finalmente, cada tipo 13 2.2 Tipos de Interesses Transversais é associado a um mecanismo de linguagem orientada a aspectos que pode ser utilizado para refatorar suas instâncias. Os treze diferentes tipos de interesses transversais definidos por Marin et al. (2005) são descritos a seguir. Comportamento consistente (Consistent Behavior) são interesses transversais que imple- mentam determinado comportamento de maneira consistente na execução de métodos. Tal comportamento pode ser capturado por um ponto de corte durante uma possível refatoração para aspectos. Esse tipo é caracterizado por chamadas a métodos que implementam uma funci- onalidade desejada. Notificações a listeners é um exemplo de interesse transversal desse tipo. Imposição de contrato (Contract Enforcement) corresponde a interesses transversais que implementam regras de contrato, por exemplo pré e pós validação de condicionais. Esse tipo é caracterizado por chamadas a métodos que implementam a verificação de condições no sistema. Assim como o tipo anterior, interesses transversais do tipo imposição de contrato podem ser capturados por um ponto de corte durante a refatoração para aspectos. É possível observar que os tipos Imposição de Contrato e Comportamento Consistente têm características em comum, no entanto eles têm objetivos diferentes de acordo com a definição de Marin et al. (2005): interesses transversais do tipo Imposição de Contrato garantem determinadas condições devido a relações entre um método e seus chamadores. Papéis entrelaçados (Entangled Roles) são interesses transversais que estendem determi- nado método de modo que ele passa a exercer um segundo papel ou responsabilidade cuja implementação é emaranhada a seu papel principal. O idioma de implementação que descreve esse tipo é a implementação de um método com funcionalidades referentes a um interesse que não o principal tratado pelo método. Esse tipo de interesse transversal é capturado por pontos de corte e advices do tipo around durante a refatoração para aspectos. De acordo com Marin et al. (2005) esse tipo são especificamente relacionados a sobreposição de papéis a nível de mé- todos. Por exemplo, na estrutura do Java Swing, é comum classes assumirem ambos os papéis view e controller: um item de menu em uma interface é habilitado/desabilitado se o comando a ser executado ao selecionar o item o habilita ou desabilita. Apesar de o método responsável por habilitar/desabilitar o item de menu ser parte da interface view, sua execução é baseada em decisões do controller. Camada de redirecionamento (Redirection Layer) são interesses transversais que definem uma camada de interface a um objeto (adiciona uma funcionalidade ou altera o contexto) e en- caminha chamadas a ele. São geralmente implementados por uma camada de redirecionamento que possui métodos responsáveis por repassar chamadas a outros métodos. Esse tipo de inte- resse transversal é capturado por pontos de corte e advices do tipo around durante a refatoração para aspectos. Os padrões decorator e adapter são exemplos desse tipo. Adição de Variabilidade (Add Variability) correspondem a interesses transversais que usam métodos como parâmetro. Interesses transversais desse tipo criam objetos de tipos (anôni- mos) que implementam uma ação única e específica: ActionListener.actionPerfor- med(), Command.execute(), Runnable.run(). Esse tipo generaliza interesses que 14 2.2 Tipos de Interesses Transversais são implementados por um conjunto de métodos. Os métodos assumem responsabilidade pela chamada a determinado objeto, e possivelmente executam tarefas adicionais como modificação de parâmetros de chamadas. Exposição de Contexto (Expose Context) são interesses transversais que expõem o con- texto de métodos chamadores aos métodos chamados por meio da passagem de informações a cada um dos métodos na pilha de chamadas (não é necessário passar as informações como um conjunto de parâmetros para cada método no fluxo de controle). Esse tipo também é conhecido como Wormhole (Laddad, 2003). O idioma de implementação é caracterizado pela adição de argumentos a cada método na pilha de chamadas. Esse tipo de interesse transversal também pode ser capturado por pontos de corte e advices, nos quais o ponto de corte captura o contexto a ser passado. Sobreposição de Papéis (Role Superimposition) é um tipo de interesse transversal cujo objetivo é implementar um papel ou responsabilidade secundária específica. É caracterizado pela implementação de uma interface, ou implementação direta de métodos que poderiam ser abstraídos pela definição de uma interface. Podem ser capturados por um ponto de inserção (introduction mechanisms) durante a refatoração para aspectos. São exemplos desse tipo os padrões Observer, Command, e Visitor (Marin et al., 2004). Classes de Suporte para Sobreposição de Papéis (Support Classes for Role Superim- position) é um tipo de interesse transversal que usa classes aninhadas para tornar o relacio- namento entre classe explícito. Assim torna-se possível sobrepor determinado papel a uma hierarquia de classes. Não há um idioma de implementação específico para esse tipo mas é possível observá-lo em comentários e documentação do sistema. Propagação de Exceção (Exception Propagation) corresponde a interesses transversais que implementam a propagação de exceção para eventos em que nem o método nem os chama- dores têm uma resposta apropriada. Geralmente, é um tipo caracterizado pela propagação da exceção para os métodos chamadores. Declaração de Cláusula throws (Declare Throws Clause) são interesses transversais que adicionam uma exceção específica à cláusula throws para todos os métodos dentro de determi- nado contexto. Imposição de Design (Design Enforcement) é um tipo em que há a imposição de deter- minado tipo de estrutura ao sistema. Por exemplo, todas as classes em uma hierarquia devem declarar construtores sem argumentos. Imposição de Comportamento Dinâmico (Dynamic Behavior Enforcement) são interes- ses transversais que implementam a imposição de regras para o uso de objetos, por exemplo obrigatoriedade de inicialização antes do uso. É possível observar que os tipos Imposição de Contrato e Comportamento Consistente têm características em comum, no entanto eles têm objetivos diferentes de acordo coma definição de Marin et al. (2005): interesses transversais do tipo Imposição de Contrato garantem deter- 15 2.2 Tipos de Interesses Transversais minadas condições devido às relações entre um método e seus chamadores. Os tipos Comportamento Consistente, Imposição de Contrato, Papéis Entrelaçados, Ca- mada de Redirecionamento, Adição de variabilidade e Exposição de Contexto têm em comum o objetivo de prover consistência em relação a determinado comportamento do sistema. Assim, tais tipos podem ser generalizados em uma categoria de tipos comportamentais. O que difere cada um deles é o idioma de implementação que os caracteriza. Isso implica que em uma ativi- dade de refatoração para aspecto são necessários mecanismos diferentes para que cada um deles sejam refatorados corretamente (Marin et al., 2005). A classificação proposta por Marin et al. (2005) estabelece uma linguagem comum para a descrição de situações que incorrem em interesses transversais. Além disso, a classificação proposta é capaz de auxiliar pesquisadores a compreender os resultados obtidos por técnicas de identificação de interesses transversais por meio do mapeamento de sintomas identificados para os tipos genéricos de interesses. A classificação de interesses transversais proposta por Ducasse et al. (2006) é mais gené- rica que a apresentada por Marin et al. (2005) e, diferentemente, independe do paradigma de programação usado. Ducasse et al. (2006) propõe metáforas para a classificação de interesses transversais que facilitam o entendimento de sintomas de transversalidade. A classificação é estendida por da Silva et al. (2009) e Figueiredo et al. (2009) resultando em 13 sintomas, 3 deles descritos a seguir. Ovelha Negra (Black Sheep): Sintoma caracterizado pelo espalhamento de fragmentos de código em diversos módulos do sistema. Não há um módulo cuja maior parte do código correspondente é dedicado à implementação do interesse. Este sintoma é ilustrado na Figura 2.3 em que as caixas representam módulos de um sistema e as áreas em cinza indicam os fragmentos de código que implementam o interesse. Figura 2.3: Representação do sintoma Ovelha negra em diversos módulos de um sistema (Adap- tado de (Da Silva, 2009)) Polvo (Octopus): Interesses transversais do tipo Polvo são relativamente bem modulariza- dos, porém há código que o implementa espalhado por outros módulos. O módulo dedicado somente à implementação de parte do interesse é o ’corpo’ do polvo, e os demais fragmentos de código espalhados são os ’tentáculos’. O sintoma é ilustrado pela Figura 2.4, em que uma caixa 16 2.2 Tipos de Interesses Transversais que representa um módulo é totalmente dedicada à implementação do interesse, e as demais caixas indicam o espalhamento dos ’tentáculos’ do polvo. Figura 2.4: Representação do sintoma Polvo em diversos módulos de um sistema (Adaptado de (Da Silva, 2009)) Dominador (God Concern): Sintoma relativo a interesses que implementam diversas fun- cionalidades do sistema. Esse tipo de interesse apresenta alto grau de espalhamento e compõe a maior parte do sistema. O sintoma é ilustrado na Figura 2.5. Figura 2.5: Representação do sintoma Dominador em diversos módulos de um sistema (Adap- tado de (Da Silva, 2009)) Os três sintomas descritos são interesses implementados em módulos parcialmente ou total- mente dedicados a eles. Há ainda sintomas relativos a herança que envolvem estruturas hierár- quicas, são eles: Planta Trepadeira (Clibing Plant) e Doença Hereditária (Hereditary Desease); sintomas relativos a acoplamento, caracterizados pela existência de acoplamento entre os com- ponentes do sistema que implementam um interesse, são eles: Interesse Enraizado (Tree Root), Tsunami, Serpente (King Snake), e Rede Neural (Neural Network); e sintomas relativos a pro- blemas de modularidade, são eles: Cópia Carbono (Copy Cat), Ovelha Dolly (Dolly Sheep), Interesse Exclusivo de Dados (Data Concern), e Interesse Comportamental (Behavioural Con- cern). 17 2.3 Considerações Finais 2.3 Considerações Finais Neste capítulo foi demonstrado que a transversalidade é caracterizada e classificada de ma- neiras diferentes na literatura. O principal problema relacionado às múltiplas definições e classi- ficações é que a validação dos resultados produzidos pelas técnicas de identificação de interesses transversais é ambígua. Ou seja, duas pessoas podem discordar acerca de um mesmo candidato a interesse transversal sendo que uma define tal candidato como real-positivo e a outra como falso-positivo. Como a interpretação de resultados é sujeita ao indivíduo que interpreta, resultados da re- plicação de determinada técnica tornam-se subjetivos. A comparação entre técnicas também é complexa, não somente pelas diferentes interpretações acerca dos resultados obtidos mas tam- bém pelas especificidades de cada uma. Além da falta de consenso sobre o que é a transversalidade de interesses, muitos autores associam transversalidade diretamente a aspectos (orientação a aspectos). Em geral, as téc- nicas para identificação de interesses transversais retornam conjuntos de elementos de código (classes, métodos, fragmentos de código) que, de acordo com determinada definição de trans- versalidade, são candidatos a aspectos. No entanto, quando um elemento de código é apontado como pertencente a um interesse transversal ele não necessariamente deve ser refatorado para um aspecto. A associação direta interesse transversal-aspecto pode tornar-se um problema, pois nem sempre são identificados todos os elementos de código que implementam determinado inte- resse transversal. Se o objetivo da identificação é a refatoração de um interesse transversal para aspecto, todos os elementos que o implementa devem ser identificados. Desse modo, é neces- sário definir de modo não ambíguo qual o tipo de interesse transversal que se deseja identificar, e escolher a técnica mais apropriada para esse tipo, de modo que sejam obtidos resultados mais precisos. Neste capítulo foram apresentadas as principais características de interesses transversais e foram dados vários exemplos das diferentes definições de transversalidade e interpretação de resultados obtidos na busca por interesses transversais. Foram apresentados os tipos de inte- resses transversais propostos pela classificação de Marin et al. (2005) e Ducasse et al. (2006). Detalhes sobre as principais abordagens para a identificação de interesses transversais adotadas pelas técnicas propostas na literatura são apresentados no Capítulo 3. 18 CAPÍTULO 3 Técnicas para a identificação de interesses transversais As técnicas para a identificação de interesses transversais propostas na literatura implemen- tam diferentes abordagens de identificação. As mais comuns empregam um algoritmo ou uma combinação de algoritmos baseados em estruturas de árvore, algoritmos de pesquisa em gra- fos, detecção de clones, análise estrutural de componentes e de execução, análise formal de conceitos, análise fan-in, regras de associação, e análise histórica. Além disso, o processo de identificação de interesses transversais pode ser analisado sob duas perspectivas diferentes: geral e específica. A primeira diz respeito às etapas executadas para a identificação de interesses transversais em qualquer técnica de identificação. A segunda diz respeito às etapas de identificação executadas por uma abordagem/técnica ou ferramenta específica. As etapas de identificação comuns a todas as técnicas de identificação de interesses trans- versais são ilustradas na Figura 3.1. Dados do programa Representação intermediária Processo de Iden. Específico Resultados da Iden. Análise Manual Pré-processamento Identificação Pós-processamento Interação do usuário Figura 3.1: Etapas do processo de identificação de interesses transversais (Adaptado de Delfim (2013)) De acordo com as etapas de identificação mostradas na Figura 3.1, o primeiro passo para executar a identificação de interesses transversais é a coleta de dados do programa em análise, 19 e se necessário, o pre-processamento dos mesmos para que sirvam como entrada para a técnica escolhida. O pre-processamento resulta em uma representação intermediária do programa, que é submetida à técnica de identificação escolhida e pode requerer a intervenção manual do usuário, por exemplo para a criação de casos de uso na aplicação de técnicas dinâmicas (Tonella e Ceccato, 2004). É importante notar que nem sempre o pre-processamento dos dados de entrada é manual. Por exemplo, a ferramenta FINT (Marin et al., 2004) faz a identificação de candidatos a in- teresses transversais sem requerer nenhum tipo de pre-processamento manual. Ao finalizar a atividade de identificação a ferramenta/abordagem escolhida apresenta os resultados obtidos que são analisados manualmente pelo usuário. Essa é a etapa de pós-processamento. O processo de identificação específico, envolve atividades que podem ser executados ma- nualmente ou não, como por exemplo a configuração de filtros e limiares para a aplicação de técnicas específicas. Como exemplo de funcionamento do processo específico de identificação, duas técnicas são apresentadas a seguir: Análise Fan-in e Detecção de Clones. 3.1 Análise Fan-in Marin et al. (2004) propuseram a análise fan-in para a identificação de interesses transversais em sistemas de software após observar que, geralmente, interesses transversais exibem alto valor fan-in. A análise fan-in calcula o valor da métrica fan-in – obtida estaticamente a partir do código fonte – para todos os métodos em um sistema orientado a objetos. Marin et al. (2004) definem o valor fan-in de um método m como o número de métodos em um sistema S que faz chamada à m. Apesar de ser uma técnica estática, o algoritmo para cálculo do valor fan-in elaborado por Marin et al. (2004) trata o polimorfismo fazendo com que uma chamada a um método m con- tribua também para o valor fan-in de todos os métodos que o refina. Desse modo métodos polimórficos não são punidos. O processo de identificação específico estabelecido pela análise fan-in é ilustrado na Figura 3.2 e consiste de três etapas que são descritas a seguir: • Cálculo do valor fan-in para todos os métodos do sistema. Tal cálculo depende do algo- ritmo elaborado e de como tal algoritmo trata casos específicos como o polimorfismo. • Filtragem de resultado, que deve ser limitado a um conjunto de métodos cujos valor fan-in é maior que um valor mínimo previamente definido. Além disso, devem ser descartados métodos utilitários, assessores e modificadores para evitar ruídos nos resultados. • Análise manual dos métodos resultantes do processo de identificação para validá-los ou não como parte da implementação de um interesse transversal. Os experimentos em que a análise fan-in foi aplicada para a identificação de interesses transversais (Marin et al., 2004) apresentaram precisão aproximada de 33%, ou seja, 33% dos 20 3.1 Análise Fan-in Dados do programa Representação intermediária Processo de Iden. Específico Resultados da Iden. Análise Manual Pré-processamento Pós-processamento Cálculo do valor fan-in Seleção de filtros para obter um conj. menor de sementesEtapas do algoritmo para cálculo do valor fan-in Interação do usuário Identificação Figura 3.2: Perspectiva específica do processo de identificação de interesses transversais - Aná- lise Fan-in (Adaptado de Delfim (2013)). métodos resultantes correspondiam à implementação de algum interesse transversal. Nós rea- plicamos a análise fan-in utilizando uma abordagem histórica para a identificação de interesses transversais e foi obtida uma precisão de até 39% (o experimento realizado é descrito em Marcal et al. (2017)). 3.2 Detecção de Clones A duplicação de código é um dos sintomas que interesses transversais podem apresentar, pois como são incompatíveis com a estrutura do sistema sua implementação acaba espalhada por diversos trechos de código (principalmente devido ao reuso de código). A detecção de duplicação de código como técnica para a identificação de interesses transversais pode adotar diferentes abordagens que implicam em diferentes processos específicos de identificação. Por exemplo, em Bruntink et al. (2004) são utilizados três detectores de duplicação diferentes, um baseado em grafos de dependência, um segundo em árvores de sintaxe abstrata, e o terceiro em tokens. Tais detectores são descritos a seguir. Detecção de Clones em Grafos de Dependência utiliza grafos de dependência para identificar duplicação de código. Cada instrução (statement) no código de um programa é re- presentada por um nó do grafo e as arestas representam relações de dependência entre as ins- truções. A duplicação de código é identificada por meio da comparação entre vários grafos de dependência gerados a partir do programa em análise. Detecção de Clone em Árvores de Sintaxe Abstrata (AST) utiliza a árvore de sintaxe abstrata do código fonte. Os algoritmos de detecção de duplicação de código desse tipo buscam por sub-árvores semelhantes na AST e retornam pares de instruções similares que são potenciais sementes de interesses transversais. 21 3.2 Detecção de Clones Detecção de Clone por análise de Tokens aplica análise léxica ao código fonte e sub- sequentemente os tokens gerados são utilizados como base para a detecção de duplicação de código. A maioria dos detectores de clones produzem como resultado pares de clones, ou seja pares de fragmentos de código que são similares. Após a identificação dos pares de clones utilizando os detectores, Bruntink et al. (2004) agrupam os clones obtidos em grupos chamados de classes de clones. Todos os fragmentos de código de uma mesma classe são clones entre si. As classes são então avaliadas para determinar a eficiência do detector para a identificação de interesses transversal. Idealmente cada classe deve conter todo trecho de código relacionado a um determinado interesse transversal. Quanto menos classes forem necessárias para capturar toda a extensão da implementação de um interesse transversal, mais eficiente é o detector. 3.2.1 Análise, Comparação, e Combinação de Técnicas Nesta seção é feita uma análise descritiva qualitativa das técnicas de identificação de inte- resses transversais consideradas pra este trabalho. O objetivo de tal análise é fazer um levan- tamento e descrever os principais atributos de cada abordagem adotada para a identificação de interesses transversais. Inicialmente foram selecionados os critérios a serem utilizados para a análise das técnicas. Kellens et al. (2007) apresentam um conjunto de critérios para comparar técnicas de identi- ficação de interesses transversais. Os critérios foram elaborados para permitir a análise de características específicas das técnicas. Assim, é possível contrastar as restrições impostas por cada técnica, o tipo de análise executada, o grau de automação e a escalabilidade. Utilizaremos um subconjunto dos critérios estabelecidos por Kellens et al. (2007) para a análise de técnicas para a identificação de interesses transversais. A seguir é apresentada uma breve descrição dos critérios definidos em Kellens et al. (2007). Dados estáticos ou dinâmicos Critério relativo ao tipo de dados que a técnica analisa. Dados podem ser obtidos por meio de processamento estático do código fonte do sistema, ou dinamicamente por meio da execução de casos de uso pré-definidos, por exemplo. Há técnicas híbridas que executam a análise sobre dados obtidos estática e dinamicamente. Análise léxica, estrutural, ou comportamental Critério referente ao tipo de análise executada sobre os dados obtidos a partir de determinado programa. A análise léxica preocupa-se com sequências de caracteres e expressões regulares. Já a análise estrutural/comportamental preocupa-se com árvores de derivação sintática, tipo de informação e envio de mensagens, por exemplo. Granularidade Critério relativo à granularidade das sementes resultantes da aplicação de uma técnica. Há técnicas em que os resultados correspondem a métodos, outras a fragmentos de código ou classes (quando o sistema em análise é orientado a objetos, por exemplo). 22 3.2 Detecção de Clones Espalhamento ou emaranhamento de código Critério relativo aos sintomas de trans- versalidade que a técnica consegue identificar. É importante notar que espalhamento e ema- ranhamento é uma classificação geral para diversos sintomas que podem ser apresentados por sementes. Tipo de envolvimento do usuário Critério relativo ao esforço manual requerido para aplicar a técnica. Por exemplo, análise de sementes resultantes. Sistema de maior porte usado para avaliação empírica Critério relativo ao tamanho do maior sistema de software ao qual a técnica foi aplicada experimentalmente. A precisão de uma técnica quando utilizada em sistemas de pequeno porte pode não se repetir em sistemas de grande porte (problema de escalabilidade). Isso ocorre devido a vários fatores como com- plexidade computacional da técnica e aumento exponencial do esforço manual requerido para a aplicação da mesma. Por isso, esse critério é importante. Pré-condições Critério referente às premissas assumidas pela técnica em relação à imple- mentação de interesses transversais. Por exemplo, convenções para a nomenclatura de métodos e classes. 3.3 Critérios de Análise A partir de uma revisão sistemática da literatura realizada para este trabalho (Marçal et al., 2016), 25 técnicas para a identificação de interesses transversais foram selecionadas. As técni- cas foram analisadas e divididas em grupos de técnicas que compartilham do mesmo método de análise para identificar interesses transversais. Os grupos foram nomeados como segue: (1) Análise de alterações concomitantes em código; (2) Análise de chamadas a métodos; (3) Aná- lise de clustering; (4) Análise de grafos; (5) Análise de link; (6) Análise de rastros de execução; (7) Análise formal de conceitos; (8) Análise de clones; (9) Análise de padrões de linguagem; e (10) Análise histórica. A seguir é descrita as características das técnicas que compõem cada um dos grupos. • (1) São técnicas que analisam dependências lógicas com base em padrões de alterações concomitantes em artefatos de software. Por exemplo, um conjunto de classes, métodos, ou pacotes que são alterados frequentemente em um mesmo commit. • (2) Técnicas que procuram por interesses transversais por meio da análise de padrões de invocação a métodos. Em alguns casos, padrões de término de execução de métodos também são analisados. As técnicas desse grupo têm sua análise baseada apenas em código fonte e o que é possível extrair diretamente dele, por exemplo Árvores de Sintaxe Abstrata. 23 3.3 Critérios de Análise • (3) Técnicas que utilizam algoritmos de clustering para tentar agrupar componentes que implementam interesses transversais. Por exemplo, agrupar todos os métodos que imple- mentam determinado interesse transversal em um mesmo cluster. • (4) Técnicas que elaboram uma representação em grafo para o sistema e analisa as de- pendências de elementos de software utilizando o grafo gerado. Por exemplo, Grafos de Controle de Fluxo podem ser usados para analisar o comportamento do sistema de modo estático (sem precisar executar o programa). • (5) Técnicas que utilizam a análise de link para analisar dependências implícitas e explí- citas entre elementos do programa, na busca por interesses transversais. • (6) Técnicas em que o sistema em análise é executado para cenários de caso de teste bem definidos. Os traços de execução são obtidos e analisados na busca por interesses transversais. • (7) Técnicas que empregam a análise formal de conceitos utilizando componentes de software para localizar interesses transversais. • (8) Técnicas que aplicam algoritmos de detecção de duplicação de código para localizar interesses transversais. • (9) Técnicas que buscam por padrões de código referentes a convenções de nomencla- tura utilizadas ao longo da codificação. Tais padrões podem indicar trechos de código relacionados/similares podem indicar a existência de interesses transversais no sistema. • (10) Técnicas que analisam dados provenientes do repositório de software para analisar os aspectos evolutivos do sistema e identificar interesses transversais. Os grupos de técnicas foram individualmente analisados e posteriormente comparados entre si. Assim, os critérios de análise foram selecionados com o objetivo de identificar e entender os fatores com maior potencial de impacto na escolha da técnica a ser aplicada para a identifi- cação de interesses transversais. Os critérios são: tipo de dado que analisa, granularidade dos resultados, tipo de análise que executa, sintoma de transversalidade que identifica, e esforço manual requerido para aplicação. Para analisar os sintomas de transversalidade relacionados a cada grupo de técnicas, foram considerados apenas dois sintomas gerais: espalhamento e ema- ranhamento, para simplificar a análise. Os critério descritos foram obtidos a partir do trabalho elaborado por Kellens et al. (2007), porém foram empregados não para a comparação entre técnicas, mas para compreender os fatores de maior impacto nos resultados da aplicação de técnicas de identificação. Para facilitar a compreensão, os critérios de análise são mostrados separadamente de acordo com o grupo de técnicas correspondente. Na Tabela 3.2 são apresentados os tipos de dados de entrada aceitos por cada grupo, na Tabela 3.3 são analisados de acordo com a granularidade de 24 3.3 Critérios de Análise resultados. Na Tabela 3.4 são mostrados os tipos de análises executadas, enquanto que na Tabela 3.5 é mostrada a granularidade dos resultados da análise. Por fim, na Tabela 3.6 é mostrado o tipo de esforço manual requerido. Na Tabela 3.1 são listadas as técnicas que implementam cada uma das abordagens de identificação consideradas para este trabalho. Tabela 3.1: Técnicas de identificação selecionadas na amostragem teórica. Técnica Marin et al. (2004) Tourwe e Mens (2004) Bruntink et al. (2004) Breu e Krinke (2004) Tonella e Ceccato (2004) Tourwe e Mens (2004) Bruntink et al. (2004) Breu (2005) Bruntink et al. (2005) Shepherd et al. (2005) Canfora et al. (2006) Krinke (2006) Breu e Zimmermann (2006) Qu e Liu (2007a) Zhang e Jacobsen (2007) Zhang et al. (2008) Ishio et al. (2008) Krinke (2008) Cojocar e Czibula (2008) Ceccato e Tonella (2009) Maisikeli e Mitropoulos (2010) Huang et al. (2010) Qu et al. (2011) Zhang e Jacobsen (2012) Junior et al. (2012) McFadden e Mitropoulos (2012) Marcal et al. (2017) Na Seção 3.3.1 é feita uma avaliação comparativa dos grupos de técnicas considerados neste trabalho. 3.3.1 Análise e Comparação de Técnicas A partir dos dados reportados na tabela 3.4 observa-se que a maior parte das técnicas pro- postas na literatura realizam análises estática e estrutural de métodos, e requerem intervenção manual somente para a análise das sementes resultantes. Além disso, poucas técnicas execu- tam análises a nível de linha de código ou classe. Observamos que isso acontece pois tentar identificar interesses transversais a nível de linha de código pode elevar o número de sementes resultantes e consequentemente o esforço manual requerido para validação de resultados. A 25 3.3 Critérios de Análise Tabela 3.2: Tipo de dado de entrada por abordagem adotada pelas técnicas atuais para a identi- ficação de interesses transversais. Grupo de técnicas Tipo de dado de entrada Estático Dinâmico Análise de alterações concomitantes em código X Análise de chamadas a métodos X Análise de clustering X Análise de grafos X X Análise de link X Análise de rastros de execução X Análise formal de conceitos X X Análise de clones X Análise de padrões de linguagem X Análise histórica X Tabela 3.3: Granularidade de resultados da aplicação de técnicas atuais para a identificação de interesses transversais. Grupo de técnicas Granularidade Fragmento de código Linha de código Método Classe Análise de alterações concomitantes em código X Análise de chamadas a métodos X Análise de clustering X Análise de grafos X X Análise de link X Análise de rastros de execução Análise formal de conceitos X X Análise de clones X Análise de padrões de linguagem X Análise histórica X capacidade de uma técnica em indicar em um arquivo fonte a linha de código exata onde ocorre a transversalidade facilita a identificação e análise de sementes, porém tal benefício só é obtido caso a técnica apresente resultados muito precisos, o que é difícil, visto que as técnicas que fazem análise a nível de linha de código geralmente retornam muitas sementes falso-positivas. O inverso é observado em técnicas com granularidade alta, como por exemplo as que resul- tam em classes que contém interesses transversais. Nesse caso, apesar de o número de sementes ser menor, o esforço de análise ainda é alto, pois é necessário analisar toda a extensão da classe para identificar os trechos de código que implementam interesses transversais. Apenas duas das técnicas consideradas para este trabalho têm granularidade a nível de classe como mostrado na Tabela 3.3. 26 3.3 Critérios de Análise Tabela 3.4: Tipo de análise executada nas abordagens adotadas pelas técnicas atuais para a identificação de interesses transversais. Grupo de técnicas Tipo de análise Estrutural Comportamental Léxica Histórica Análise de alterações concomi- tantes em código X Análise de chamadas a métodos X X Análise de clustering X X Análise de grafos X X X Análise de link X X Análise de rastros de execução X X Análise formal de conceitos X X X Análise de clones X X Análise de padrões de linguagem X Análise histórica X Tabela 3.5: Sintomas de transversalidade analisados nas abordagens adotadas pelas técnicas atuais para a identificação de interesses transversais. Grupos de técnicas Sintoma de Transversalidade Espalhamento Emaranhamento Análise de alterações concomitantes em código X Análise de chamadas a métodos X Análise de clustering X X Análise de grafos X Análise de link X Análise de rastros de execução X X Análise formal de conceitos X X Análise de clones X Análise de padrões de linguagem X Análise histórica X Os dados mostrados na Tabela 3.6 deixam claro que apesar de automatizar a busca por inte- resses transversais, nenhuma das técnicas analisadas é capaz de identificar interesses transver- sais sem o envolvimento humano. Todas requerem a análise manual das sementes resultantes, fato que está relacionado a três assertivas para toda técnica de identificação de interesses trans- versais: (1) O número de sementes resultantes deve ser limitado de modo que seja viável a análise manual das mesmas. (2) A limitação do número de sementes resultantes não deve preju- dicar a precisão da técnica nem se contrapor aos objetivos da identificação. (3) A validação de resultados é subjetiva, pois depende do conhecimento e definição de transversalidade adotada pelo avaliador. As assertivas (1) e (2) dão origem à tripla restrição precisão vs. número de sementes vs. esforço manual ilustrada na Figura 3.3. Qualquer perturbação em um dos fatores impacta dire- tamente nos demais, como descrito a seguir. 27 3.3 Critérios de Análise Tabela 3.6: Esforço manual requerido nas abordagens adotadas pelas técnicas atuais para a identificação de interesses transversais. Grupo de técnicas Esforço Manual Exigido Análise de alterações concomitantes em código Análise de sementes resultantes Análise de chamadas a métodos Análise de sementes e configuração de parâmetros de identificação (filtros e th- resholds) Análise de clustering Análise de sementes resultantes Análise de grafos Análise de sementes resultantes Análise de link Análise de sementes resultantes Análise de rastros de execução Pré-processamento de dados e análise de sementes resultantes Análise formal de conceitos Pré-processamento de dados e análise de sementes resultantes Análise de clones Análise de sementes resultantes Análise de padrões de linguagem Análise de sementes resultantes Análise histórica Análise de sementes resultantes Esforço manual Precisão Número de sementes Figura 3.3: Tripla Restrição para Técnicas de Identificação de Interesses Transversais. É imediato que se tomada uma técnica pouco precisa e que retorna poucas sementes, as chances de nenhuma delas fazer parte da implementação de interesses transversais é alta. No entanto, uma técnica pouco precisa que resulta em muitas sementes, talvez identifique interesses transversais, apesar de sua imprecisão. Nesse último caso, o esforço manual para descarte de falso-positivos nos resultados obtidos aumenta. Para uma técnica precisa (por exemplo 95% de precisão), um número baixo de sementes resultantes significa que é possível identificar interesses transversais e o esforço manual para a análise de resultados é baixo. No entanto, apesar da precisão, a técnica pode não ser indi- cada para sistemas de grande porte que potencialmente têm um número elevado de interesses transversais. Resultados com poucas sementes podem refletir o fato de que a técnica é incapaz de identificar toda a extensão do código que implementa os vários interesses transversais em um sistema de grande porte. Nesse caso, atividades de refatoração e entendimento de código 28 3.3 Critérios de Análise requerem maior esforço por parte do desenvolvedor, que deve, a partir das poucas sementes reportadas, analisar todo o código fonte do programa para identificar toda a implementação de um interesse transversal. Se uma técnica é precisa e é capaz de identificar muitas sementes, o esforço manual para aná- lise dos resultados aumenta proporcionalmente, pois é preciso descartar falso-positivos, visto que apesar da precisão não há garantia de que todas as sementes reportadas realmente cor- respondem à implementação de interesses transversais. Ainda não foi reportada na literatura nenhuma técnica com precisão igual a 100% para qualquer cenário de aplicação. Paralelo ao desafio imposto pela tríplice restrição à proposição e uso de técnicas para a iden- tificação de interesses transversais, a subjetividade da validação manual das sementes resultan- tes influencia na precisão da técnica. Um exemplo de validação subjetiva pode ser observado em Breu e Zimmermann (2006) em que métodos resultantes do processo de identificação são validados como transversais se forem invocados de modo semelhante em diferentes módulos do sistema (mesmo contexto local e mesmos parâmetros de chamada) e se puderem ser implemen- tados/refatorados para aspecto. Breu e Zimmermann (2006) explicam que durante a validação de sementes não é considerado se a refatoração do método para aspecto poderia ou não melhorar a qualidade de código, e em caso de dúvida quanto à possível implementação do método como aspecto a semente é classificada como falso-positivo. A validação de sementes feita em Breu e Zimmermann (2006) é subjetiva pois (1) depende do conhecimento do avaliador acerca das possibilidades de implementação de interesses trans- versais como aspectos, e (2) depende da definição de similaridade contextual de chamada a métodos. É importante notar que a subjetividade dificulta a replicação de técnicas de identi- ficação e a comparação de resultados, já que critérios de validação vagos como o usados em Breu e Zimmermann (2006) impedem a equivalência de análise de sementes em uma possível replicação. A aplicação de técnicas dinâmicas em sistemas de software é limitada pelos trechos de có- digo do sistema passíveis de execução em algum caso de teste. Por isso, como observado na Tabela 3.4, o tipo de análise executada por técnicas dinâmicas é classificado como comporta- mental. Geralmente, técnicas dinâmicas são executadas a nível de métodos e exigem a elabora- ção de casos de uso com alta abrangência, ou seja que permitam exercitar a maior quantidade de código possível. Como nem sempre é viável elaborar casos de uso para todos os cenários de execução possíveis, os resultados da análise dinâmica podem não incluir interesses transversais cuja implementação não fora executada. Além disso, a elaboração dos casos de uso anterior à aplicação da técnica é um esforço manual adicional. Assim observa-se que técnicas dinâmicas requerem mais trabalho manual do que determinadas técnicas estáticas como por exemplo as propostas em Bruntink et al. (2004), Canfora et al. (2006), Cojocar e Czibula (2008). Há poucos estudos que tentam combinar o uso de dados estáticos e dinâmicos em uma única técnica (Breu, 2005, Qu e Liu, 2007b, Krinke, 2008). Tal combinação tem por objetivo minimizar a limita- ção imposta pela dificuldade em exercitar todos os cenários de execução possíveis em técnicas 29 3.3 Critérios de Análise Esforço manual Precisão Número de sementes Pré-Condições Figura 3.4: As pré-condições assumidas por técnicas de identificação podem afetar o número de sementes identificadas e o nível de esforço manual requerido. Indiretamente também afetam a precisão. dinâmicas. Técnicas baseadas em análise de tokens são aplicadas em dados estáticos e, geralmente, assumem que interesses transversais são implementados de modo específico e de acordo com convenções de codificação bem estabelecidas e aceitas pelos desenvolvedores. Assumir que interesses transversais são implementados seguindo convenções de codifica- ção específicas, ou que exibem características únicas e específicas pode afetar tanto a precisão quanto o número de sementes resultantes (Consequentemente afeta o esforço manual – Figura 3.4). O impacto negativo em potencial dessas pré-condições é minimizado proporcionalmente ao nível de conhecimento que o usuário da técnica tem sobre o código que implementa o sistema em análise. Além disso, Li e Prasad (2005) reportam que apesar de desenvolvedores entende- rem a importância do uso de convenções de codificação, eles podem não segui-las, por exemplo quando o desenvolvimento precisa ser acelerado. 3.3.2 Combinação de Técnicas Marin et al. (2006) propuseram um framework para a combinação de diferentes técnicas de identificação de interesses transversais com o objetivo de melhorar a precisão dos resultados obtidos. Observa-se em Marin et al. (2006) que a precisão e o número de sementes relevan- tes identificadas podem ser melhorados com a combinação de técnicas baseadas em diferentes abordagens de identificação. O tipo de combinação mais simples é a aplicação de duas técnicas distintas e a análise da intersecção dos resultados obtidos. No entanto, para isso é necessário haver compatibilidade de granularidade entre as técnicas. Além disso, elas devem ser dedicadas à identificação dos mesmos tipos de interesses transversais. Isso porque caso as técnicas combinadas identifiquem tipos distintos de interesses transversais, os resultados formarão conjuntos de sementes disjun- tos e a intersecção de resultados será vazia. Esse tipo de combinação melhora a precisão dos resultados desde que as técnicas escolhidas sejam compatíveis. Outro modo comum de fazer a combinação entre técnicas é tomar a união dos resultados 30 3.3 Critérios de Análise das mesmas. Esse tipo de combinação não requer a compatibilidade entre os tipos de interes- ses transversais identificáveis como é exigido na combinação pela tomada da intersecção de resultados. Além disso, o número de sementes resultantes pode ser maior. Isso significa que a combinação de técnicas pela união de sementes resultantes é uma boa opção para a identificação da maior quantidade possível de código que implementa interesses transversais. É importante notar que esse aumento no número de sementes resultantes altera o equilíbrio da tripla restrição ilustrada na Figura 3.3. A combinação entre técnicas de identificação de interesses transversais é difícil principal- mente devido às características específicas do processo de identificação de cada técnica, e tam- bém pela granularidade a qual tal processo é aplicado. Técnicas de diferente granularidade são difíceis de combinar. Para auxiliar no processo de combinação, em (Marcal et al., 2017) nós propomos um framework para a combinação de técnicas de identificação em diferentes níveis de granularidade (Marcal et al., 2017). Tal framework consiste no uso de técnicas com granu- laridade alta para selecionar os dados a serem analisados pela técnica com granularidade baixa. Experimentos executados constataram melhora significante na relevância dos resultados obtidos pelas técnicas combinadas. 3.4 Considerações finais Neste capítulo foi demonstrado que as técnicas para a identificação de interesses transversais propostas na literatura adotam abordagens de identificação diferentes. Mesmo técnicas perten- centes a um mesmo grupo podem adotar algoritmos de identificação distintos. Por exemplo, diferentes algoritmos de clustering ou algoritmos para detecção de duplicação de código. Toda técnica de identificação assume premissas sobre o modo como interesses transversais são implementados no sistema, e isso pode afetar a precisão dos resultados obtidos. No entanto, umas vez conhecidas pelo analista, é possível utilizar as premissas adotadas por cada técnica para direcionar sua aplicação à identificação de tipos específicos de interesses transversais, e assim obter resultados mais relevantes. A combinação de técnicas de identificação é difícil devido às especificidades de cada uma, como granularidade e métodos de busca por interesses transversais. Há diferentes maneiras de combinar técnicas de identificação, por exemplo tomando a intersecção ou união dos resultados de duas ou mais técnicas. A análise descritiva qualitativa baseada em critérios específicos das técnicas para a identifi- cação de interesses transversais propostas na literatura ajudou a identificar três parâmetros que têm grande impacto na aplicação e resultados de uma técnica. Tais parâmetros são: (1) tipo de dado de entrada, (2) tipo de análise, e (3) granularidade. Observou-se que o tipo de dado de entrada depende do sistema em análise, enquanto que o tipo de análise depende do tipo de dado selecionado. A granularidade influencia no esforço manual para a aplicação das técnicas de identificação e tem impacto direto sobre o número de sementes resultantes. Para aprofundar a análise sobre os parâmetros identificados foi realizado um estudo qualita- 31 3.4 Considerações finais tivo dos mesmos baseado na Teoria Fundamentada em Dados. A metodologia adotada permitiu confirmar e entender melhor os parâmetros preliminarmente observados, além de estendê-los para que fosse possível elaborar as diretrizes propostas neste trabalho. A metodologia adotada e a aplicação da Teoria Fundamentada em Dados são descritas no Capítulo 4. 32 CAPÍTULO 4 Metodologia A proposta deste trabalho é resultado direto da análise qualitativa de dados sobre técni- cas para a identificação de interesses transversais. A Teoria Fundamentada em Dados (TDF) (Strauss e Corbin, 1990, Walker e Myrick, 2006, Rondon e Pastor, 2007) foi adotada como me- todologia de pesquisa para auxiliar na explicação dos fatos observados durante a investigação de conceitos relacionados à identificação semi-automática de interesses transversais. A análise qualitativa dos dados extraídos da literatura por meio do uso da TDF deu origem às diretrizes propostas neste trabalho. Para explicar melhor a metodologia de pesquisa utilizada, a seguir são descritos os principais conceitos relacionados à TFD e como ela é utilizada. As ameaças da TFD à validade do estudo elaborado também é discutido a seguir. 4.1 Conceitos da Teoria Fundamentada em Dados A Teoria Fundamentada em Dados é um método de pesquisa qualitativa originalmente pro- posto por dois sociologistas, Barney Glaser e Anselm Strauss, como alternativa aos métodos de pesquisa tradicionais constituídos por formulação de hipótese, técnicas de verificação e análi- ses quantitativas. A TFD tem por objetivo permitir a formulação de teorias a partir da análise criteriosa de dados que são organizados em categorias. Tais categorias são obtidas por meio da análise do domínio do problema abordado pela pesquisa (Willig, 2013). Para identificar, refinar, integrar, e por fim formular uma teoria, são usadas estratégias como análise comparativa constante, amostragem teórica e codificação. A seguir são descritas as principais estruturas analíticas usadas no método da TFD de acordo com Willig (2013). 4.1.1 Categorias Categorias designam um conjunto de instâncias que compartilham determinadas caracterís- ticas e que descrevem suas instâncias em baixo nível de abstração. Assim, categorias podem ser 33 4.1 Conceitos da Teoria Fundamentada em Dados também chamadas de rótulos, conceitos, ou categorias descritivas (Strauss e Corbin, 1990). Por exemplo, C, Java, e Pascal são instâncias que podem ser agrupadas na categoria “Linguagem de Programação”. Com o progresso da pesquisa é possível identificar categorias em níveis mais elevados de abstração. Quando o nível de abstração de uma categoria aumenta, ela deixa de ser descritiva e passa a ser analítica, pois refere-se à interpretação de suas instâncias e não mais à descrição de características comuns de suas instâncias. Tanto categorias analíticas quanto descritivas são baseadas na identificação de relações de similaridade e diferenças entre os dados analisados (Dey, 1999), no entanto enquadram-se em diferentes níveis de abstração. 4.1.2 Codificação O processo de identificação de categorias é chamado de codificação e é realizado durante a análise dos dados coletados para a pesquisa. Inicialmente são identificadas categorias descri- tivas e, posteriormente, analíticas. Categorias analíticas são utilizadas para integrar categorias descritivas. Tal análise caracteriza o processo de comparação constante de dados (Strauss e Corbin, 1990). A codificação ocorre em três estágios (Strauss e Corbin, 1990). (1) Inicialmente é reali- zada a codificação aberta em que os dados são analisados e categorias descritivas iniciais são identificadas. Aqui as categorias refletem características gerais do problema investigado. Após a codificação aberta, é realizada a (2) codificação axial, em que os dados já catego- rizados são analisados novamente (processo de comparação constante) para que as categorias já definidas sejam refinadas, se necessário subdivididas em novas categorias, ou reagrupadas. O principal objetivo da codificação axial é tornar explícitos os relacionamentos existentes entre categorias e subcategorias. A partir do refinamento das categorias por meio da codificação axial, é realizada a codifi- cação seletiva. Essa codificação envolve a seleção e identificação de uma categoria principal capaz de relacionar todas as demais categorias. O processo de codificação seletiva envolve a validação e refinamento dos relacionamentos identificados na codificação axial para que seja possível integrar as categorias identificadas e formular a teoria final. Neste trabalho a codifica- ção seletiva não é realizada, pois não há uma única categoria (mas sim um conjunto) central que possa ser considerada como o conceito fundamental para a formulação das diretrizes propostas. 4.1.3 Comparação Consta