• Nenhum resultado encontrado

TrabalhodeGraduaçãoAliceZloccowickBornerdeOliveiraRecife27deJunhode2019 Aperfeiçoandotécnicasdemergeentreblocosdeinicializaçãoestáticosparaumaferramentademergesemiestruturado UniversidadeFederaldePernambucoCentrodeInformáticaGraduaçãoemEngenhariadaComputa

N/A
N/A
Protected

Academic year: 2022

Share "TrabalhodeGraduaçãoAliceZloccowickBornerdeOliveiraRecife27deJunhode2019 Aperfeiçoandotécnicasdemergeentreblocosdeinicializaçãoestáticosparaumaferramentademergesemiestruturado UniversidadeFederaldePernambucoCentrodeInformáticaGraduaçãoemEngenhariadaComputa"

Copied!
26
0
0

Texto

(1)

Universidade Federal de Pernambuco Centro de Informática

Graduação em Engenharia da Computação

Aperfeiçoando técnicas de merge entre blocos de inicialização estáticos para uma ferramenta de merge semiestruturado

Trabalho de Graduação

Alice Zloccowick Borner de Oliveira Recife

27 de Junho de 2019

(2)

Universidade Federal de Pernambuco Centro de Informática

Alice Zloccowick Borner de Oliveira

Aperfeiçoando técnicas de merge entre blocos de inicialização estáticos para uma ferramenta de merge semiestruturado

Trabalho apresentado ao Programa de Graduação em En- genharia da Computação do Centro de Informática da Uni- versidade Federal de Pernambuco como requisito parcial para obtenção do grau de Bacharel em Engenharia da Computação.

Orientador: Paulo Henrique Monteiro Borba

Recife

27 de Junho de 2019

(3)

Resumo

Sistemas de controle de versão, como Git, SVN e Mercurial, são amplamente utilizados atu- almente e são ferramentas essenciais para o desenvolvimento de softwares em equipe. Essas ferramentas utilizam uma técnica chamada merge não estruturado, que se baseia apenas em uma comparação textual entre as versões dos códigos alteradas pelos desenvolvedores para re- alizar a integração de código. Uma nova técnica, chamadamergesemiestruturado, propõe uma melhor utilização da estrutura do programa para realizar essa integração com maior precisão e diminuir o esforço manual na resolução dos possíveis conflitos gerado durante a integração.

Ferramentas já existentes utilizam essa nova técnica, porém, existem melhorias necessárias para justificar a utilização na indústria. Neste trabalho um novo módulo foi adicionado a ferramenta de integração semiestruturado existente, s3m para projetos em Java. Esse módulo trata cenários demergeenvolvendo blocos de inicialização estáticos. Foram avaliados 9 projetos opensource do GitHub, mostrando ganhos significativos. Apesar disso, também são encontradas evidências de que tempo e esforço devem ser investidos em outros módulos da ferramenta.

Palavras-chave: sistemas de controle de versão,mergesemiestruturado, conflitos de integra- ção, blocos de inicialização estáticos

(4)

Conteúdo

1 Introdução 5

2 Motivação 7

3 Solução 10

3.1 Merge Semiestruturado . . . 10

3.2 Algoritmo existente . . . 12

3.3 Algoritmo proposto . . . 13

3.4 Implementação . . . 15

4 Avaliação 16 4.1 Metodologia . . . 16

4.2 Resultados . . . 16

4.3 Análise . . . 18

4.3.1 Bloco removido . . . 18

4.3.2 Bloco com baixa similaridade e alta inserção . . . 19

4.3.3 Bloco com baixas similaridade e inserção . . . 20

5 Trabalhos relacionados e Riscos à validade 23

6 Conclusão 24

A Pseudocódigo do algoritmo proposto 26

(5)

C

APÍTULO

1

Introdução

Sistemas de controle de versão, como Git, SVN e Mercurial, são amplamente utilizados atu- almente e são ferramentas essenciais para o desenvolvimento de softwares em equipe. Essas ferramentas disponibilizam funcionalidades como histórico de desenvolvimento do projeto, ras- treamento de mudanças, portabilidade de código, técnicas demerge(integração), entre outras, tendo como principal objetivo facilitar a colaboração concorrente. Possibilitando que vários de- senvolvedores trabalhem paralelamente no mesmo projeto ou arquivo sem que ocorra perdas ou sobrescrita de código, quando feito omerge das modificações dos diferentes desenvolvedores para gerar uma versão do projeto.

Em muitos casos essas ferramentas são capazes de realizar o merge dos códigos automa- ticamente, porém, quando a ferramenta não é capaz, um conflito é reportado. A resolução de conflitos é o principal desafio das ferramentas demerge[10]. Quando ocorrem têm que ser re- solvidos manualmente por um desenvolvedor, o que ainda é um processo que consome tempo, possivelmente complicado e passível de erros. Muitos elementos interconectados podem es- tar envolvidos no conflito e o processo de mergedepende da análise sintática e semântica dos elementos, como descrito por Mens [1].

As ferramentas de maior utilização na indústria ainda utilizam a técnica de mergenão es- truturado. Esta conta apenas com uma simples comparação textual, conferindo se houveram mudanças em uma mesma área de código nas versões comparadas. Sem nenhuma análise sin- tática ou semântica dos elementos do programa, o que pode ocasionar erros, já que conflitos não ocorrem apenas se as mesmas linhas de código forem modificadas.

Existem também ferramentas que utilizam a técnica demergeestruturado. Esta trata os pro- gramas como árvores de sintaxe abstratas. Ele é capaz de explorar conhecimentos específicos de cada linguagem e, portanto, é mais preciso do que abordagens não estruturadas. Porém, é menos eficiente em relação ao tempo de execução [5].

Tentando encontrar um equilíbrio entre as técnicas citadas anteriormente, não estruturada e estruturada, Apel et al [2] propôs uma nova técnica, denominadamergesemiestruturado. Esta técnica é explicada em mais detalhes no Capítulo 3, mas a ideia geral é unir a generalidade das ferramentas não estruturadas e o conhecimento adquirido sobre a estrutura do programa de ferramentas estruturadas. Um primeiro protótipo de uma ferramenta de integração semies- truturado foi implementada, o FSTMerge. O autor mostra que houve uma redução no número de conflitos em média de 34%, em 60% dos projetos analisados, se comparado ao mergenão estruturado, porém, melhorias ainda precisam ser feitas.

Trazendo algumas dessas melhorias, Guilherme et al [3], desenvolveram uma nova ferra- menta, chamada s3m, em que, através da criação dehandlers(módulos) que lidam com tipos específicos de cenários demergeque precisam ser tratados separadamente, tenta realizarmer- gesmais preciso em projetos na linguagem Java.

Por exemplo, cenários de merge entre arquivos que contêm blocos de inicialização está- ticos podem ser complicados, pois esses blocos não possuem um identificador único, como, por exemplo, um método que pode ser facilmente identificado pelo seu nome mais sua lista de

(6)

6 CAPÍTULO 1 INTRODUÇÃO

parâmetros. Logo, por não possuírem um identificador, é um desafio realizar omatch(corres- pondência) entre esses blocos, principalmente em um cenário com múltiplos blocos de inicia- lização, para assim, então, poder realizar omergeentre os blocos corretos.

Quando omergesemiestruturado não é capaz de realizar omatchentre dois blocos, mantém os dois, o que pode levar a falsos negativos, visto que em alguns casos, como, por exemplo, mudanças feitas pelos desenvolvedores impactarem umas as outras, um conflito deveria ser reportado, e caso ele não seja, diz-se que ocorreu um falso negativo. Caso ocorra um cenário em que a ferramenta reportou um conflito, quando na verdade não deveria, chama-se de falso positivo.

Para solucionar tal problema, uma abordagem de match por similaridade textual entre os blocos de inicialização estáticos foi implementada em um dos handlers encontrados na fer- ramenta, o InitializationBlocksHandler, porém, como mostraremos neste trabalho, essa abor- dagem não foi suficiente para realizar o merge corretamente em alguns cenários e um novo algoritmo, utilizando, além da similaridade, o nível de inserção do conteúdo (linhas de código) de um bloco em outro, foi proposto.

Os Capítulos seguintes do trabalho estão dispostos da seguinte maneira: no Capítulo 2, a motivação para ser proposto um novo algoritmo, já no Capítulo 3, a solução descrita em mais detalhes, como também o funcionamento domerge semiestruturado em um pouco mais de detalhes. Logo em seguida, no Capítulo 4, uma descrição da metodologia de avaliação da solução e os resultados obtidos. O Capítulo 5 traz um pouco sobre trabalhos relacionados e riscos à validade. Por fim, no Capítulo 6 encontramos a conclusão do trabalho.

(7)

C

APÍTULO

2

Motivação

A ideia básica domergesemiestruturado é representar os artefatos do programa como árvores, da mesma forma que nomergeestruturado, e fornecer informações, por meio de uma gramática anotada, sobre como os nós de um determinado tipo (e.g. métodos ou classes) e as suas sub- árvores são integradas [2].

Os nós destas árvores são integrados utilizando uma técnica chamada de superimposição, proposta por Apel e Lengauer [4], esta será explicada em um pouco mais de detalhes no Ca- pítulo 3, mas basicamente realiza omatchdos nós por similaridade estrutural e nominal. Para omergede nós terminais (folhas da árvore) a ferramenta utiliza o mergenão estruturado, por isso então, chama-se semiestruturado, por ser uma junção das estratégias estruturada e não estruturada.

Tanto o merge estruturado quanto o merge não estruturado seguem as regras básicas do three-way merge [10], em que dois arquivos modificados, modificações que podem ter sido realizadas em múltiplos commits, são comparados em relação ao seu ancestral em comum.

Neste trabalho chamados deleft,rightebase, respectivamente.

Caso durante a superimposição não ocorra omatchentre dois blocos, ambos são mantidos na árvore. Isto ocorre no caso de blocos de inicialização estáticos, devido ao fato desses blocos não possuírem identificadores, ou seja, não é possível fazer um matchnem por similaridade estrutural, todos os blocos inicialização estáticos são folhas da árvore, nem nominal, visto que eles não têm nome.

Isso pode levar a falsos negativos, como mostrado por Guilherme et al [3], visto que em alguns casos, como, por exemplo, mudanças feitas pelos desenvolvedores impactarem umas as outras, um conflito deveria ser reportado, como podemos ver no exemplo da Figura 2.1.

Figura 2.1: Falso negativo obtido utilizando a ferramenta original FSTMerge [3].

(8)

8 CAPÍTULO 2 MOTIVAÇÃO

Neste caso, um conflito deveria ser reportado para que os desenvolvedores do projeto pos- sam resolver se a variável _name deve ser inicializada com o valor Maria ou Bob. Como a ferramenta original, FSTMerge, não é capaz de fazer omatchentre os blocos e realizar omerge entre eles, mantêm ambos os blocos. Sendo assim a variável será inicializada com o valorMa- ria(blocos de inicialização estático em Java são executados em ordem), o que pode não estar correto, porque pode afetar a lógica do outro desenvolvedor, que queria o valor de_namesendo Bob.

Para solucionar tal problema, uma abordagem de match por similaridade textual entre os blocos de inicialização estáticos foi implementada em um doshandlersencontrados na ferra- menta s3m, oInitializationBlocksHandler, em que somente após ser realizado omatchentre os blocos, omergenão estruturado é invocado, realizando omergeentre os conteúdos dos blocos.

Podemos ver um exemplo do funcionamento correto deInitializationBlocksHandlerna Fi- gura 2.2. Neste exemplo é fácil detectar os blocos correspondentes, ou seja, os matches, e realizar o merge, apenas pela alta similaridade que uns blocos têm com outros. Utilizando a ferramenta FSTMerge o resultado domerge seria um arquivo contendo os quatro blocos com conteúdos diferentes contidos emleft,baseeright, o que estaria incorreto.

Figura 2.2: Resultado correto obtido com ohandleradicionado a ferramenta s3m.

Porém, verificar apenas a similaridade textual não é suficiente em alguns casos, vamos olhar o exemplo seguinte, nas Figuras 2.3 e 2.4, retirado do projeto Jenkins da classeHudsonTest- Casee entender o porque.

Figura 2.3: Bloco embase.

(9)

CAPÍTULO 2 MOTIVAÇÃO 9

Figura 2.4: Bloco emleft.

Esses blocos possuem apenas 61% de similaridade textual, o que é menor do que um limiar aceitável para ser consideradomatch(70% é o limiar utilizado atualmente na ferramenta s3m).

Logo,InitializationBlocksHandlernão consideraria eles como ummatch, então, iria manter os dois blocos no resultado domerge.

O relaxamento desse limiar também não traria bons resultados visto que acabaria por resul- tar emmatchesincorretos, por exemplo, utilizando o já visto na Figura 2.2, poderia resultar em ummatchentre o primeiro bloco de basee o segundo deright, o que resultaria em um bloco contendo as três variáveisa,bec, o que já vimos não ser o resultado esperado.

O comportamento dohandleratual da ferramenta s3m de manter os dois blocos das figuras no arquivo final não é o esperado, já que, é fácil de perceber, analisando esses blocos que realmente se trata de ummatch, e a razão para tal é simplesmente devido a alta inserção (neste caso 100%) do conteúdo debaseemleft. O nível de inserção de conteúdo é conferido a partir da quantidade de linhas de código idênticas entre os blocos.

(10)

C

APÍTULO

3

Solução

A solução proposta por este trabalho é um novo algoritmo, como também sua implementação, em um novohandleradicionado a ferramenta s3m, que realiza omergeentre blocos de inicia- lização estáticos, não baseado apenas no nível de similaridade textual, como também no nível de inserção do conteúdo de um bloco em outro para realizarmatchesmais preciso.

O matché a correspondência entre dois blocos, ou seja, uma relação de paridade criada para que fique claro pro algoritmo que foi encontrado emleftourightum bloco semelhante ao bloco que existe embase, que é possivelmente uma edição. Essa definição é importante, pois, é com ela que o algoritmo é capaz de separar os blocos entre edição e adição. Veremos em seguida o algoritmo em mais detalhes.

3.1 Merge Semiestruturado

Para entendermos melhor o algoritmo do handler existente e do proposto por este trabalho é útil explicar com um pouco mais de detalhes como funciona omergesemiestruturado.

Como introduzido no início do Capítulo 2, a ideia básica do merge semiestruturado é re- presentar os artefatos do programa como árvores e realizar omergedos nós dessas árvores de maneira recursiva, através de uma técnica chamada de superimposição, que faz omatch dos nós por similaridade estrutural e nominal, representada de forma simples pela Figura 3.1.

Figura 3.1: Representação da superimposição das árvores sintáticas [4].

Como descrito por Apel e Lengauer [4], em Java, pacotes, classes e interfaces são represen- tados por nós não-terminais. Os artefatos de implementação que eles contêm são representados por nós filhos, por exemplo, um pacote contém várias classes e as classes contêm classes inter- nas, métodos e campos.

Dois nós não-terminais similares, ou seja, que possuem similaridade nominal ou estrutural, são compostos pela composição do seus nós filhos, por exemplo, dois pacotes com nomes iguais são unidos em um pacote que contém a composição dos elementos filhos (classes, interfaces, subpacotes) dos dois pacotes originais. Métodos, campos, imports, listas de modificadores, e as cláusulas deextends, implementsethrowsão representadas por nós terminais (as folhas da árvore), onde a recursão termina.

(11)

3.1 MERGE SEMIESTRUTURADO 11

As estruturas internas dos nós terminais ou conteúdo não são consideradas no modelo, por exemplo, o fato de que um método contém uma sequência de instruções ou que um campo se refere a um valor ou a uma expressão, por isso, regras de composição específicas devem ser criadas para esses casos. Para resumir, esta técnica funciona porque, em Java, a ordem de declaração de métodos não importa [7]. Como também, não importa a ordem declaração de variáveis [3].

Podemos então entender melhor o que houve durante a superimposição na Figura 3.1: temos a árvore TopOfStack, que possui o nó raizutil, representando o pacote, o nó Stack, a classe contida neste pacote e por fim a folhatop, um método. A árvoreBasicStack, que possui o nó raizutil, representando o pacote, o nóStack, a classe contida neste pacote, as folhaspopepush que são métodos, e a folha data representando um campo na classe. O resultado é a árvore CompStack, que possui as folhastop,pop,pushedata.

Este caso é um exemplo de um falso positivo das ferramentas não estruturadas, denominado conflito de ordem [3]. Um conflito seria reportado entre as declarações dos métodostop,pope push, quando na verdade o resultado esperado é o representado na Figura 3.1,CompStack, que é a representação do resultado da superimposição das árvores sintáticas que ocorre no merge semiestruturado, contendo os três métodos. Logo, esse tipo de falso positivo é resolvido pelas ferramentas semiestruturadas.

Para entender essa superimposição em um exemplo de código Java, podemos observar a Figura 3.2, que compara os resultados de ummergeutilizando uma estratégia não estruturada e semiestruturada.

Figura 3.2: Comparação dos resultados utilizando técnicas diferentes [6].

Neste exemplo simples, podemos ver claramente os benefícios que podem ser obtidos uti- lizando o merge semiestruturado. No resultado domergesemiestruturado vimos que a ferra- menta é capaz de adicionar à classeMembertanto o campousername, quanto o campoemail,

(12)

12 CAPÍTULO 3 SOLUÇÃO

pois, como os campos possuem identificadores diferentes, não são ummatch, logo, ambos são mantidos.

Já no resultado do merge não estruturado, visto que ambos os desenvolvedores alteraram a mesma linha de código com valores diferentes, como a comparação textual é linha a linha, um conflito é reportado, gerando esforço manual desnecessário para resolução do mesmo. A dificuldade do merge varia, diferente desse simples exemplo, pode ser bastante complexo e trabalhoso para resolução manual.

3.2 Algoritmo existente

O algoritmo existente, implementado nohandler InitializationBlocksHandler, é fortemente ba- seado na similaridade textual entre os blocos para realizar omatch. O algoritmo de similaridade textual utilizado é o cálculo da distância de Levenshtein [3].

Explicando este algoritmo de maneira breve, a distância Levenshtein, é a distância de edi- ção entre dois blocos. Os conteúdos desses blocos são armazenados comostrings, e a distância é dada pelo número mínimo de inserções, remoções ou edições necessárias para transformar um bloco em outro. Podemos agora entender porque no exemplo das Figuras 2.3 e 2.4 a simi- laridade é baixa, devido ao alto nível de inserções para transformar o bloco de baseno bloco deleft.

O algoritmo funciona da seguinte maneira: para cada bloco de inicialização estático exis- tente embase, procura-se um com conteúdo similar emlefte emright, utilizando como limiar de similaridade 70%.

Caso sejam encontrados blocos similares, um match, triplas são criadas, com o conteúdo original do bloco embase, e o conteúdo editado porleftouright. Caso apenas um deles tenha alterado, por exemplo, apenasleftfez alterações no bloco,righté ignorado nessa tripla e vice- versa. Se não forem encontrados blocos similares, o bloco não vai estar em nenhuma tripla, logo não vai estar no arquivo final demerge.

Essas triplas são criadas com a intenção de identificar os trios de blocos similares, para caso os arquivos envolvidos nomerge (base, left eright) contenham múltiplos blocos, o algoritmo seja capaz de realizar omergeentre os blocos corretos.

Se não houver nenhum similar embase, ainda podem existir similares entre os blocos adi- cionados por left e right. Esses também são verificados e caso um match ocorra, triplas são criadas, ignorando o valor de base, e omerge é feito. Passo importante para que, caso left e right adicionem o mesmo bloco, não haja duplicação. Caso não ocorra match, o bloco será adicionado à árvore.

Após a criação de todas as triplas, o merge não estruturado é realizado entre o conteúdo delas e a árvore é atualizada com o novo conteúdo.

Há também um caso particular, caso haja apenas um bloco de inicialização estático em cada um dos arquivos de merge, então, provavelmente, omatch é entre eles e a similaridade não chega a ser verificada.

Como ilustrado anteriormente, no exemplo das Figuras 2.3 e 2.4, e seguindo o comporta- mento do algoritmo descrito acima, o resultado domergeiria conter os dois blocos no arquivo

(13)

3.3 ALGORITMO PROPOSTO 13

final. O que não é o esperado, já que, é fácil de perceber, analisando os blocos, o alto nível de inserção (100%) do conteúdo debaseemleft. Logo, são ummatche deve ser feito omergedos conteúdos deles.

Outro problema que pode ocorrer no algoritmo descrito é que, no caso particular, realizar o matchdireto entre esses blocos sem nenhuma verificação pode ser perigoso. Caso um dos blocos seja completamente diferente dos outros dois, o que indicaria uma remoção seguida por adição e não apenas uma edição, o resultado do merge estaria incorreto. Em vez de apenas um conflito entre os conteúdos dos blocos, o bloco que foi adicionado deveria permanecer no arquivo final e um conflito entre a remoção e a edição do bloco que existia embasedeveria ser reportado, este tipo de conflito pode ser entendido conferindo a Figura 4.2.

3.3 Algoritmo proposto

Já o algoritmo proposto, baseia-se principalmente no nível de inserção do conteúdo de um bloco em outro. Porém, também utiliza a similaridade textual, calculada pela distância de Levenshtein, como nohandlerexistente. O pseudocódigo pode ser encontrado no Apêndice A.

Manter a similaridade é importante para casos em que a inserção é baixa, mas é possível ser ummatch. Por exemplo, se um bloco possui apenas uma linha e houve uma edição na mesma, o nível de inserção é 0%. Porém, se o nível de similaridade for alto, no caso de realmente ter sido apenas uma edição, então deve-se ter ummatch. Podemos ver um exemplo na Figura 3.3.

Figura 3.3: Exemplo de blocos que possuem baixo nível de inserção e alto nível de similaridade.

Neste exemplo, o nível de inserção é 0%, porém, a similaridade é alta. Sendo fácil de perceber que se trata do mesmo bloco, ou seja, um match. Pois, ambos os desenvolvedores estão querendo alterar o valor da mesma variável,dog.id, apenas utilizando diferentes atributos do objetoowner.

O algoritmo começa realizando a seleção de candidatos. Esta seleção é feita a partir da diferença dos conjuntos dos blocos contidos emleft,rightebase. Por exemplo, para a seleção dos candidatos à remoção deleft, é realizado o cálculo da diferençaBlocosBASE−BlocosLEFT. Essa diferença vai resultar em todos os blocos que estão em base, mas não estão em left, ou seja, podem ter sido removidos ou editados. Já para a seleção dos candidatos à adição deleft, é realizado o cálculo da diferençaBlocosLEFT−BlocosBASE, essa diferença vai resultar em todos os blocos que estão em left mas não estão embase. Ou seja, podem ter sido adicionados ou editados. Durante esses processos, para checar se um bloco está contido em um conjunto ou não, é verificada a igualdade.

(14)

14 CAPÍTULO 3 SOLUÇÃO

Após definição dos candidatos, os blocos precisam ser separados entre editados, adiciona- dos e removidos. Para cada bloco candidato à adição, blocos que estão supostamente apenas em left ou right é verificado o nível de inserção e similaridade do conteúdo desse bloco nos candidatos à remoção delefteright, respectivamente.

Para ser considerado um edição é necessário que o nível de inserção seja maior que 70%, o fator mais relevante neste algoritmo. Apenas se não for, é verificado se o nível de similaridade é maior que 50%. Estes valores foram definidos realizando testes seguido por análise manual subjetiva para classificar se houvematchentre os blocos esperados.

Se o nível de inserção está acima dos limiares, este bloco então é considerado uma edição e não uma adição. Então esse bloco é adicionado a uma estrutura de dados contendo o bloco editado e uma referência para o bloco original debase.

Quando esse processo de definição dos blocos que foram editados termina, removemos esses blocos dos conjuntos de blocos candidatos à adição e remoção. Assim possuímos os conjuntos com os blocos que foram adicionados, removidos e editados. De acordo com a classificação feita seguindo os limiares estabelecidos, podendo haver imprecisão na mesma o que leva a possíveis erros de classificação.

Possuindo os conjuntos de blocos editados, removidos e adicionados bem definidos, pode- mos agora iterar sobre os blocos que existiam embase. Verificamos para cada bloco se houve edição ou remoção. No caso de edição emleft ouright, em que o outro não editou o mesmo bloco, o resultado é trivialmente a edição, e o bloco que está na árvore terá seu conteúdo atua- lizado com o conteúdo da edição.

Já se tanto left, quantoright, editaram o bloco, realiza-se omergenão estruturado entre os conteúdos dos bloco. O resultado dessemergeserá colocado no conteúdo do bloco que está na árvore, podendo ser um conflito ou não.

Caso o bloco tenha sido removido por left ou right, é necessário checar se o outro fez edições no bloco, caso tenha feito, é necessário reportar um conflito e atualizar a árvore com o conflito gerado, caso não, o bloco é de fato removido da árvore. Como também, se tanto left, quantorightremoveu o bloco, o bloco também é removido da árvore.

No caso geral, a adição é realizada durante a superimposição dos nós. Porém, foi detectada a necessidade de uma checagem de dependência de ordem entre os blocos adicionados, trazida pelo novo algoritmo. Essa checagem é importante pois, apesar de em Java, como dito anteri- ormente, a ordem dos métodos não importar, o mesmo não se aplica a blocos de inicialização estáticos. Isso é fácil de entender, visto que se dois blocos inicializarem a mesma variável e es- tiverem em ordens diferentes, o valor com que a variável será inicializada será diferente, como no exemplo visto na Figura 2.1.

Assim, caso os blocos adicionados alterem os valores, essa verificação não tem como ser precisa, apenas se verifica se valores são atribuídos as mesmas variáveis. Ou se eles acessam as mesmas variáveis globais, e estes blocos não são idênticos, foi decidido sempre reportar um conflito.

O caso de tantoleft, quantorightadicionarem blocos idênticos, mesmo que difícil de ocor- rer, é verificado para que não haja duplicações. Caso aconteça, um dos blocos com conteúdo igual é removido da árvore.

Sempre reportar conflito para esses casos foi decidido mantendo uma abordagem conser-

(15)

3.4 IMPLEMENTAÇÃO 15

vadora, para evitar a adição de falsos negativos. Porém, correndo o risco de reportar falsos positivos, o que é menos prejudicial, visto que esses são mais fáceis de analisar e resolver [3].

3.4 Implementação

O algoritmo discutido na seção anterior foi implementado nohandler InitializationBlocksHan- dlerMultipleBlockse adicionado a ferramenta s3m, utilizando toda a infraestrutura já existente, como a definição dos nós porFSTNode, para nós não terminais, eFSTTerminal para nós ter- minais. Os blocos de inicialização estáticos são do tipo FSTTerminal, no qual podemos ter acesso ao corpo do bloco, e podem ser identificados dentro da lista de nósFSTNodeda árvore do programa através da anotaçãoInitializerDeclfeita nos nós deste tipo.

(16)

C

APÍTULO

4

Avaliação

A avaliação do novo algoritmo foi feita através de experimentos em projetos reais seguindo a metodologia descrita a seguir. A avaliação é um passo crucial neste trabalho devido as impre- cisões envolvidas nas classificações feitas e subjetividade envolvida.

Realizando os experimentos, obtivemos os resultados expostos nas seções seguintes, junto à análise detalhada de alguns dos cenários demergeem que oshandlersantigo e novo obtiveram resultados diferentes, mostrando como foi tomada a decisão de qual obteve o resultado correto.

4.1 Metodologia

Para avaliar o algoritmo proposto, realizamos experimentos utilizando como amostra 9 pro- jetos disponíveis publicamente no GitHub. Estes projetos foram selecionados pois sabia-se previamente conter blocos de inicialização estáticos, visto que apenas esses são do interesse deste trabalho. Em cada um desses projetos foi utilizado um minerador [3] que filtra apenas os commitsdemergenos projetos, estes totalizaram 30651 cenários.

A metodologia seguida foi a descrita a seguir: para cada cenário, foi avaliado se os arquivos envolvidos (base, left e right) continham blocos de inicialização estáticos, caso tivessem, a ferramenta realizava omergeentre os arquivos utilizando uma vez ohandlerantigo e uma vez ohandlernovo, caso não, o cenário era apenas descartado.

Nos cenários que foram realizados o mergeutilizando ohandlerantigo e o handlernovo, ao final de cada execução os resultados obtidos entre oshandlerseram comparados, caso fos- sem iguais, o cenário era apenas contabilizado. Caso fossem diferentes, os cenários além de contabilizados, tinham os tempos de execução medidos.

Para evitar erros na medição dos tempos, cada cenário foi executado 10 vezes e uma me- diana dos tempos de execução foi levada em consideração (os tempos de execução tinham variância significativa para ser levada em conta apenas o tempo médio).

Como também, os arquivos eram colocados em um novo diretório de experimentos para serem analisados manualmente posteriormente.

4.2 Resultados

Na Tabela 4.1 podemos observar os resultados obtidos separados por projeto realizando os experimentos descritos na seção anterior.

No total foram 1424 cenários demergeque envolvem arquivos que contêm blocos de inici- alização estáticos, representando 4,65% do total de cenários dos projetos.

Dos quais, 38 cenários tiveram resultados diferentes utilizando os diferenteshandlers, re- presentando 2,67% dos cenários que contêm blocos de inicialização estáticos e apenas 0,12%

do total de cenários avaliados.

(17)

4.2 RESULTADOS 17 Tabela 4.1: Resultados por projeto

Projeto # merge commits

# merge em arquivos contendo blocos de ini- cialização estáticos

# resultados diferentes obtidos entre handlers (%)

# acertos novo handler(%)

Activiti 1389 41 2 (4,88%) 2 (100,00%)

cgeo 2330 94 3 (3,19%) 3 (100,00%)

realm 2794 327 15 (4,59%) 15 (100,00%)

kotlin 630 35 0 (0,00%) 0 (0,00%)

Jenkins 4113 709 15 (2,12%) 10 (66,66%)

k-9 1101 46 2 (4,35%) 2 (100,00%)

voldemort 496 8 0 (0,00%) 0 (0,00%)

Osmand 8025 11 1 (9,09%) 1 (100,00%)

cassandra 9773 153 0 (0,00%) 0 (0,00%)

Total 30651 1424 (4,65%) 38 (2,67%) 33 (86,84%)

Os cenários em que os handlersobtiveram resultados diferentes foram o foco do estudo e serão discutidos na seção seguinte.

Na Figura 4.1, encontramos a mediana dos tempos de execução, medição feita entre as 10 execuções de cada um dos 38 cenários, por cenário demerge.

Figura 4.1: Mediana dos tempos de execução dos experimentos por cenário.

Desempenho é algo a ser levado em conta, já que seres humanos são impacientes, e o tempo de espera tende a reduzir a frequência com que estes comandos úteis são executados [9]. Como podemos ver na Figura 4.1, em geral, o novohandlerfoi mais lento em sua execução quando

(18)

18 CAPÍTULO 4 AVALIAÇÃO

comparado ao antigo, porém, o aumento não foi grande, alguns nanosegundos, a ponto de in- viabilizar o uso do novo algoritmo. Tentando sempre encontrar um equilíbrio entre precisão e desempenho, neste caso, uma taxa de acerto de 86,84% justifica o aumento em poucos nanose- gundos de tempo de execução.

4.3 Análise

Durante a análise manual dos 38 cenários em que os handlers se comportaram de maneira diferente, foi possível categoriza-los em 3 tipos, como descritos nos tópicos a seguir.

Para cada cenário foi avaliado se o resultado obtido com ohandlerantigo ou com o novo foi o correto. Esta análise foi feita de forma subjetiva, tentando entender o contexto do projeto e o resultado que deveria ser obtido intuitivamente. Em alguns casos, mais desafiadores, analisados por mais uma pessoa para tomada de decisão.

4.3.1 Bloco removido

Neste cenário,leftourightremoveu um dos blocos que existia embasee o outro alterou o bloco removido, ou fez alterações nas outras declarações da classe, mas não nos blocos estáticos.

Casos de remoção de um bloco sem alteração no outro arquivo (leftouright), devem trivi- almente resultar em um arquivo demergefinal que não contêm o bloco removido.

Figura 4.2: Conflito esperado entre remoção e edição do bloco.

Já no caso em que um leftourightalterou o bloco que existia embase, e o outro removeu

(19)

4.3 ANÁLISE 19

o mesmo, o comportamento esperado é que a ferramenta reporte um conflito entre a remoção e a edição, como no exemplo da Figura 4.2.

No handler antigo, o bloco removido era mantido pois o algoritmo existente não tratava o caso de remoção, quando a superimposição dos nós ocorria, o bloco removido era mantido porque estava no outro arquivo, com ou sem as edições feitas. Este handler só acertaria o resultado no caso de ambas as branches removerem o mesmo bloco.

A definição de blocos removidos no algoritmo novo trata este caso, forçando a remoção do nó na árvore ou atualizando o conteúdo do nó com o conflito devidamente reportado.

Em todos os cenários avaliados deste tipo o novohandleracertou. O resultado dohandler antigo era inadequado, pois, manter um bloco removido faz com que variáveis sejam iniciali- zadas com valores errados. Se utilizarmos o exemplo visto na Figura 2.1, podemos criar um cenário que o bloco destacado em verdefoi na removido, mas por um erro do algoritmo, foi mantido. Neste caso, a variável _name terá sido inicializada com o valorMaria, quando na verdade deveria ter sidoBob.

4.3.2 Bloco com baixa similaridade e alta inserção

Neste cenário os blocos contidos emleft eright possuem baixa similaridade com os debase.

Porém, possuem uma alta inserção. Podemos utilizar como exemplo para este caso os exemplos vistos nas Figuras 2.3 e 2.4 anteriormente no Capítulo 2.

Analisando este cenário atentamente, conseguimos perceber que o conteúdo do bloco de baseestá presente 100% no conteúdo do bloco deleft, como podemos ver em 4.3.

Figura 4.3: Intersecção entre os conteúdos dos blocos debaseeleft.

Apesar da similaridade entre os blocos ser baixa (61%), causada pela inserção de conteúdo, o mais provável é que trata-se sim de ummatch. Não temos garantir sem termos acompanhado

(20)

20 CAPÍTULO 4 AVALIAÇÃO

o trabalho do desenvolvedor, mas dificilmente, um bloco que tem inserção de 100% e esta representando grande parte do bloco final, não será ummatch.

Pelo fato de que a similaridade é baixa, o handler antigo considera que o bloco de left é um novo bloco, já que não existe nenhum matchcom os blocos de base. Logo, o resultado do mergecom o handler antigo contém 1 bloco a mais, o bloco que já existia embase mais o novo bloco (que na verdade foi apenas uma alteração do bloco de base). Pois, como dito anteriormente, durante a superimposição, se não ocorrematch, o bloco é considerado como um novo nó e vai ser adicionado a árvore.

A consequência desse comportamento dohandlerantigo é o arquivo final com o resultado domergeconter blocos que não deveriam estar contidos. Isto pode causar duplicação de exe- cução desnecessária do mesmo código. Como também, a depender da ordem que esses blocos tenham sido adicionados no arquivo final e das modificações feitas, pode resultar no mesmo erro descrito na seção anterior: variáveis sejam inicializadas com valores errados.

Com o novohandler, como a inserção também é levada em consideração durante o processo de definição de blocos editados, omatché realizado entre os blocos das Figuras 2.3 e 2.4, e o conteúdo do nó da árvore é atualizado com omergedos conteúdos desses blocos.

Em todos os cenários avaliados deste tipo o novohandleracertou. Não houveram casos no novohandlerem que o resultado domergecontinha mais blocos. Isto porque, osmatcheseram realizados entre os blocos devido a verificação da inserção e omergefeito entre os conteúdos, resultando em um só bloco no arquivo final.

4.3.3 Bloco com baixas similaridade e inserção

Neste cenário os blocos contidos emlefterightpossuem baixa similaridade com os debase, e diferentemente da seção anterior, estes possuem também uma baixa inserção, sendo um cenário bem mais desafiador.

Vamos utilizar como exemplo nesta seção, para melhor entendimento, os blocos nas Figuras 4.4 (base), 4.5 (left) e 4.6 (right), retirado do projeto Jenkins da classeJnlpSlaveAgentProto- col3.

Nohandlerantigo, como pode ser visto na Figura 4.7, mesmo que os blocos tenham baixa similaridade, existe um caso particular em que, caso tenha apenas 1 bloco em cada arquivo (left,baseeright) omatché feito sempre entre eles.

Nohandlernovo, como pode ser visto na Figura 4.8, o algoritmo entende queleftremoveu o bloco que tinha embase e adicionou um novo bloco, járight alterou o bloco que tinha em base, então, a árvore contém o novo bloco adicionado porlefte o conteúdo do nó que já existia embaseé atualizado com um conflito entre a remoção e alteração do bloco que existia embase feita porright.

Analisando cuidadosamente este exemplo é fácil perceber querightaltera o bloco debase, basicamente apenas removendo a conteúdo deelseda cláusulaif. Quando vamos fazer a mesma análise para left, não é tão simples perceber o que ocorreu, podemos ver que as variáveis lo- cais existentes anteriormente não existem mais, a condição da cláusula if foi alterada, tanto quanto o comando caso a condição seja verdadeira. Então, para definir se o que ocorreu foi uma edição ou uma remoção seguido por uma adição de um novo bloco, precisamos anali-

(21)

4.3 ANÁLISE 21

sar o contexto. Neste caso, a motivação da existência deste bloco é de inicializar a variável ENABLED, ou seja, por esse fato podemos perceber que em sua essência os blocos deleft e base fazem a mesma coisa, apenas de maneiras diferentes, logo, conceitualmente devem ser ummatch, independente dohandler, poisleftapenas editou o bloco debase.

Então, para o exemplo visto, um conflito é reportado entre os conteúdos dos blocos que foram alterados. O handler que consegue reproduzir o comportamento correto é o antigo, seguindo nossa análise anterior de que tantoleftquantorightalteraram o bloco debase.

Logo, para este caso e similares, consideramos que o handler antigo acertou o resultado do merge. Porém, caso os arquivos possuíssem mais de um bloco, algo parecido com o que ocorre no novohandlerocorreria, como a similaridade é baixa com o bloco debase, o bloco é entendido como novo, e o arquivo final ia possuir as duas versões do bloco, a que já existia em basee a editada.

Figura 4.4: Bloco original embase.

Figura 4.5: Bloco emleft.

Figura 4.6: Bloco emright.

(22)

22 CAPÍTULO 4 AVALIAÇÃO

Figura 4.7: Resultado obtido pelohandlerantigo.

Figura 4.8: Resultado obtido pelohandlernovo.

(23)

C

APÍTULO

5

Trabalhos relacionados e Riscos à validade

Existem diversos trabalhos tentando melhorar cada vez mais as técnicas de ferramentas de merge, visto que é um comando que ocorre muito frequentemente [9] e a resolução de conflitos é o principal desafio das ferramentas demerge[10]. Entre 22,75% e 46,62% de todos osmerges em quatro grandes projetos apresentam conflitos [11]. Além disso, essas ferramentas enfrentam o grande desafio de encontrar um equilíbrio entre precisão e desempenho [5].

Essas técnicas vêm sendo estudadas, por exemplo, por Mens [1] que analisou o estado da arte das operações demerge. Destacando várias das opções demergesdisponíveis na literatura.

Incluindo técnicas comomergesemântico emergeestruturado.

Uma das técnicas que busca essas melhorias é a de mergesemiestruturado, um protótipo de uma ferramenta semiestruturada, FSTMerge, foi proposta por Apel et al [2]. FSTMerge foi aperfeiçoada por Guilherme et al [3], que desenvolveram uma nova ferramenta chamada s3m, e serviu como base para o estudo presente.

Na ferramenta s3m, trata-se o cenário de mergeentre blocos de inicialização estáticos em um doshandlers, o InitializationBlocksHandler. Este utiliza a similaridade textual como base para realizar omatchentre os blocos, para assim, então, realizar omerge.

Porém, essa abordagem não foi suficiente para realizar o merge corretamente em alguns cenários. Então um novo algoritmo foi proposto, utilizando, além da similaridade, o nível de inserção. Implementado nohandler InitializationBlocksHandlerMultipleBlockse adicionado a ferramenta s3m.

Vimos em detalhes no Capítulo 4 uma comparação entre os resultados obtidos utilizando os diferenteshandlerse também as melhorias e falhas de cada um. Apesar de o novohandlernão ter acertado em todos os cenários demergeavaliados em que os resultados foram diferentes, a taxa de acerto foi alta, de 86,84%, errando em apenas uma das categorias vistas, blocos com baixas similaridade e inserção, em que foi definido que ohandler antigo acertou, mas como discutido anteriormente, também erraria para cenários mais complexos, envolvendo múltiplos blocos.

Os riscos à validade deste estudo são principalmente relativos ao fato de que cada projeto tem um estilo, não existe um padrão universal, que garanta que caso o algoritmo obtenha bons resultados para um conjunto de projetos irá obter para qualquer projeto. Pode ser que os re- sultados obtidos neste trabalho não façam sentido no contexto de um outro projeto específico.

Para exemplificar, cenários da categoriabloco com baixas similaridade e inserção, discutida na subseção 4.3.3 só foram encontrados no projeto avaliadoJenkins.

Outro risco à validade deste, é a análise manual feita nos casos em que o handler antigo e novo obtiveram resultados diferentes. Para cada um desses casos, coube a uma avaliação subjetiva para decidir qualhandleracertou. Alguns cenários, como o discutido na seção 4.3.3, foram avaliados por mais de uma pessoa para chegar a uma conclusão. Mas, mesmo assim, para ter certeza absoluta de qual é o resultado esperado, apenas perguntando aos desenvolvedores que entendem do contexto e requisitos do projeto.

(24)

C

APÍTULO

6

Conclusão

Neste trabalho foi proposto um novo algoritmo para realizar ummergemais preciso entre blo- cos de inicialização estáticos para uma ferramenta de merge semiestruturado. O mesmo foi implementado e adicionado a uma ferramenta já existente, em que foi possível realizar experi- mentos em projetos do mundo real para avaliar o real impacto da nova solução.

A maior dificuldade para realizar o mergeentre esses blocos é o fato deles não possuírem um identificador, dificultado o matchentre os blocos para assim então realizar omerge entre os blocos corretos. Ohandler já existente na ferramenta realizava essematchatravés do nível de similaridade textual entre os blocos, mas vimos que essa abordagem não era suficiente em alguns casos para realizar omerge corretamente. O novo algoritmo se baseia principalmente no nível de inserção do conteúdo de um bloco em outro para definir se os blocos são ummatch ou não.

Após analisar os resultados dos experimentos, foi possível concluir que houve melhora na precisão com que omergeentre blocos de inicialização estáticos é realizado adicionando o conhecimento relativo ao nível de inserção de conteúdo, além da similaridade. E que uma piora nos tempos de execução foi detectado, mas não é significativo, ou seja, ainda assim justificando a utilização da nova implementação.

Porém, apenas 4,65% dos cenários demergeavaliados contêm blocos de inicialização es- táticos, em que, dos quais, apenas 2,67% o handlerque implementa o novo algoritmo obteve resultados diferentes do que já existia e que o novohandleracertou em 86,64% desses. E como podemos ver na Tabela 4.1, os resultados em que oshandlersse comportaram de maneira dife- rente variam consideravelmente de projeto para projeto.

Conclui-se então que a solução proposta é válida para a amostra e traz melhorias na ferra- menta. Mas o impacto da solução é relativo a algumas características de cada projeto, como, por exemplo, a quantidade de blocos de inicialização estáticos sendo alterados em paralelo.

Podemos concluir também que investir tempo e esforço na melhoria de outros módulos da fer- ramenta é um caminho a ser seguido, entendendo melhor os padrões de desenvolvimento da linguagem e trabalhando em módulos que tenham grande impacto na precisão do merge da ferramenta para justificar a utilização na indústria.

(25)

Bibliografia

[1] T. Mens, "A State-of-the-Art Survey on Software Merging", IEEE Trans. Software Eng., vol. 28, no. 5, pp. 449-462, May 2002.

[2] S. Apel, J. Liebig, B. Brandl, C. Lengauer, and C. Kastner, “Semistructured merge:

Rethinking merge in revision control systems”. In: Proceedings of the 19th ACM SIG- SOFT Symposium and the 13th European Conference on Foundations of Software Engi- neering, ser. ESEC/FSE ’11. ACM, 2011, pp. 190–200.

[3] Guilherme Cavalcanti, Paulo Borba, and Paola Accioly. 2017. "Evaluating and Improving Semistructured Merge". In: Proc. ACM Program. Lang. 1, OOPSLA, Article 59 (October 2017), 27 pages. https://doi.org/10.1145/3133883.

[4] Sven Apel and Christian Lengauer. 2008. "Superimposition: A Language-independent Approach to Software Composition". In: Proceedings of the 7th International Conference on Software Composition (SC’08). Springer-Verlag.

[5] Sven Apel, Olaf Lessenich, and Christian Lengauer. 2012. "Structured Merge with Auto- tuning: Balancing Precision and Performance". In: Proceedings of the 27th IEEE/ACM International Conference on Automated Software Engineering (ASE’12). ACM.

[6] Guilherme Cavalcanti, Paola Accioly, and Paulo Borba. Oct. 2015. “Assessing Semistruc- tured Merge in Version Control Systems: A Replicated Experiment”. In: Proceedings of the 9th International Symposium on Empirical Software Engineering and Measurement (ESEM’15).ACM.

[7] Sven Apel, Jörg Liebig, Christian Lengauer, Christian Kästner and William Cook. 2010.

"Semistructured Merge in Revision Control Systems"In: Proceedings of the Fourth Inter- national Workshop on Variability Modelling of Software-intensive Systems (VaMoS) [8] Andres Löh, Wouter Swierstra, and Daan Leijen. "A principled approach to version con-

trol."(FASE) 2007.

[9] R. Conradi and B. Westfechtel, “Version Models for Software Configuration Manage- ment,” ACM Computing Surveys (CSUR), vol. 30, no. 2, pp. 232–282, 1998.

[10] Fengmin Zhu and Fei He. 2018. "Conflict Resolution for Structured Merge via Version Space Algebra". Proc. ACM Program. Lang. 2, OOPSLA, Article 166 (November 2018), 25 pages. https://doi.org/10.1145/3276536

[11] T. Zimmermann. 2007. "Mining Workspace Updates in CVS". In Fourth International Workshop on Mining Software Repositories (MSR’07:ICSE Workshops 2007). 11´s11.

https://doi.org/10.1109/MSR.2007.22

(26)

A

PÊNDICE

A

Pseudocódigo do algoritmo proposto

Figura A.1: Pseudocódigo do algoritmo proposto.

Referências

Documentos relacionados

Oficial de Registro de Imóveis, Civil de Pessoa Jurídica e de Títulos e Documentos Comarca de Mogi das Cruzes - Estado de São Paulo. CNS nu

Deve conhecer perfeitamente este Manual de Procedimentos ou “Bússola”, e o papel de cada ministério da Equipe de Serviço; assim como o Esquema do Curso

Podem treinar tropas (fornecidas pelo cliente) ou levá-las para combate. Geralmente, organizam-se de forma ad-hoc, que respondem a solicitações de Estados; 2)

11 – O Município de Alcanena, que tem como imagem de marca “Alcanena, Capital da Pele”, concentra no seu território, mais de 90 % das indústrias de

Entre os escavadores modernos, tocas simples, com Martin (2009) descreveu tocas do Grupo pouca inclinação, terminando em uma câmara, são Otway (Albiano) da Austrália e as

Varr edura TCP Window ( cont inuação) ACK- win manipulado Não Responde ACK- win manipulado ICMP Tipo 3 Firewall Negando Firewall Rejeitando Scanner de Porta... Var r edur a FI N/

Com o Selo 2013-2016, o UNICEF inicia um novo ciclo de trabalho com os municípios do Semiárido, com a proposta de fomentar a implementação de um conjunto de Ações Estratégicas

Concentração de determinada substância, acima da qual podem ocorrer alterações prejudiciais à qualidade do solo e da água subterrânea VALOR DE PREVENÇÃO -