Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema...

35
CENTRO UNIVERSITÁRIO CESMAC CURSO DE PÓS-GRADUAÇÃO “LATO SENSU” ENGENHARIA DE SOFTWARE MELHORANDO A QUALIDADE DO CÓDIGO COM A TÉCNICA DE REFATORAÇÃO: estudo de caso em um sistema legado Java Anderson Lemos Camelo Maceió/AL 2013

description

Este artigo mostra como a técnica de refatoração pode ser empregada para melhorar a qualidade de código de sistema legado desenvolvido em Java. Serão mostrados todos os passos da metodologia necessários para aplicação da refatoração com segurança. Também será feita uma exploração do sistema legado com o intuito de identificar os principais trechos de código ruim e a melhor estratégia para transformá-lo em um código limpo. Ao fim da discussão, serão levantados vários dados estatísticos do sistema legado, antes e depois da refatoração, para mensurar os ganhos de qualidade de código advindos do uso desta técnica.

Transcript of Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema...

Page 1: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

CENTRO UNIVERSITÁRIO CESMAC CURSO DE PÓS-GRADUAÇÃO “LATO SENSU”

ENGENHARIA DE SOFTWARE

MELHORANDO A QUALIDADE DO CÓDIGO COM A

TÉCNICA DE REFATORAÇÃO: estudo de caso em um sistema legado Java

Anderson Lemos Camelo

Maceió/AL

2013

Page 2: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

Anderson Lemos Camelo

MELHORANDO A QUALIDADE DO CÓDIGO COM A

TÉCNICA DE REFATORAÇÃO: estudo de caso em um sistema legado Java

Maceió/AL

2013

Page 3: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

Anderson Lemos Camelo

MELHORANDO A QUALIDADE DO CÓDIGO COM A

TÉCNICA DE REFATORAÇÃO: estudo de caso em um sistema legado Java

Artigo apresentado ao Centro

Universitário Cesmac como parte dos

requisitos para a obtenção do título de

Especialista em Engenharia de Software,

sob a orientação do Prof. Me. Adilson

Jorge dos Santos.

Maceió/AL

2013

Page 4: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

Anderson Lemos Camelo

MELHORANDO A QUALIDADE DO CÓDIGO COM A

TÉCNICA DE REFATORAÇÃO: estudo de caso em um sistema legado Java

Aprovado em 30 de setembro de 2013

__________________________________________

Prof. Me. Adilson Jorge dos Santos

- Orientador -

Maceió/AL

2013

Page 5: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

AGRADECIMENTOS

Agradeço, primeiramente, a Deus por sempre se colocar como uma ponte para que eu

pudesse transpor as águas agitadas do caminho pelo qual trilhei.

Agradeço a minha família pelo amor e cumplicidade durante todos os momentos de

minha vida.

Agradeço ao professor Adilson Santos, meu orientador, por incentivar o

desenvolvimento do tema escolhido e colaborar com a conclusão deste trabalho.

Por último, mas não menos importante, agradeço a todas as pessoas que duvidaram da

minha capacidade e colocaram meu talento a prova.

Page 6: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

“Tudo que está no plano da realidade já foi sonho

um dia.”

Leonardo da Vinci

Page 7: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

SUMÁRIO

1 INTRODUÇÃO ........................................................................................... 1

2 FUNDAMENTAÇÃO TEÓRICA ............................................................... 3

2.1 REFATORAÇÃO ........................................................................................ 3

2.2 CÓDIGO LIMPO ......................................................................................... 4

2.3 ODORES DE CÓDIGO ............................................................................... 5

2.3.1 CÓDIGO DUPLICADO .............................................................................. 5

2.3.2 MÉTODO LONGO ...................................................................................... 6

2.3.3 CLASSE GRANDE ..................................................................................... 6

2.3.4 LISTA DE PARAMETROS LONGA ......................................................... 7

2.3.5 INVEJA DE DADOS ................................................................................... 7

2.3.6 COMENTÁRIOS ......................................................................................... 9

2.3.7 PROPÓSITO OBSCURO ............................................................................ 9

2.4 PROJETO SIMPLES ................................................................................... 11

2.5 MÉTRICAS DE CÓDIGO FONTE ............................................................. 12

3 METODOLOGIA ........................................................................................ 13

4 RESULTADOS E DISCUSSÃO ................................................................. 14

4.1 ARQUITETURA DO SISTEMA REVERSI ............................................... 14

4.2 REFATORAÇÃO DO SISTEMA REVERSI .............................................. 15

4.2.1 PORQUE REFATORAR ............................................................................. 15

4.2.2 O PRIMEIRO PASSO DA REFATORAÇÃO ............................................ 16

4.2.3 O PROCESSO DE REFATORAÇÃO ......................................................... 18

4.2.4 QUANDO PARAR DE REFATORAR ....................................................... 23

4.3 MÉTRICAS DO SISTEMA REVERSI ....................................................... 24

5 CONCLUSÃO ............................................................................................. 26

REFERÊNCIAS ........................................................................................................ 26

Page 8: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

LISTA DE ILUSTRAÇÕES

Figura 1 - Exemplo de refatoração de uma lista de parâmetros longa ....................... 7

Figura 2 - Exemplo de refatoração de um código “acidente de trem” ....................... 8

Figura 3 - Exemplo de inveja de dados que não viola a Lei de Demeter .................. 9

Figura 4 - Exemplo de código com propósito obscuro .............................................. 10

Figura 5 - Exemplo de código legível ........................................................................ 11

Figura 6 - Diagrama de pacotes do Reversi ............................................................... 15

Figura 7 - Particionamento de equivalência para o Reversi ....................................... 16

Figura 8 - Conjunto de testes automáticos do Reversi ............................................... 17

Figura 9 - Método buscaJogadaComputador com vários odores ............................. 19

Figura 10 - Refatoração do antigo método buscaJogadaComputador ...................... 19

Figura 11 - Método de fábrica obterComputador ...................................................... 20

Figura 12 - Inveja de dados do objeto objControle ................................................... 20

Figura 13 - Responsabilidade reposicionada na classe ControladorDoJogo ............ 21

Figura 14 - Código “Acidente de trem” ao chamar método getMatPedrasTabuleiro 21

Figura 15 - Refatoração do Acidente de Trem do método getMatPedrasTabuleiro . 22

Figura 16 - Muitas linhas de código no método executaJogada ............................... 23

Figura 17 - Refatoração do método executaJogada .................................................. 23

Figura 18 - Métricas do projeto Reversi .................................................................... 25

Page 9: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

1

MELHORANDO A QUALIDADE DO CÓDIGO COM A TÉCNICA DE

REFATORAÇÃO: ESTUDO DE CASO EM UM SISTEMA LEGADO JAVA

Anderson Lemos Camelo

Adilson Jorge dos Santos (Orientador)

RESUMO: Este artigo mostra como a técnica de refatoração pode ser empregada para melhorar a

qualidade de código de sistema legado desenvolvido em Java. Serão mostrados todos os passos da

metodologia necessários para aplicação da refatoração com segurança. Também será feita uma

exploração do sistema legado com o intuito de identificar os principais trechos de código ruim e a

melhor estratégia para transformá-lo em um código limpo. Ao fim da discussão, serão levantados vários

dados estatísticos do sistema legado, antes e depois da refatoração, para mensurar os ganhos de

qualidade de código advindos do uso desta técnica.

PALAVRAS-CHAVES: Refatoração; Código Legado; Linguagem de Programação Java; Código

Limpo; Testes Automatizados.

ABSTRACT: This article aims to show how the refactoring technique can be used to improve the

quality of a legacy code in a system developed in Java. We will show all the methodology steps needed to

safely implement the refactoring. Also there will be an exploration of the legacy system in order to

identify key pieces of bad code and the best strategy to turn them into clean code. At the end of the

discussion, we will gather statistical data from the legacy system, before and after refactoring, to

measure the improvement in code quality from the use of this technique.

KEYWORDS: Refactoring; Legacy Code; Java Programming Language; Clean Code; Automated

Testing.

1 INTRODUÇÃO

Quando a aplicação da tecnologia de objetos, e particularmente à linguagem de

programação Java, se tornou corriqueira, um novo problema surgiu para a comunidade

de software. Um número significativo de programas pobremente projetados, criados por

desenvolvedores menos experientes e que faziam uso de metodologias consideradas

Page 10: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

2

antiquadas, resultavam em aplicações ineficientes e difíceis de manter e estender. Os

profissionais de desenvolvimento de sistemas acabaram descobrindo como é difícil

trabalhar com aplicações “não-ideais” herdadas ou legadas (FOWLER et al., 2004).

Segundo Feathers (2004), o conceito de sistemas de software legados não se

restringe apenas aos sistemas que possuem muito tempo de vida, continuam em

produção e se mantém em uso, mas principalmente aos sistemas desenvolvidos

recentemente e que apresentam problemas de qualidade que podem impedir sua

evolução ou até gerar erros graves após uma simples manutenção. Normalmente estes

sistemas não podem ser substituídos por diversas razões, o que os tornam caros quanto à

manutenção e trazem muitos riscos no momento de sua evolução.

Devido a estes problemas torna-se necessário melhorar a qualidade desses

sistemas legados podendo ser uma forma interessante de mantê-los ativos, tornando-os

mais uma vez produtivos e permitindo que melhorias e evoluções sejam efetuadas com

menos riscos. Consequentemente é gerado uma maior confiabilidade e segurança a cada

evolução que se faça necessária. O incremento de novas funcionalidades nos sistemas

legados com maior qualidade permite que a empresa tenha vantagens competitivas sem

grandes investimentos de novos desenvolvimentos, gerando lucros, permitindo também

a integração com novos sistemas (SARTORELLI, 2007). Logo, para melhorar a

integridade estrutural e o desempenho destes sistemas é necessário recorrer a técnica de

refatoração.

A refatoração foi inicialmente concebida nos círculos de Smalltalk, mas não

demorou muito a encontrar o seu caminho em outras linguagens de programação.

Devido ao fato de refatoração ser essencial ao desenvolvimento de frameworks, o termo

vem à tona rapidamente quando desenvolvedores de frameworks falam sobre seu

trabalho. Ele surge quando eles refinam suas hierarquias de classes e quando se

empolgam com o número de linhas de código que conseguiram apagar.

Desenvolvedores de frameworks sabem que um framework não estará pronto na

primeira tentativa - ele deve evoluir à medida em que eles ganham experiência. Eles

também sabem que o código será lido e modificado mais frequentemente do que será

escrito. A chave para manter o código legível e modificável é refatorar - para

frameworks, em particular, ou para qualquer outro software, de maneira geral

(FOWLER et al., 2004).

Page 11: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

3

No entanto, o processo de refatorar requer alterações no código em

funcionamento que podem introduzir falhas sutis. A refatoração, se não for feita

apropriadamente, pode atrasar o projeto em dias, ou até mesmo semanas. E a

refatoração se torna mais arriscada ainda quando praticada informalmente e sem seguir

nenhuma metodologia aceita. O programador começa a alterar o código. Logo descobre

novas oportunidades de mudanças, e altera ainda mais o código. Quanto mais ele

trabalha, mais coisas aparecem e mais alterações são feitas (FOWLER et al., 2004). No

final,o programador não consegue mensurar o impacto das mudanças realizadas no

funcionamento do sistema. Para evitar este cenário de incerteza, a refatoração deve ser

feita sistematicamente.

O objetivo deste trabalho é apresentar a técnica de refatoração sob uma

perspectiva simples e prática, visando melhorar a qualidade de código de um sistema

legado de forma evolutiva e garantindo segurança durante o processo de manutenção.

Será mostrado como aplicar os principais passos da metodologia e as melhores

estratégias para transformar um código ruim em um código bom, utilizando como

estudo de caso o sistema legado Reversi, desenvolvido na linguagem Java.

2 FUNDAMENTAÇÃO TEÓRICA

Nesta seção será apresentada a fundamentação teórica levantada sobre os

principais conceitos necessários para o estudo deste trabalho. Será abordada uma breve

explanação sobre refatoração, código limpo, odores de código, projeto simples e

métricas de código fonte.

2.1 REFATORAÇÃO

Refatoração é o processo de alteração de um sistema de software de modo que o

comportamento externo do código não mude, mas que sua estrutura interna seja

melhorada. É uma maneira disciplinada de aperfeiçoar o código que minimiza a chance

de introdução de falhas. Em essência, quando se usa refatoração, está se melhorando o

projeto do código após este ter sido escrito (FOWLER et al., 2004).

O uso da técnica de refatoração aprimora o design de um software e evita a

deterioração tão comum durante o ciclo de vida de um código. Esta deterioração é

Page 12: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

4

geralmente causada por mudanças com objetivos de curto prazo ou por alterações

realizadas sem a clara compreensão da concepção do sistema (WIKIPÉDIA, 2013a).

Com a refatoração, descobre-se que o ponto de equilíbrio do trabalho muda.

Descobre-se que o projeto, em vez de acontecer todo no inicio, ocorre continuamente

durante o desenvolvimento. Aprende-se, com a construção do sistema, a como melhorar

o projeto. A interação resultante leva a um programa que permanece bom à medida em

que o desenvolvimento continua (FOWLER et al., 2004).

Segundo Fowler et al. (2004), é desejado que os programas que sejam fáceis de

ler, que tenham toda sua lógica especificada em um e apenas um lugar, que não

permitam que as alterações arrisquem o comportamento preexistente e que permitam

que lógica condicional seja expressa da forma mais simples possível. Logo, refatorar é

processo de pegar um programa em produção e agregar a ele valor, não por meio da

alteração de seu comportamento, mas dando a ele mais destas qualidades que nos

permitem continuar desenvolvendo rapidamente.

Durante a fase de refatoração, pode-se aplicar qualquer conceito sobre um bom

projeto de software. Pode-se aumentar a coesão, diminuir o acoplamento, separar

preocupações, modularizar as preocupações do sistema, reduzir o tamanho das classes e

funções, escolher nomes melhores, além de poder remover a duplicação, garantir a

expressividade do código e minimizar o número de classes e métodos (MARTIN,

2009).

2.2 CÓDIGO LIMPO

A definição de um bom código não é precisa. Do mesmo modo que enfrenta-se

dificuldades para definir o que é arte, não se pode definir um conjunto de parâmetros

lógicos e mensuráveis para delimitar a diferença de qualidade entre códigos-fonte. Pode-

se considerar aspectos como testabilidade, eficiência, facilidade de modificação, processo

pelo o qual foi desenvolvido, entre outros.

No livro Clean Code (MARTIN, 2009), o autor entrevistou grandes especialistas

em desenvolvimento de software como Ward Cunningham (colaborador na criação do

Fit, do Wiki e da Programação Extrema (BECK, 1999)) e Dave Thomas (fundador da

OTI - Object Technology International - e muito envolvido no Projeto Eclipse)

questionando-os quanto a uma definição para código limpo. Cada um dos entrevistados

Page 13: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

5

elaborou respostas diferentes, destacando características subjetivas, como elegância,

facilidade de alteração e simplicidade, e outras puramente técnicas, incluindo a falta de

duplicações, presença de testes de unidade e de aceitação e a minimização do número de

entidades (ALMEIDA; MIRANDA, 2010).

Em certo sentido, um código limpo está inserido em um estilo de programação

que busca a proximidade a três valores: expressividade, simplicidade e flexibilidade. Tais

termos são utilizados por Kent Beck no livro Implementation Patterns (BECK, 2007)

que estão em conformidade com a unidade de pensamento que permeia as respostas dos

especialistas (ALMEIDA; MIRANDA, 2010).

2.3 ODORES DE CÓDIGO

Segundo a Wikipédia (2013b), odores de código (do inglês bad smell) é qualquer

sintoma no código fonte de um programa que possivelmente indique sérios problemas

em sua concepção. Geralmente não são erros - eles não são códigos tecnicamente

incorretos e não impedem o correto funcionamento do programa. Em fez disto, eles

indicam deficiências no projeto que podem vir a atrasar o desenvolvimento ou aumentar

o risco de bugs e falhas no futuro. Odores de código são heurísticas para indicar quando

refatorar, e quais as técnicas específicas de refatoração devem ser usadas.

A seguir, será feita uma breve explanação sobre os odores de código mais

comuns: código duplicado, método longo, classes grandes, lista de parâmetros longa,

inveja de dados, comentários e propósito obscuro de variáveis e métodos.

2.3.1 CÓDIGO DUPLICADO

Como o próprio nome diz, código duplicado é, simplesmente, o mesmo trecho

de código repetido em vários outros lugares como classes e métodos. É considerado o

pior odor de um código, pois quando a lógica do trecho duplicado muda, é necessário

alterá-la em diversos pontos sistema. Segundo Martin (2009), autores como Dave

Thomas e Andy Hunt o chamaram de princípio do Não Se Repita (do inglês DRY -

Don't Repeat Yourself), enquanto Kent Beck o tornou como o centro dos princípios da

eXtreme Programming (XP) e o chamou de “Uma vez, e apenas uma”.

A forma mais obvia de duplicação é quando você possui blocos de código

idênticos, como se alguns programadores tivessem saído copiando e colando o mesmo

Page 14: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

6

código várias vezes. Nestes casos, deve-se substituir estes trechos por métodos. Uma

das formas mais simples de duplicação são as estruturas aninhadas de switch/case e

if/else que aparecem repedidas vezes em diversos módulos, sempre testando as mesmas

condições. Neste caso, deve-se substituir pelo polimorfismo (MARTIN, 2009).

2.3.2 MÉTODO LONGO

O odor de método longo consiste em métodos que comportam grandes trechos

de códigos, geralmente realizam mais de uma ação, atuam em vários níveis de

abstração, contém um número elevado estruturas condicionais e laços de repetição

aninhados, é narrado por meio de comentários de código, entre outras coisas.

Segundo Almeida e Miranda (2010), o ideal é que cada método seja pequeno o

suficiente para facilitar sua leitura e compreensão. Deve-se ter em vista a dificuldade de

assimilação de grandes porções de informação durante a leitura e o fato de que nem

sempre uma instrução é clara. A partir dessas idéias, um método será uma porção curta

de código que trabalha com poucas variáveis e tem um nome explicativo que espelha a

sua funcionalidade.

Segundo Fowler et al. (2004), uma boa técnica para decompor métodos longos é

olhar para seus comentários. Um bloco de código com um comentário que lhe diz o que

ele faz pode ser substituído por um método cujo nome seja baseado no comentário.

Além deste, expressões condicionais, condições e laços também podem ser

decompostos em métodos menores.

2.3.3 CLASSE GRANDE

De maneira análoga, o odor de classe grande apresenta as mesmas deficiências

de design de código que o odor de método longo. Logo, do mesmo modo que considera-

se importante limitar a quantidade de informação que um método transmite ao leitor,

quer-se que as classes sejam o menor possível. Além de facilitar a leitura e

entendimento, programar buscando minimizar o tamanho das classes leva-se a criar

unidades coesas e a evitar duplicações.

Segundo Fowler et al. (2004), o tamanho de uma classe deve ser definido através

do Principio da Responsabilidade Única (do inglês SPR - Single Responsability

Page 15: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

7

Principle). Este principio afirma que uma classe ou módulo deve ter apenas uma

responsabilidade e apenas um motivo para mudar.

2.3.4 LISTA DE PARAMETROS LONGA

O número de argumentos de um método se torna bastante importante quando se

quer métodos pequenos e com apenas uma tarefa. Se um método recebe muitos

argumentos, provavelmente os utiliza para um conjunto de operações e não uma

somente.

Listas de parâmetros longas são difíceis de entender, porque se tornam

inconsistentes e difíceis de usar e porque você irá sempre alterá-las à medida que

precisar de mais dados. A maioria das alterações é removida passando-se objetos,

porque é muito mais provável que você precise fazer apenas algumas solicitações para

chegar em um novo dado (FOWLER et al., 2004).

Figura 1 - Exemplo de refatoração de uma lista de parâmetros longa

Fonte: Autoria própria, baseada em Martin (2009)

2.3.5 INVEJA DE DADOS

Segundo Martin(2009), os métodos de uma classe devem ficar interessados

apenas nas variáveis e funções da classe a qual eles pertencem, e não nas de outras

classes. Quando um método usa métodos de acesso e de alteração de algum outro objeto

para manipular os dados dentro deste objeto, o método inveja o escopo da classe

daquele outro objeto. Ele queria estar dentro daquela outra classe de modo que pudesse

ter acesso direto às variáveis que está manipulando. É o que chamamos inveja de dados

(do inglês, Feature Envy), um dos odores mais comuns em códigos que apresentam

problemas na divisão de responsabilidades entre as classes e alto acoplamento.

Page 16: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

8

Um exemplo clássico deste odor é o código conhecido como “acidente de trem”

(do inglês, train wreck), onde uma série de métodos do getters são chamadas de forma

encadeada, como os vagões de um trem.

Figura 2 - Exemplo de refatoração de um código “acidente de trem”

Fonte: Autoria própria, baseada em Freeman e Pryce (2012)

O acidente de trem é uma violação clássica do estilo “Diga, Não Pergunte” (do

inglês, Tell, Don’t Ask) ou mais formalmente, Lei de Demeter (do inglês, The Law of

Demeter). Segundo Almeida e Miranda (2010), esta lei diz que um método “M” de uma

classe “C” só deveria chamar um método:

da própria classe;

de um objeto criado por M;

de um objeto passado como argumento para M;

de um objeto guardado em uma variável de instância de C.

Seguido consistentemente, este estilo produz código mais flexível, porque ele é

mais fácil de trocar objetos que executam o mesmo papel. O chamador não vê nada da

estrutura interna deles ou da estrutura do resto do sistema que está por trás da interface

do papel do objeto chamado. Além disto, ele força a tornar explícitas e então nomear as

interações entre os objetos, ao invés de deixá-las implícitas na cadeia de getters

(FREEMAN; PRYCE, 2012).

No entanto, existem alguns casos onde um método mesmo sem violar a Lei de

Demeter, tem um grande acoplamento com outra classe. O exemplo da figura 3 não viola

esta, pois faz chamadas somente a métodos de um objeto que lhe foi passado por

parâmetro. Como se pode-se ver, o método salarioDoMes possui um grande

Page 17: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

9

acoplamento com a classe Empregado ao utilizar diversos de seus métodos, de forma que

fica caracterizado uma inveja de dados.

Figura 3 - Exemplo de inveja de dados que não viola a Lei de Demeter

Fonte: (ALMEIDA; MIRANDA, 2010)

2.3.6 COMENTÁRIOS

Um dos odores mais polêmicos é o de comentários. Na verdade, um comentário

bem feito será sempre bem vindo. No entanto, segundo Fowler et al. (2004), é

surpreendente a frequência com que se veem códigos cheios de comentários e percebe-se

que eles estão lá porque os códigos são ruins. Neste contexto, os comentários são

utilizados como desodorante de código que cheira mal.

Segundo Martin (2009), os comentários tendem a mentir para os leitores do

código onde eles foram fixados. Nem sempre, e não intencionalmente, mas é muito

comum. Quanto mais antigo um comentário for e quanto mais longe ele estiver do

código o qual ele descreve, mais provável será que esteja errado. O motivo é simples: é

pouco provável que os programadores consigam mantê-los atualizados.

Segundo Fowler et al. (2004), uma boa heurística para evitar o mal uso de

comentários: sempre que se sentir necessidade de escrever um comentário, deve-se

experimentar primeiro tornar o trecho de código mais legível de modo que qualquer

comentário se torne supérfluo.

1.3.7. PROPÓSITO OBSCURO

Segundo Boswell e Foucher (2009), códigos devem ser escritos de modo a

minimizar o tempo necessário para sua compreensão. É o chamado Teorema

Fundamental da Legibilidade. Segundo Martin (2009), nomes em softwares são 90%

responsáveis pela legibilidade do mesmo. Precisa-se tomar seu tempo para escolhê-los

Page 18: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

10

sabiamente e mantê-los relevantes. Nomes são muito importantes para serem tratados de

qualquer jeito.

Chama-se de propósito obscuro (do inglês, Obscured Intent), um conjunto de

pequenos odores que degradam a legibilidade do código fonte, principalmente, no que

se refere a nomes de variáveis e métodos que não revelam seu propósito facilmente,

como por exemplo, códigos que apresentam os “números mágicos”, ou seja, números

cujo significado não está claro; como também a notação Húngara, que consiste em

nomear as variáveis com o prefixos que demonstram o seu tipo.

Um bom exemplo de código com propósito obscuro é o mostrado na figura 4. É

bem provável que um desenvolvedor perca bastante tempo para conseguir entender a

lógica contida neste método. Isto, simplesmente, porque o desenvolvedor não se

esforçou para nomear as variáveis de forma clara.

Figura 4 - Exemplo de código com propósito obscuro

Fonte: (MARTIN, 2009)

Por outro lado, o código exibido na figura 5 foi escrito de uma forma bem mais

legível. Fica claro a intenção do desenvolvedor em calcular a pontuação de uma partida

de boliche.

Page 19: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

11

Figura 5 - Exemplo de código legível

Fonte: (MARTIN, 2009)

2.4 PROJETO SIMPLES

Segundo Sommerville (2007), a insatisfação com abordagens pesadas de

desenvolvimento de software, que focam principalmente no planejamento, no projeto e

na documentação de um sistema, levou um número de desenvolvedores de software da

década de 1990 a propor novos métodos, denominados Ágeis. Estes permitiam que a

equipe de desenvolvimento se concentrasse no software somente, em vez de em seu

projeto e documentação. Geralmente, os Métodos Ágeis contam com uma abordagem

iterativa para especificação, desenvolvimento e entrega de software, e foram criados

principalmente para apoiar o desenvolvimento de aplicações de negócios nas quais os

requisitos de sistema mudam rapidamente durante o processo de desenvolvimento. Eles

destinam-se a entregar um software de trabalho rapidamente aos clientes, que podem

então propor novos requisitos e alterações a serem incluídos nas iterações posteriores do

sistema.

Provavelmente, o nome mais conhecido do movimento ágil seja o de Kent Beck,

idealizador do método ágil conhecido como Extreme Programming (XP). Durante a

criação do conceito de XP, Beck propôs um método para criação de software bem

projetado conhecido como Projeto Simples. Segundo ele, um projeto é “simples” se

seguir, em ordem de relevância, as seguintes regras (MARTIN, 2009):

a) Efetuar todos os testes;

b) Sem duplicação de código;

Page 20: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

12

c) Expressar o propósito do programador;

d) Minimizar o número de classes e métodos.

Efetuar todos os testes significa utilizar a metodologia de desenvolvimento

guiada por teste (TDD), que consiste em criar testes automáticos para cada nova

funcionalidade antes mesmo de escrever seu código.

Programar utilizando essa metodologia torna os sistemas passíveis de testes, isso

nos direciona a um projeto que segue o Princípio da Responsabilidade Única, ou seja,

um projeto no qual as classes sejam pequenas e de único propósito. Classes que seguem

esse princípio geralmente são mais fáceis de testar. Logo, quanto mais testes se criar,

mais serão direcionados a construir coisas mais simples de serem testadas.

Similarmente, o forte acoplamento dificulta a criação de testes, quanto mais

testes se criar, mais será usado os princípios como o Princípio da Inversão de

Dependência, que diz que as classes devem depender de abstrações e não de detalhes

concretos, e frameworks de injeção de dependência de modo a minimizar este

acoplamento.

Segundo Martin (2009), ao seguir primeira regra do Projeto Simples, estarão

preparados para atingir as demais regras, ou seja, ao dispor de um conjunto de testes, é

possível manter o código de um sistema limpo, para isso basta recorrer à técnica de

refatoração.

2.5 MÉTRICAS DE CÓDIGO FONTE

Segundo Almeida e Miranda (2010), as métricas permitem criar mecanismos

automatizáveis para detecção de características obtidas através da análise do código-

fonte. Elas podem ser usadas como pontos de avaliação da qualidade do software.

Existem dois tipos de métricas de código-fonte. Algumas avaliam características de

métodos e outras de classes. As métricas de classe são normalmente somas ou médias

dos valores das métricas de métodos. Dentre as métricas selecionadas para este trabalho,

pode-se citar:

Complexidade Ciclomática de McCabe: calcula o número de caminhos

linearmente independentes (ou fluxos) de um método. Quanto menor o valor

desta métrica, mais fácil de assimilar será o código;

Page 21: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

13

Número de Classes: calcula o número de classes do projeto. Quanto maior o

valor desta métrica, mais provável será a alta coesão e a divisão de

responsabilidades entre as classes;

Total de Linhas de Código: calcula o número de linhas de código de uma classe.

Quanto menor o valor desta métrica, mais provável será a alta coesão e a divisão

de responsabilidades entre as classes;

Linha de Código por Método: calcula o número de linhas de código de um

método. Quanto menor o valor desta métrica, mais legível e menos coisas fará o

método.

3 METODOLOGIA

Como estudo de caso deste trabalho, foi escolhido o aplicativo Reversi, em sua

versão 0.25 Beta. Reversi é um aplicativo criado exclusivamente para fins acadêmicos,

como parte de um trabalho de conclusão de curso de graduação (CAMELO, 2011).

Escrito na linguagem Java, ele consiste na implementação para computador do jogo de

estratégia de tabuleiro de mesmo nome, mas que também pode ser conhecido como

Othello em algumas regiões. Ele foi escolhido principalmente por ser classificado como

software legado, ou seja, que não possui testes automatizados; além disso, ele não foi

construído com boas práticas de projeto, tornando-o um ambiente rico em bad smells; e

possuir uma quantidade de linhas de código relativamente pequena, mas adequada para

um trabalho como o que se está desenvolvendo.

Como ambiente de desenvolvimento, foi utilizada a IDE Eclipse Java EE for

Web Developers em sua versão Juno. A fim de obter métricas para esta pesquisa, foram

instalados neste ambiente os plug-ins EclEmma Java CodeCoverage for Eclipse, versão

2.2.1, utilizado para mensurar a quantidade de código coberta por testes; e Metrics for

Java projects, versão 1.3.6, utilizado para realizar análise estática do código e gerar uma

série de estatísticas da qual se fará uso da complexidade ciclomática de McCabe, do

número de linhas de código por método, do total de linhas de código das classes e

número de classes do projeto.

Na fase de codificação, foram utilizados os frameworks JUnit, versão 4.8.1,

usado para dar suporte a criação de testes automatizados da linguagem de programação

Page 22: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

14

Java; e o WindowLicker, versão 1.0.0, usado em conjunto com o JUnit para dar suporte

a testes de aceitação através da interface de usuário Swing.

Por fim, o próprio processo de refatoração como um todo pode ser considerado

como parte da metodologia, isto por que será necessário seguir um conjuntos de

pequenos passos e boas práticas para se obter sucesso ao aplicar a técnica em qualquer

projeto. Será apresentado este processo, desde a criação de um conjunto sólido de testes

até a detecção dos principais odores de código e a respectiva heurística utilizada para

refatoração do mesmo.

4 RESULTADOS E DISCUSSÃO

Esta seção tem como objetivo apresentar o sistema legado escolhido como

estudo de caso deste trabalho, explicar suas principais características dando ênfase em

aspectos da sua arquitetura e qualidade de código.

4.1 ARQUITETURA DO SISTEMA REVERSI

Do ponto de vista de projeto e arquitetura, a aplicação Reversi é classificada

como Desktop e apresenta características modestas se comparada com os padrões atuais

de desenvolvimento. Mesmo apenas se passado pouco mais de dois anos desde o seu

lançamento, ela aparenta ser bem mais antiga, pois foi construída por desenvolvedores

inexperientes, que não faziam uso de uma metodologia de desenvolvimento, utilizando-

se somente o kit de desenvolvimento Java, em sua versão 1.6.0, e não faz uso de

nenhuma API ou framework robusto. Dado estes fatos, já poderíamos facilmente

classificá-la como um sistema legado. No entanto, segundo Feathers (2004), existe uma

importante característica que já enquadraria esta aplicação como legada: a ausência de

testes automáticos.

A arquitetura está dividida em três camadas principais - Gui ou interface,

Domínio e IA. A figura 6 ilustra esta divisão. O pacote Gui está situado na parte superior

do diagrama, sua função é agrupar todas as classes de interface gráfica. É através dessas

classes que o jogador interage com o jogo posicionando suas pedras no tabuleiro. O

pacote situado na parte central do diagrama é o de Domínio, sua função é agrupar todas

as classes responsáveis por controlar as regras de negocio da aplicação. As classes de

Page 23: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

15

Domínio armazenam informações sobre o estado atual do jogo como, por exemplo,

pontuação e espaços vagos no tabuleiro. Situado na parte inferior do diagrama, está o

pacote de IA (Inteligência Artificial). Sua função é agrupar todas as classes responsáveis

por implementar os jogadores virtuais da aplicação, mais especificamente, os algoritmos

Poda alfa-beta e Genético (CAMELO, 2011).

Figura 6 - Diagrama de pacotes do Reversi

Fonte: CAMELO (2011)

4.2 REFATORAÇÃO DO SISTEMA REVERSI

Nesta seção será detalhada a metodologia de refatoração do sistema Reversi.

4.2.1 PORQUE REFATORAR

Suponha-se, hipoteticamente, que os desenvolvedores de Reversi recebessem

hoje uma oferta irrecusável para migrar seu software para um ambiente web ou alterar

sua interface gráfica para a interface nativa de algum dispositivo móvel compatível com

as especificações do projeto.

Dado o alto acoplamento e a falta de coesão das classes do sistema, não seria

possível aproveitar a regra de negócio do projeto e utilizá-lo em outra interface. Logo, a

solução mais rápida e obvia seria duplicar o projeto, o que resultaria em dois projetos

distintos, o desktop clássico e o com a nova interface.

Um problema poderia vir a surgir quando se descobrisse um bug em sua

implementação de algoritmo genéticos, por exemplo, a correção teria que ser feita em

Page 24: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

16

dois lugares (projetos) diferentes, o que implicaria em mais tempo para manter o

sistema ou inconsistência das correções nos projetos.

Portanto, segundo Fowler et al. (2004), quando descobre-se que tem que

acrescentar uma característica a um programa e o código desse programa não está

estruturado de forma conveniente para tal, primeiro refatore o programa para facilitar o

acréscimo da característica e só depois faz-se a adição.

4.2.2 O PRIMEIRO PASSO DA REFATORAÇÃO

Segundo Fowler et al. (2004), o primeiro passo da refatoração é sempre o

mesmo, verificar se o projeto possui um conjunto de testes confiáveis para o trecho de

código que se deseja refatorar. Caso o projeto não possua testes ou possua, mas não

sejam confiáveis, cria-se seu próprio conjunto de testes. É essencial para a refatoração

que se tenha um bom conjunto de testes, pois eles dirão se for introduzido alguma falha

durante este processo.

Para criação dos cenários de testes foi utilizada a técnica de modelagem de teste

baseado na especificação, conhecida como Particionamento de Equivalência. Esta

técnica consiste em dividir as entradas do sistema em conjuntos que produzem a mesma

saída. Para cada conjunto de entradas é especificado um teste. Para o Reversi, foi criado

o particionamento como o mostrado na figura 7. Nela, foi dividido o conjunto de

entradas entre jogadas boas, jogadas ruins e jogadas boas e ruins, e o conjunto de saídas

entre vitórias, empates e derrotas.

Figura 7 - Particionamento de equivalência para o Reversi

Fonte: Autoria própria

Page 25: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

17

A partir desta especificação foram criados um conjunto de testes de aceitação

para o sistema. Testes de aceitação são testes automáticos que exercitam o sistema da

perspectiva do usuário, ou seja, como se ele estivesse interagindo com o sistema. Para

que isto fosse possível, foi utilizado o framework WindowLicker em conjunto com o

JUnit. Assim, os testes interagem com a aplicação clicando nos locais da tela do sistema

que foram programados, realizando jogadas e validando cada comportamento resultante

da mesma. Este conjunto de testes pode ser visto na figura 8. Como é possível observar,

devido a dificuldade de se obter um conjunto de jogadas que faça a partida terminar

empatada, o teste que cobre a situação de empate foi descartado.

Figura 8 - Conjunto de testes automáticos do Reversi

Fonte: Autoria própria

Por fim, vale apena ressaltar um problema ocorrido neste primeiro passo. Para se

construir testes automáticos para um sistema, o mesmo deve ser passível de teste, ou

seja, ele deve prover mecanismos para que seja possível simular ou prever seu

comportamento. No caso do Reversi, as jogadas realizadas pelo computador são

imprevisíveis, haja vista que as mesmas empregam uma regra de negócio complexa.

Assim, seria muito difícil automatizar as jogadas de um usuário sem saber o conjunto de

jogadas do computador. A solução é substituir o computador real por um computador de

Page 26: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

18

teste (ou computador Stub1). Em sistemas não passíveis de teste isto muito vezes não é

possível por conta do alto acoplamento entre as classes. Portanto, antes de criar este

conjunto de testes, foi necessário realizar uma pequena alteração no projeto, colocando

um pequeno trecho de código de teste no código do sistema. Isto não é recomendável,

mas foi necessário para a realização deste trabalho.

4.2.3 O PROCESSO DE REFATORAÇÃO

Agora que o projeto do Reversi já possui um conjunto sólido de testes, está-se

apto para começar a refatorar qualquer trecho de código que esteja coberto por estes

testes. O processo de refatoração deve seguir os seguintes passos:

a) Explorar o código do sistema em busca de algum odor;

b) Realizar a refatoração de um pequeno trecho do código “fedorento”;

c) Executar o conjunto de testes automáticos (ou teste de regressão) para se

certificar de que as alterações não comprometeram o sistema;

d) Caso os testes tenham sido executados com sucesso, siga para o passo a; caso

contrário, desfaça suas alterações e volte ao passo b.

O primeiro trecho de código que chamou atenção é o da figura 9. Apesar de ser

relativamente pequeno, ele é um verdadeiro ecossistema de pequenos odores. A começar

pelo nome, que apesar de ser legível, não segue a convenção da linguagem para nomes

de métodos, pois não começa com verbo para indicar uma ação. Existe um alto

acoplamento em se instanciar as classes Busca e População, além disso, elas são usadas

somente neste método, o que pode ser um indício de responsabilidade mal posicionada.

O método realizaJogada recebe dois parâmetros quando poderia simplesmente receber

um único objeto: Jogada.

Os comentários são usados de forma a minimizar o odor do código mal escrito,

ora usado para esconder código morto, ora usado de forma redundante para descrever o

funcionamento do método. Pode-se ver também uma pequena Inveja de Dados na

expressão condicional. Assim como, o método realiza duas ações, busca a jogada e

depois a executa. Por último, existe um erro de lógica no comando condicional if/else: se

1 Segundo InfoQ (2013), stub é um objeto falso utilizado, no lugar de um objeto real, para propósito de

testes. Ele fornece respostas pré configuradas para as chamadas que lhe são feitas durante os testes e

normalmente não respondem a nada que não esteja programado para o teste.

Page 27: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

19

o método getStrInteligênciaArtificial retornar nulo, por exemplo, o sistema irá escolher o

algoritmo minimax alfa-beta, quando deveria tomar outra ação.

Figura 9 - Método buscaJogadaComputador com vários odores

Fonte: Autoria própria

Após a refatoração, o método anteriormente denominado

buscaJogadaComputador ficou bem mais intuitivo, como mostra a figura 10. Além de

um nome mais legível, ele agora executa somente uma ação, e a executa de forma bem

feita.

Figura 10 - Refatoração do antigo método buscaJogadaComputador

Fonte: Autoria própria

A responsabilidade de instanciar a inteligência artificial da aplicação foi

transferida para um método de fábrica, como mostra a figura 11. Nela, também é

possível ver a correção da lógica do comando condicional if/else, e um exemplo de

comentário de código benéfico, sinalizando um débito técnico.

Page 28: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

20

Figura 11 - Método de fábrica obterComputador

Fonte: Autoria própria

O segundo trecho de código que chamou atenção foi o da figura 12. Além de

uma série de nomeações de métodos que não seguem a convenção da linguagem, tem-se

um caso típico de Inveja de Dados, mais precisamente nas chamadas dos métodos

fimJogo, isVezJogado e resultadoJogo. Apesar de não violar a Lei de Demeter, está

claro que este trecho de código “inveja os dados” do objControle.

Figura 12 - Inveja de dados do objeto objControle

Fonte: Autoria própria

A solução é posicionar a responsabilidade de obter a mensagem com status atual

do jogo na classe correta, ou seja, na classe ControladorDoJogo como mostra a figura

13.

Page 29: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

21

Figura 13 - Responsabilidade reposicionada na classe ControladorDoJogo

Fonte: Autoria própria

Além da falta de legibilidade dos nomes de variáveis e métodos, e há um

excessivo número de comentários que insistem em explicar o que os nomes ruins do

método não conseguem. Um dos odores que mais vem se repetindo no código do

Reversi é o Acidente de Trem e a duplicação de código que sempre o acompanha. A

figura 14 mostra claramente a repetição de código causada pelo Acidente de Trem ao

chamar as funcionalidades do objeto objControle. Por fim, outro odor que está

começando a “cheirar forte” neste trecho de código, devido a grande quantidade de

“números mágicos” e notação Húngara, é o chamado Propósito Obscuro.

Figura 14 - Código “Acidente de trem” ao chamar método getMatPedrasTabuleiro

Fonte: Autoria própria

A solução para este tipo de odor consiste basicamente em delegar para a classe

colaboradora mais próxima a responsabilidade de prover a funcionalidade que se estava

interessado ao fazer o Acidente de Trem. No caso especifico, foi delegado a classe

ControladorDoJogo a obtenção do caminho da imagem, como mostra a figura 15. Esta

Page 30: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

22

refatoração também irá resolver o problema de duplicação de código ocorrido ao se

chamar o método getMatPedrasTabuleiro, pois agora existirá apenas uma única

chamada a este método, centralizada em uma classe que possua tal responsabilidade.

Também foram removidos os “números mágicos” com constantes explicativas e

renomeadas as variáveis de forma mais legível. Por fim, vale lembrar que o trecho de

código da figura 14 acabou sendo extraído para um método que explicará claramente

seu propósito, chamado gerarTabuleiroLabelComEstadoAtualDoJogo.

Figura 15 - Refatoração do Acidente de Trem do método getMatPedrasTabuleiro

Fonte: Autoria própria

Um método que também chamou atenção foi o executaJogada, que possuía 191

linhas de código, como mostra a figura 16. Logo, não resta nenhuma dúvida de que este

método realiza mais de uma ação. Além disso, mesmo ocultando a maior parte do

código contido no método, é possível imaginar que ele continha uma quantidade

elevada de “odores”.

Page 31: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

23

Figura 16 - Muitas linhas de código no método executaJogada

Fonte: Autoria própria

A solução para este problema foi remanejar as responsabilidades deste método,

ora utilizando uma extração de trechos de código para um método menor com propósito

claro, ora criando novas classes para realizar funções específicas. De acordo com os

comentários da figura 16, a responsabilidade de executaJogada é atualizar o estado do

tabuleiro, invertendo as cores das pedras afetadas após uma jogada. A refatoração deste

método pode ser vista na figura 17. Foram criadas várias classes do tipo Reversível que

implementam o método reverter de acordo com a direção (ou sentido) do tabuleiro que

se deseja atualizar.

Figura 17 - Refatoração do método executaJogada

Fonte: Autoria própria

4.2.4 QUANDO PARAR DE REFATORAR

Não existe uma condição de parada exata para determinar quando a refatoração

termina, haja vista que tudo depende da sensibilidade e necessidades do desenvolvedor

que a executa. No caso do Reversi, o objetivo foi seguir apenas a Regra do Escoteiro (do

inglês, The Boy ScoutRule), uma metáfora que segundo Martin (2009), diz:

“Deixe a área do acampamento mais limpa do que como você a encontrou.”

Page 32: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

24

Fazendo uma analogia para programação, se cada desenvolvedor deixar o código

fonte do sistema em que está trabalhando mais limpo do que quando o recebeu de outro

programador, ele estará atendendo à Regra.

Portanto, este processo de refatoração foi repetido várias vezes consecutivas até

que todo o código do Reversi, que estava coberto por testes, estivesse melhor que o

código original.

4.3 MÉTRICAS DO SISTEMA REVERSI

Com o intuito de mensurar os ganhos de qualidade advindos do processo de

refatoração, foi realizada a coleta das métricas escolhidas para o projeto Reversi. Elas

foram coletadas durante os três marcos deste processo, são eles:

a) Após posse do sistema legado, ou seja, antes da refatoração ser aplicada;

b) Após a criação do conjunto de testes de aceitação;

c) Após o processo de refatoração chegar ao fim.

As métricas coletadas podem ser vistas na figura 18. Como pode-se ver, as

quatro primeiras métricas referentes a complexidade ciclomática1 e linhas de código

avaliam o projeto no escopo de método. Nelas, o processo de refatoração reduziram

seus números iniciais aproximadamente pela metade (com exceção da complexidade

ciclomática máxima que teve uma redução muito maior). Isto significa que os métodos

do projeto estão mais coesos, realizam menos ações e estão mais legíveis.

1 Complexidade ciclomática (ou complexidade condicional) é uma métrica de software usada para indicar

a complexidade de um programa de computador. Desenvolvida por Thomas J. McCabe em 1976, ela

mede a quantidade de caminhos de execução independentes a partir de um código fonte (WIKIPÉDIA,

2013c).

Page 33: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

25

Figura 18 - Métricas do projeto Reversi

Fonte: Autoria própria

As métricas seguintes, total de classes e média de linhas de código das classes,

avaliam o projeto no escopo de classes. Percebe-se que os números se contrapõem em

proporções bastante semelhantes, enquanto o total de classes do projeto teve um

aumento pouco maior que o dobro em relação aos números iniciais, a média de linhas de

código das classes do projeto teve seus valores reduzidos pela metade em relação aos

números iniciais. Isto significa que as responsabilidades das classes foram melhor

divididas através da criação de mais classes e a coesão das mesmas aumentada pela

menor quantidades de linhas que elas apresentam.

Por fim, as métricas de cobertura de testes nos mostram a porcentagem de linhas

de código do projeto coberta por testes. Como pode-se ver, o projeto saiu do patamar de

projeto legado, ou seja, que não possui código coberto por testes, para um projeto com

49,4% do seu código coberto por testes. Vale lembrar que este conjunto de testes

cobrem apenas os pacotes Gui e Domínio do projeto, ficando o pacote IA sem testes e,

consequentemente, sem refatoração. Isto aconteceu porque foi necessário substituir o

computador real por um computador de teste (ou computador Stub) durante a execução

dos testes. Assim, o fluxo de execução do programa, que passava pelo pacote IA, foi

desviado para um pacote de testes previamente configurado.

Page 34: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

26

5 CONCLUSÃO

Este artigo sugeriu a utilização da técnica de refatoração para melhorar a

qualidade de código de sistemas legados, com o intuito de avaliar se os benefícios

advindos de sua utilização são satisfatórios o bastante para adotá-la no processo de

evolução deste tipo de sistema, tornando-os mais produtivos e permitindo que suas

melhoria e manutenção sejam efetuadas com rapidez e segurança.

Ao final do processo de refatoração foi constatado, com base em um conjunto de

métricas de software, que a qualidade do projeto aumentou consideravelmente. As

classes se tornaram mais coesas e suas responsabilidades foram melhor divididas. Os

métodos perderam boa parte de sua complexidade e tamanho, e agora realizam ações

mais específicas. Além disso, ganharam maior legibilidade. Por fim, o projeto ganhou

um conjunto de testes automáticos que podem ser executados a qualquer momento,

permitindo que o sistema possa evoluir com segurança e rapidez.

Tendo em vista os fatos mencionados, considera-se a técnica de refatoração

importante para a melhoria da qualidade de sistemas legados, tornando-os mais

produtivos e permitindo que melhorias e evoluções sejam efetuadas com um menor

risco.

REFERÊNCIAS

ALMEIDA, Lucianna Thomaz; MIRANDA, João Machini de. Código Limpo e seu

Mapeamento para Métricas de Código Fonte. Trabalho de Conclusão de Curso -

Instituto de Matemática e Estatística, Universidade de São Paulo - USP. São Paulo,

2010.

BECK, Kent. Extreme Programming Explained. Boston: Addison Wesley, 1999.

BECK, Kent. Implementation Patterns. Boston: Addison Wesley, 2007.

BOSWELL, Dustin; FOUCHER, Trevor. A Arte de Escrever Programas Legíveis:

técnicas simples e práticas para elaboração de programas fáceis de serem lidos e

entendidos. Trad. Rafael Zanolli. São Paulo: Novatec, 2012.

Page 35: Melhorando a Qualidade de Código com a Técnica de Refatoração - Estudo de Caso em um Sistema Legado Java

27

CAMELO, Anderson Lemos. Um Jogo de Othello Evolutivo. Trabalho de Conclusão

de Curso (Graduação em Ciências da Computação) - Instituto de Computação,

Universidade Federal de Alagoas - UFAL, Maceió, 2011.

FOWLER, Martin; BECK, Kent; BRANT, John; OPDYKE, Willian; GAMMA, Erich.

Refatoração: aperfeiçoando o projeto de código existente. Trad. Acauan Fernandes.

Porto Alegre: Bookman, 2004.

FEATHERS, Michael C. Working Effectively with Legacy Code. UpperSaddle River:

Prentice Hall, 2004.

FREEMAN, Steve; PRYCE, Nat. Desenvolvimento de Software Orientado a

Objetos, Guiado por Testes. Trad. Savannah Hartmann. Rio de Janeiro: Alta Books,

2012.

INFOQ. Mocks Aren't Stubs. 2013. Disponível em:

<http://www.infoq.com/br/articles/mocks-Arent-Stubs>. Acesso em: 28 set. 2013.

MARTIN, Robert C. Código Limpo: habilidades práticas do agile software. Trad.

Leandro Chu. Rio de Janeiro: Alta Books, 2009.

SARTORELLI, Reinaldo Coelho. Proposta de Processo para Automação de Testes

em Sistemas Legados. Trabalho de Conclusão de Curso (Pós-Graduação em Técnicas

de Construção de Software Orientado a Objetos) - Centro Universitário SENAC, São

Paulo, 2007.

SOMMERVILLE, Ian. Engenharia de Software. Trad. Selma Shin Shimizu

Melnikoff, Reginaldo Arakaki, Edilson de Andrade Barbosa. São Paulo: Pearson

Addison-Wesley, 2007.

WIKIPÉDIA. Refatoração. 2013a. Disponível em:

<http://pt.wikipedia.org/wiki/Refatoração>. Acesso em: 17 set. 2013.

WIKIPÉDIA. CodeSmell. 2013b. Disponível em:

<http://http://en.wikipedia.org/wiki/Code_smell>. Acesso em: 17 set. 2013.

WIKIPÉDIA. Complexidade ciclomática. 2013c. Disponível em:

<http://pt.wikipedia.org/wiki/Complexidade_ciclomática>. Acesso em: 28 set. 2013.