refactorizaciÓn automatizada para la eliminaciÓn de
TRANSCRIPT
TESIS DE GRADO EN INGENIERÍA DE SISTEMAS
REFACTORIZACIÓN AUTOMATIZADA PARA LA
ELIMINACIÓN DE FEATURE ENVY
por
Antivero, Juan Pablo
Arias, Lucas
Director: Vidal, Santiago A.
Co-Directora: Marcos, Claudia A.
FACULTAD DE CIENCIAS EXACTAS
UNIVERSIDAD NACIONAL DEL CENTRO DE LA PROVINCIA DE
BUENOS AIRES
Tandil, Argentina
2018
2
Índice
Capítulo 1: Introducción ................................................................................. 8
1.1 Calidad de software .................................................................................................. 8
1.2 La problemática de los Code Smell .......................................................................... 9
1.3 Extensión de Bandago .............................................................................................. 10
1.4 Esquema general ...................................................................................................... 12
Capítulo 2: Calidad y mantenimiento de software ..................................... 13
2.1 Calidad de software .................................................................................................. 13
2.2 Refactoring ............................................................................................................... 14
2.3 Code Smells ............................................................................................................... 15
2.3.1 Feature Envy .......................................................................................................... 17
2.3.2 Refactoring de Feature Envy ................................................................................. 18
2.3.2.1 Program Slicing ............................................................................................. 18
2.3.2.2 Statements ..................................................................................................... 18
2.3.2.3 Problemática del Move Method .................................................................... 19
Capítulo 3: Herramientas de refactorización y análisis de
Feature Envy ............................................................................. 20
3.1 Enfoques del refactoring de Feature Envy ............................................................ 20
3.2 Herramientas ............................................................................................................ 20
3.2.1 Herramientas de recomendación de refactoring ..................................................... 20
3.2.1.1 MethodBook .................................................................................................. 21
3.2.1.2 MORE ........................................................................................................... 22
3.2.1.3 c-JRefRec ...................................................................................................... 25
3.2.1.4 JMove ........................................................................................................... 27
3.2.2 Herramientas de aplicación de refactorings ........................................................... 28
3.2.2.1 Eclipse ........................................................................................................... 29
3.2.3 Herramientas de recomendación y aplicación de refactorings ................................ 29
3.2.3.1 JDeodorant .................................................................................................... 29
3.3 Criterios de comparación ........................................................................................ 30
3.3.1 Comparación y conclusiones ................................................................................. 31
3
Capítulo 4: Un enfoque iterativo para la refactorización de
Feature Envy ............................................................................ 33
4.1 Refactorización de Feature Envy .......................................................................... 33
4.2 Esquema general de la solución iterativa de Feature Envy ................................ 34
4.3 Desarrollo del enfoque iterativo para la refactorización de Feature Envy ........ 36
4.3.1 Actividad 1: Obtener características del método .................................................... 36
4.3.2 Actividad 2: Elegir la clase candidata .................................................................... 38
4.3.3 Actividad 3: Seleccionar el fragmento de código a mover ..................................... 39
4.3.4 Actividad 4: Calcular las métricas de la solución generada ................................... 41
4.3.5 Actividad 5: Aplicar el refactoring ........................................................................ 42
4.3.6 Actividad 6: Corregir errores ................................................................................. 43
4.4 Implementación de la solución ................................................................................ 44
4.4.1 Aplicación de refactorings .................................................................................... 44
4.4.2 Vista arquitectónica de Bandago ........................................................................... 45
Capítulo 5: Casos de estudio ........................................................................ 49
5.1 Proyectos evaluados y operatoria de la evaluación ............................................... 49
5.2 Características de las Feature Envy ....................................................................... 51
5.3 RQ #1: ¿Qué porcentaje de Feature Envy son automáticamente eliminadas por
la tool, sin necesidad de correcciones por parte del desarrollador? ........................... 54
5.3.1 Hipótesis ............................................................................................................... 54
5.3.2 Análisis e Interpretación ....................................................................................... 54
5.4 RQ #1: ¿Qué porcentaje de Feature Envy son automáticamente eliminadas por
la tool, sin necesidad de correcciones por parte del desarrollador? ........................... 59
5.4.1 Hipótesis ............................................................................................................... 59
5.4.2Análisis e Interpretación ........................................................................................ 60
5.5 RQ #1: ¿Qué porcentaje de Feature Envy son automáticamente eliminadas por
la tool, sin necesidad de correcciones por parte del desarrollador? ........................... 64
5.5.1 Hipótesis ............................................................................................................... 64
5.5.2 Análisis e Interpretación ....................................................................................... 65
Capítulo 6: Conclusión .................................................................................. 69
6.1 Conclusiones finales ................................................................................................. 69
6.2 Contribuciones .......................................................................................................... 70
4
6.3 Limitaciones .............................................................................................................. 70
6.4 Trabajos futuros ....................................................................................................... 71
Bibliografía .................................................................................................... 72
5
Índice de Figuras
1.1 Esquema base de la herramienta ..................................................................................... 11
2.1 Etapas del proceso de refactoring .................................................................................. 14
2.2 Detección de Feature Envy ............................................................................................ 17
3.1 Proceso utilizado por MethodBook para encontrar recomendaciones ........................... 21
3.2 Arquitectura del recomendador de refactorings MORE ................................................ 23
3.3 Vista Class State View de la herramienta c-JRefRec .................................................... 26
3.4 Vista Refactoring Candidates View de la herramienta c-JRecRef ................................ 26
3.5 Interfaz de JMove .......................................................................................................... 28
3.6 Presentación de Feature Envy de JDeodorant ................................................................ 30
4.1 Correlación entre code smells. Lanza y Marinescu ....................................................... 33
4.2 Esquema general de la solución de Feature Envy ......................................................... 35
4.3 JSpIRIT Smells View .................................................................................................... 37
4.4 Llamados a variables de instancia de la propia clase del método ejemplo..................... 37
4.5 Identificación de llamados a clases externas ................................................................. 39
4.6 Selección de statement o conjunto de statements a extraer ........................................... 40
4.7 Selección del statement candidato a ser extraído para la clase
name.gyger.jmoney.model.Entry.......................................................................................... 41
4.8 Cálculo de las métricas de la solución generada (Bandago View) ................................. 42
4.9 Selección de una solución para Feature Envy (Bandago Wizard).................................. 43
4.10 Método movido a la clase candidata............................................................................. 43
4.11 Extracción de un método previo a ser movido ............................................................. 45
4.12 Diagrama de contexto de Bandago .............................................................................. 46
4.13 Arquitectura de alto nivel de Bandago ......................................................................... 48
5.1 Diagrama de la operatoria del experimento .................................................................... 51
5.2 Boxplot para la métrica ATFD ...................................................................................... 52
5.3 Boxplot para la métrica LAA ........................................................................................ 53
6
5.4 Boxplot para la métrica FDP ......................................................................................... 53
5.5 Extracción Total vs Extracción Parcial .......................................................................... 58
5.6 Cantidad de soluciones identificadas .............................................................................. 58
5.7 Limitaciones de Eclipse al aplicar el refactoring Move Method .................................... 59
5.8 Cantidad de smells solucionados por el enfoque ........................................................... 61
5.9 Porcentajes de smells solucionados ............................................................................... 62
5.10 Cantidad de smells creados por el enfoque .................................................................. 62
5.11 Porcentajes de smells creados....................................................................................... 63
5.12 Code Smells afectados por el enfoque .......................................................................... 64
5.13 Cantidad de Feature Envy identificadas por JDeodorant y JSpIRIT ............................ 65
5.14 Porcentaje de resolución de ambas herramientas sobre la intersección ...................... 66
5.15 Método solucionado por JDeodorant y no solucionado por el enfoque propuesto ...... 66
5.16 Cantidad de Feature Envy resueltas por ambas herramientas ...................................... 67
5.17 Porcentaje de Feature Envy resueltas por ambas herramientas ................................... 68
7
Índice de Tablas
2.1 Code Smells catalogados por Lanza y Marinescu .......................................................... 16
2.2 Métricas utilizadas por la herramienta............................................................................ 17
3.1 Selección de refactorings basado en reglas de MORE ................................................... 25
3.2 Categorías de las herramientas ...................................................................................... 31
3.3 Características de las herramientas ................................................................................. 31
4.1 Priorización de clases externas accedidas por la Feature Envy ...................................... 39
4.2 Elementos de la arquitectura de Bandago....................................................................... 46
5.1 Proyectos evaluados ....................................................................................................... 49
5.2 Cantidad de Feature Envy por proyecto ........................................................................ 51
5.3 Resultados de Feature Envy analizadas y resueltas automáticamente ........................... 55
5.4 Resultados de Feature Envy analizadas y resueltas luego de la intervención por parte del
desarrollador ........................................................................................................................ 56
5.5 Resultados de Feature Envy analizadas y resueltas ........................................................ 57
5.6 Comparación de Code Smells pre y post refactoring .................................................... 60
8
Capítulo 1: Introducción
1.1 Calidad de software
En los sistemas de software es muy importante centrar el desarrollo en su calidad [22,23]. En
el contexto del software, calidad es "la totalidad de aspectos y características de un producto
o servicio que tienen que ver con su habilidad de satisfacer las necesidades explícitas o
implícitas" [12]. Para asegurar esto es que existe el ciclo de vida del software, metodologías
de desarrollo, modelos de mejora continua de procesos y distintos aspectos relacionados al
área de SQA (Sofware Quality Assurance, es decir, Garantía de la Calidad de Software) [24].
Sin embargo, la calidad y la estructura de los sistemas se ven deterioradas a menudo,
generalmente como resultado de los cambios que introducen los programadores para resolver
objetivos a corto plazo, sin conocer completamente el diseño del código [2]. Estos problemas
de diseño normalmente son conocidos como code smells. Un code smell (también llamado
bad smell), se refiere a cualquier síntoma que puede indicar que el código fuente presenta
problemas [2], como lo es el código duplicado, métodos o clases muy largos, mal
encapsulamiento de clases o extensas listas de parámetros, entre otros.
Feature Envy es un code smell que impacta principalmente en la modificabilidad del sistema.
Lanza y Marinescu [3] lo definen de la siguiente manera:
“La desharmonía de diseño Feature Envy se refiere a los métodos que parecen más
interesados en los datos de otras clases que en los de su propia clase. Estos métodos acceden
o una gran cantidad de datos de otras clases directamente o mediante métodos de acceso”
La presencia de Feature Envy afecta negativamente el mantenimiento y la extensibilidad,
minimizando la cohesión de una clase y generando el riesgo de sufrir un efecto en cascada
(un cambio en un método dispara cambios en otro método y así sucesivamente).
Es importante señalar que la calidad del software no se refiere únicamente a obtener un
producto sin errores, sino también a que su código fuente se pueda extender, modificar de
manera simple y entender sin que esto resulte un problema con el paso del tiempo, debido a
que la etapa posterior a la entrega es la parte más importante en el desarrollo de software
[14]. La existencia y aumento de code smells generan una degradación de la calidad del
software, impactando fuertemente sobre la comprensión, mantenimiento y evolución del
código fuente [1].
La manera de solucionar los code smells es mediante la refactorización [2] del código fuente.
Refactorizar, en Ingeniería de Software, se describe como el proceso de realizar un cambio
en la estructura interna del software para que este sea más fácil de entender y más simple de
modificar sin cambiar su comportamiento. El refactoring es realizado por los desarrolladores
como parte del proceso de desarrollo del software, ya que incrementa la legibilidad y
mantenibilidad. Este proceso, además, permite mejorar el diseño del software mejorando su
9
modularización y evitando así, en muchos casos, una mayor cantidad de código para realizar
una misma tarea debido a código duplicado.
1.2 La problemática de los Code Smell
A pesar de la importancia del proceso de refactoring como medio para mantener la calidad
del software, éste no siempre es realizado con la frecuencia ni con el tiempo que requiere. La
falta de refactorings, en general, se debe a lo complejo y costoso que puede resultar el proceso
de detección de code smells, la forma de solucionarlos, y el riesgo de generar errores durante
el proceso. También, en la industria, la frecuencia y tiempo que se le dedica a este proceso
se ve afectada por los cortos tiempos de entrega que se disponen.
El autor K. Beck, en uno de sus libros sobre la metodología ágil eXtreme Programming,
afirma que el refactoring ahorra tiempo en desarrollo y mejora la calidad [18], instando a los
desarrolladores a incluir al refactoring como una etapa que sea parte del ciclo de desarrollo
del software. Por otro lado, existe la idea de que los ingenieros de software a menudo evitan
el refactoring cuando se encuentran limitados con respecto a recursos y tiempos de entrega
[16]. En general, muy pocos desarrolladores se acercan a un equilibrio entre la adición de
nueva funcionalidad y la utilización de refactoring. En cualquiera de los casos, la falta de
herramientas que determinan el impacto real del refactoring y sus efectos secundarios,
contribuyen con la decisión de posponer el refactoring reiteradas veces, y en la mayoría de
los casos nunca es ejecutado [17].
Un estudio de campo realizado por Kim, Zimmermann y Naggapan [19] muestra algunas
contradicciones en sus resultados acerca de los beneficios de aplicar refactorizaciones.
Aunque muchos programadores afirman que el uso de refactoring disminuye la cantidad de
bugs, otros señalan que en muchas ocasiones aparecen bugs de regresión al refactorizar. Sin
embargo, la causa de este inconveniente ha sido analizada por Murphy-Hill et al. [21], que
encontró que desarrolladores usualmente ejecutan refactorings junto con otros cambios que
alteran el comportamiento, además que los refactorings son aplicados en forma manual en
lugar de utilizar una herramienta que automatiza el proceso. Este tipo de prácticas son
propensas a introducir errores en el código.
La Feature Envy es un code smell sobre el cual se posee poca información que permita inferir
un método automatizado intuitivo para eliminarla. Martin Fowler [2] plantea que la solución
consiste en mover el método a la clase de la cual envidia el mismo mediante el refactoring
Move Method. En caso de que únicamente una parte del método sufra esta anomalía,
previamente hay que extraerla mediante Extract Method para luego realizar el Move
únicamente de esa parte.
Realizar manualmente este proceso puede ocasionar problemas de compilación y/o de
modificabilidad. Se deben comprobar las dependencias para no correr el riesgo de afectar el
funcionamiento del código, ya sea generando errores o incluso cambiando el comportamiento
original del programa accidentalmente.
Adicionalmente se deben tener en cuenta cuatro condiciones al realizar el refactoring Extract
Method:
10
El código seleccionado para extraerse tiene que ser una lista de sentencias.
Dentro del fragmento de código no pueden existir asignaciones a variables que sean
utilizadas luego en el flujo del método. En el caso de Java, se puede permitir la
asignación de una variable y ésta será la variable de retorno en el método.
No pueden existir sentencias del tipo return.
El bloque de código no puede contener ramas de ejecución que vayan por fuera del
código seleccionado.
En cuanto al uso de Move Method, adicionalmente se deben tener en cuenta las condiciones
que imposibilitan la realización del mismo:
El método no debe estar declarado en superclases o subclases.
Deben modificarse todos los llamados que referencien a ese método.
En la clase candidata a la cual se moverá no debe existir un método del mismo
nombre.
El método no debe sobreescribir un método abstracto.
El método debe referenciar a la clase candidata a través de sus parámetros o de los
campos de la clase original.
Debido a la complejidad que conlleva el control de todos los puntos para asegurar que no se
ha modificado la funcionalidad del sistema ni se han introducido errores de compilación, es
importante encontrar la forma de automatizar la refactorización de Feature Envy.
Pocos estudios intentan solucionar code smells con una refactorización automatizada [25]
[40] [41]. En el caso de Feature Envy, existen herramientas que intentan lograrlo. Sin
embargo, ninguna solución conocida intenta la extracción (Extract Method) previa al Move
Method.
Existen herramientas, como JDeodorant [25] que han logrado una correcta solución a este
code smell, siempre y cuando se pueda mover el método completo a la clase candidata. Se
requiere realizar un análisis más detallado para lograr la identificación de métodos en los que
únicamente es necesario mover una parte del mismo.
1.3 Extensión de Bandago
En este trabajo se presenta una extensión de la herramienta Bandago [20] para el code smell
Feature Envy. Bandago es una herramienta que tiene como objetivo la solución de code
smells y luego el análisis del costo beneficio de la solución mediante la presentación de
métricas pertinentes. Originalmente dicha herramienta poseía la funcionalidad para
solucionar el code smell Brain Method, y fue extendida para soportar la resolución de Feature
Envy.
Para solucionar el code smell Feature Envy se aplican los refactorings Move Method y
Extract Method [2]. De esta forma se mueve el método a la clase en la cual se debería
encontrar. En caso de no poder realizarse esta acción directamente, se buscan alternativas
11
para extraer la parte del método que genere Feature Envy y moverla a la clase candidata. Así
se logra poner en un mismo lugar el método y los datos que se utilizan conjuntamente [2],
minimizando la posibilidad de "efectos cascada" (un cambio en un método dispara cambios
en otro método sucesivamente) y se maximiza la cohesión [3].
Figura 1.1: Esquema base de la herramienta.
La Figura 1.1 muestra un esquema del enfoque propuesto donde se observa la Feature Envy
como la entrada, el código refactorizado como la salida y componentes que fueron utilizados,
encargados de realizar el análisis del código afectado y de aplicar el refactoring. Se realizó
un enfoque heurístico sobre la herramienta Bandago [20] y se utilizó como entrada la
herramienta JSpIRIT [13] para la detección de los code smells. El análisis de las métricas
tiene como base las investigaciones de Lanza y Marinescu [3]. También, se estudiaron las
herramientas que provee el IDE Eclipse para la extracción de código, y especialmente para
la realización de Move Method, debido a que actualmente la API de Eclipse no provee un
soporte completo para realizar correctamente este refactoring programáticamente.
Para poder validar los beneficios del enfoque se realizó un caso de estudio donde se
respondieron 3 research questions. Estas fueron:
RQ#1: ¿Qué porcentaje de Feature Envy son automáticamente solucionadas por el
enfoque propuesto, sin necesidad de intervención del desarrollador?
RQ#2: ¿Solucionar las Feature Envy permite solucionar otros Code Smells?
RQ#3: ¿Son complementarias las soluciones identificadas por el enfoque propuesto
y por JDeodorant en la refactorización de Feature Envy?
Estas Research Questions corroboraron la efectividad del enfoque, permitiendo identificar
un alto porcentaje de soluciones sobre el total de Feature Envy de un sistema. En la RQ#1,
se analizaron todas las Feature Envy que se lograron solucionar automáticamente sin
intervención por parte del desarrollador. Para la RQ#2, se analizó si la solución de Feature
Envy permite solucionar otros code smells detectados por JSpIRIT. Para la RQ#3, se
comparó el enfoque propuesto con otra herramienta de recomendación y aplicación de
refactors para la eliminación de Feature Envy, llamada JDeodorant [25].
12
La refactorización de este code smell lleva a una mejora en la cohesión y el acoplamiento del
software. Se obtuvo como resultado un código fuente mejor estructurado, más legible y con
mejor diseño.
Las contribuciones del trabajo final son las siguientes: Se logró automatizar todo el proceso
de refactorización de las Feature Envy, generando una solución válida. Se pueden visualizar
el conjunto de métricas relacionadas que justifican la aplicación de la solución propuesta.
Además, se extendió la funcionalidad de Bandago para hacerlo más configurable a las
necesidades de un desarrollador. Otro aporte importante es el análisis automatizado de
posibilidades de extracción en caso de no poder mover el método completo, ya que no existe
precedencia en la aplicación de este análisis adicional al intentar resolver una Feature Envy.
1.4 Esquema general
El esquema general de la tesis está organizado de la siguiente manera:
En el capítulo 2 se presentan los conceptos de la calidad y mantenimiento de software. Así
mismo, se introducirán temas clave como la noción de code smell y refactorización.
En el capítulo 3 se describen herramientas enfocadas a refactorizar automáticamente una
Feature Envy. Adicionalmente, serán comparados entre sí.
En el capítulo 4 se presenta el enfoque de la solución planteada. Se desarrollarán las
actividades y se describirán detalladamente. Luego, se presentarán la implementación y el
diseño de la solución.
En el capítulo 5 se presenta un caso de estudio que responde las research questions. Se
presenta la operatoria que se utilizó en el caso de estudio y posteriormente el análisis de los
resultados obtenidos.
Finalmente, el caso 6 resume conclusiones, contribuciones principales, limitaciones y el
trabajo futuro.
13
Capítulo 2: Calidad y mantenimiento de software
2.1 Calidad de software
En el contexto del software, calidad es "la totalidad de aspectos y características de un
producto o servicio que tienen que ver con su habilidad de satisfacer las necesidades
explícitas o implícitas" [12]. Para asegurar esto es que existe el ciclo de vida del software,
metodologías de desarrollo, modelos de mejora continua de procesos y todo lo relacionado
al área de SQA (Sofware Quality Assurance, es decir, Garantía de la Calidad de Software)
[24]. Por lo tanto, es muy importante centrar el desarrollo en su calidad [22,23].
La calidad de software hace referencia a dos puntos importantes: generar código libre de
errores y concentrarse en mantener la calidad del código con el paso del tiempo. Este último
punto es mucho más complejo para el software que para otros productos industriales [24].
Por lo tanto, la tarea de mantenimiento es dificultosa y requiere de un gran consumo de
tiempo si no se desea que se degrade la calidad de software.
Al realizar la tarea de mantenimiento de software, el conocimiento sobre el sistema es
importante. Entre el 40% y el 60% del esfuerzo realizado en mantener un sistema está
relacionado con el entendimiento del mismo [26]. Esto conlleva a que si es dificultoso
obtener la información necesaria sobre requerimientos que el sistema intenta satisfacer,
arquitectura utilizada, detalles técnicos, etc. el tiempo invertido en mantenimiento aumentará
considerablemente.
Así mismo, esta tarea no es un problema que debe ser resuelto o evitado. Es, en cambio, una
solución natural al hecho de que los sistemas de software deben mantenerse en sintonía con
el entorno y con las necesidades de los usuarios [26]. Lehman [29] marca como clave el
hecho de que los sistemas nunca están completos y siempre continúan evolucionando. A
medida que evolucionan, se vuelven más complejos a menos que se realicen acciones para
reducir su complejidad.
El mantenimiento de software está dado por 4 necesidades [28]:
1. Modificar el sistema para adaptarlo a nuevas necesidades (aproximadamente el 50%
de los proyectos de mantenimiento).
2. Adaptar el sistema a un entorno constantemente cambiante (aproximadamente el
25% de los proyectos de mantenimiento)
3. Corregir errores preventivamente (aproximadamente el 5% de los proyectos de
mantenimiento)
4. Corregir errores como resultado de un problema actual (aproximadamente el 20% de
los proyectos de mantenimiento)
Como puede apreciarse en los porcentajes, los mantenimientos más comunes son los
primeros dos. Esto ocurre porque la evolución del software está dada por dos grandes
razones. La primera razón es el cambio en los requerimientos, aspecto que se encuentra
fuertemente relacionado con el primer tipo de mantenimiento enumerado. La segunda razón
14
es el cambio constante de la tecnología y el software, aspecto que se encuentra fuertemente
relacionado con el segundo mantenimiento enumerado.
Estos dos mantenimientos, que son los que recubren la mayor cantidad de proyectos, están
fuertemente ligados con el refactoring de un sistema. El refactoring lleva a un código más
mantenible y extensible. Este lleva a mantener el sistema evolucionable y adaptativo a los
cambios de requerimientos del sistema.
2.2 Refactoring
Refactorizar se describe como el proceso de realizar un cambio en la estructura interna del
software para que éste sea más fácil de entender y modificar sin cambiar su comportamiento.
Es decir, se modifica la estructura interna de un sistema de software, pero sin alterar el
comportamiento externo del mismo [29]. Es decir, con el mismo conjunto de entradas, el
programa genera la misma salida, antes y después de someterse al proceso de refactoring.
Aunque no cambie el comportamiento del programa, refactorizar puede ayudar al diseño y
evolución de un software, reestructurando el programa de una forma que permita introducir
cambios más fácilmente [30]. Los cambios extremadamente complicados en programas mal
estructurados pueden incluir tanto refactoring como cambios en el comportamiento.
El concepto de refactoring también tiene una estrecha relación con la programación orientada
a objetos, debido a que este paradigma hace más factible el uso de esta técnica al hacer más
explícita la información estructural necesaria para refactorizar un programa [30]. Algunas de
las actividades que se realizan con este objetivo son: reducir la duplicación de código,
mejorar la cohesión, reducir el acoplamiento, mejorar atributos de calidad como la
legibilidad, flexibilidad, mantenimiento, etc.
Para realizar un refactoring, se deben cumplir las siguientes 3 etapas [31]:
Figura 2.1: Etapas del proceso de refactoring
15
Como se ve en la Figura 2.1, las etapas son:
1. Decisión para refactorizar: Esta etapa ocurre antes de realizar el refactoring
propiamente dicho. Consiste en las decisiones previas relacionadas con aspectos
personales (quienes lo van a realizar) y la situación actual del código (qué refactorings
se aplicarán para generar una solución valiosa).
2. Proceso de refactorización: Hace referencia a realizar las actividades de refactoring.
Se deben definir las herramientas que se utilizarán para las mismas.
3. Resultados de la refactorización: Se refiere al análisis posterior, que determinará si se
introdujo algún error y si realmente la solución generó algún valor agregado al código
existente.
Como se puede apreciar, el proceso de refactorización comienza al analizar la situación actual
del código para identificar oportunidades de refactorización. En este paso, para decidir qué
refactoring utilizar, se puede utilizar como guía la identificación de code smells [33].
La mayoría de los IDEs actuales soportan este enfoque, proveyendo herramientas para la
realizar refactorings de forma semi automática. De esta forma se reducen los tiempos de
debugging y testing [34].
2.3 Code Smells
Debido a que se decidió utilizar un code smell como guía para tomar la decisión de
refactorización, es importante definir qué es un code smell y por qué es importante
identificarlos.
Un code smell surge por la utilización de “malas prácticas” al desarrollar un sistema. Son
decisiones pobres de implementación que hacen que un sistema orientado a objetos sea difícil
de mantener [35]. Son las descripciones generales de código problemático y sirven para
ayudar a los desarrolladores a decidir cuándo un código necesita refactorización [36]. Una
vez aplicado el refactoring apropiado, en la mayoría de los casos se mejoran diversos aspectos
de calidad como mantenibilidad, comprensibilidad y reusabilidad. [37]
Los code smells surgen como una forma de clasificar de una manera lo más precisa posible
los diferentes problemas de diseño que se pueden identificar en un sistema. Dichos problemas
fueron detectados inicialmente por los investigadores como no-conformidad con principios
de diseño, violación de heurísticas de diseño, valores de métricas excesivos, falta de patrones
de diseño o incluso aplicación de anti-patterns [37].
Como se puede inferir, un code smell no es un error y no impide el correcto funcionamiento
de un sistema. Indican problemas de diseño y degradan diversos atributos de calidad,
incrementando el riesgo de costos altos de mantenimiento durante la evolución del sistema o
posibles errores en el futuro.
16
La forma de eliminar un code smell consiste en la aplicación de un refactoring apropiado,
mejorando la estructura del software sin modificar su comportamiento [37]. Teniendo
conocimiento que los code smells degradan la calidad de un sistema, y sabiendo que el efecto
acumulativo de sucesivos refactorings mejora la calidad del diseño, este tratamiento garantiza
una mejora sustancial en la calidad del código.
En la siguiente tabla se puede visualizar el catálogo de code smells realizado por Lanza y
Marinescu [3]:
Code Smell Descripción God Class Clases que tienden a centralizar la inteligencia del
sistema. Una God Class realiza demasiado trabajo
por sí misma, delegando únicamente los detalles
menores a un conjunto de clases triviales, usando los
datos de otras clases (Normalmente de Data Class).
Feature Envy Métodos más interesados en los datos de otras clases
que en los de su propia clase.
Data Class Clases “tontas” qué funcionan únicamente como
contenedoras de datos, sin ninguna funcionalidad
compleja. Sin embargo otras clases pueden depender
fuertemente de ellas.
Brain Method Métodos extensos que tienden a centralizar la
funcionalidad de una clase.
Brain Class Similar a God Class, con la diferencia de que a pesar
de ser clases excesivamente complejas, no acceden
abusivamente a datos de clases “satélite”.
Significant Duplication Porciones de código que contienen una cantidad
significativa de duplicación.
Intensive Coupling Método que se encuentra sujeto a demasiadas
operaciones en el sistema, y estas operaciones
proveedoras están dispersas en pocas clases.
Dispersed Coupling Similar a Intensive Coupling, pero las operaciones
proveedoras se encuentran dispersas en muchas
clases diferentes.
Shotgun Surgery Método del cual dependen un conjunto amplio de
otras operaciones dispersas en muchas clases. Es el
caso inverso de Dispersed Coupling.
Refused Parent Bequest Hace referencia a clases hijas en una jerarquía de
herencia que no utilizan los métodos declarados por
el padre.
Tradition Breaker Hace referencia a clases que en lugar de especializar
la clase de la cual heredan, simplemente agregan
nuevos métodos que tienen poca relación con
aquellos métodos heredados del padre.
Tabla 2.1: Code Smells catalogados por Lanza y Marinescu
Para poder realizar una refactorización basada en la eliminación de code smells, previamente
deben identificarse los mismos. Una opción es identificarlos automáticamente utilizando
métricas relacionadas.
17
2.3.1 Feature Envy
Feature Envy puede ser considerado el síntoma más común relacionado con problemas de
acoplamiento y cohesión [38]. Se define como:
“Un método que parece más interesado en los datos de otra clase que en los de su propia
clase” [3].
Este code smell surge cuando el desarrollador viola el principio de agrupar el
comportamiento con los datos relacionados [38]. Estos métodos acceden directamente a
través de métodos accesores (getters) a una gran cantidad de datos de otras clases. Esto
provoca un aumento de “efectos cascada” (el cambio en un método dispara cambios en otros
métodos y así sucesivamente) y disminuye la cohesión de un sistema. La forma de detectarlo
es contar el número de datos externos accedidos, y asegurarse de que los mismos provengan
de pocas clases, o de una única incluso. Las métricas que intervienen en este análisis son
descriptas en la Tabla 2.2 [3]:
Métrica Descripción Acceso a datos extranjeros (ATFD) Indica el uso directo de atributos de otras clases.
Localidad de los accesos a atributos (LAA) Indica la relación entre el acceso a atributos locales
y el acceso a atributos extranjeros.
Proveedores de datos extranjeros (FDP) Indica la cantidad de clases que proveen atributos
extranjeros al método.
Tabla 2.2: Métricas utilizadas por la herramienta
Una vez identificadas las métricas que intervienen, se debe definir un umbral que permita
decidir cuándo se está en presencia de una anomalía. Como se ve en la Figura 2.2, las tres
métricas intervienen en la identificación, y todas deben superar el umbral especificado para
generar una Feature Envy. En caso de que una de las reglas no se cumpla, no se considera la
existencia de este code smell.
Figura 2.2 Detección de Feature Envy
18
2.3.2 Refactoring de Feature Envy
Los refactorings utilizados para solucionar una Feature Envy son Move Method y Extract
Method. La idea es mover el método que sufre de este code smell a la clase que contiene los
datos que envidia. En primer lugar, se deben identificar los casos en los cuales es conveniente
realizar primero una extracción del fragmento del método que genera la Feature Envy, para
luego mover únicamente ese extracto a la clase correspondiente. De esta forma se encapsulan
los datos y la funcionalidad que manejan esos datos en una misma clase, mejorando la
modificabilidad y mantenibilidad, al tener en una misma ubicación los fragmentos de código
que muy posiblemente se modificarán en conjunto al evolucionar el sistema. De esta forma,
se reduce el nivel de acoplamiento entre clases.
El problema principal al aplicar estos refactorings es la posibilidad de afectar el
comportamiento original del sistema. Si esto llegase a ocurrir, se estaría violando la
definición de refactoring. A la hora de realizar Extract Method, únicamente se pueden extraer
fragmentos de código que mantengan la funcionalidad. Para asegurar esto, se utilizará la
práctica de Program Slicing [8]. En cuanto al uso de Move Method, se controlarán las
dependencias utilizadas por el método antes de realizarlo para no generar errores en el código.
2.3.2.1 Program Slicing
La técnica de Program Slicing es necesaria para realizar Extract Method. Es un método para
descomponer programas automáticamente analizando su flujo de datos y de control. El
programa reducido, llamado “slice”, es un programa independiente que garantiza una
representación fiel del programa original dentro del dominio del subconjunto de
comportamiento especificado [39].
Para mantener el control de flujo y datos, se genera un grafo de dependencias que sirve para
decidir si es posible extraer la porción (slice) de código. Esta técnica busca extraer la porción
más pequeña posible.
Todos estos controles son realizados por la API JDT de Eclipse. Aunque no utiliza la técnica
de Program Slicing directamente, es parte de la aplicación del refactoring considerado en este
informe.
2.3.2.2 Statements
Para realizar Extract Method, se debe dividir el método a nivel statement. Un statement es
una porción del código. El código a extraer debe ser una lista de statements, y no puede
contener ramas de ejecución que continúen por fuera del flujo del código seleccionado. Los
diferentes tipos de statement son: Block, ExpressionStatement, LabeledStatement,
SwitchCase, ForStatement, AssertStatement, EmptyStatement, BreakStatement,
SuperConstructorInvocation, Constructor Invocation, SynchronizedStatement, DoStatement,
LabeledStatement, WhileStatement, TryStatement, ThrowStatement, Variable Declaration
Statement, Return Statement, Type Declaration Statement.
19
Debido a que un Statement puede contener más Statements dentro de sí mismo anidados, la
forma de obtener todos los Statements de un método es recorrerlos a todos en profundidad
hasta que no queden más nodos por recorrer.
2.3.2.3 Problemática del Move Method
Para realizar satisfactoriamente un Move Method se deben tener en cuenta un conjunto de
precondiciones que aseguren mantener el comportamiento post-refactoring [40]. Entre ellos,
se puede mencionar que la clase a la que se mueve el método no debe contener un método
con el mismo nombre, ni ser declarada como una interfaz. Para una eficaz eliminación de
Feature Envy de un sistema deben satisfacerse todas las precondiciones, de lo contrario no
es aconsejable hacer la recomendación de refactorización de la solución al code smell.
20
Capítulo 3: Herramientas de refactorización y
análisis de Feature Envy
3.1 Enfoques del refactoring de Feature Envy
Para realizar el refactoring de una Feature Envy, se deben realizar dos pasos fundamentales:
identificar la oportunidad de refactoring, y luego aplicarla. Las herramientas analizadas en
esta sección tienen una particularidad: una vez identificada la Feature Envy, el único
refactoring recomendado y/o aplicado es Move Method. Ninguna herramienta considera una
extracción previa. En cuanto a las posibles acciones realizadas por las herramientas, se
pueden clasificar en tres enfoques:
Recomendación: Las herramientas incluidas en esta categoría sólo encuentran
métodos candidatos y recomiendan la aplicación del refactoring. No distinguen si el
refactoring es posible o si realmente se soluciona la Feature Envy al aplicarlo. En este
grupo se encuentran las herramientas MethodBook, MORE, c-JRecRef y Jmove (las
cuales serán analizadas en este capítulo).
Aplicación: Las herramientas incluidas en esta categoría realizan el refactoring
propiamente dicho, es decir, mueven el método de una clase a otra. No realizan
ningún tipo de análisis o recomendación en cuanto al método que se desea mover,
únicamente realizan el Move Method siempre y cuando se cumpla la regla de no
modificar el comportamiento del sistema ni generar errores de sintaxis. Un ejemplo
representativo de este grupo es la API nativa de Eclipse.
Recomendación y Aplicación: Las herramientas incluidas en esta categoría realizan
por completo el proceso de eliminación de code smells. Son más complejas que las
anteriores, ya que realizan ambos procedimientos e intentan obtener un resultado
válido. Son las únicas que automatizan por completo el proceso de refactorización de
Feature Envy. En este grupo se encuentra únicamente la herramienta JDeodorant.
3.2 Herramientas
En esta sección se presentarán las herramientas mencionadas anteriormente, con el fin de
profundizar el concepto de los enfoques que cada una realiza.
3.2.1 Herramientas de recomendación de refactoring
En esta sección se encuentran las herramientas que encuentran los métodos candidatos a
mover y realizan la recomendación, sin aplicar el refactoring. La mayoría de las herramientas
se encuentran en esta categoría, debido a la complejidad de implementar el refactoring Move
Method.
21
3.2.1.1 MethodBook
La herramienta MethodBook [40] propone oportunidades de aplicación del refactoring Move
Method con la finalidad de eliminar una Feature Envy.
El enfoque está basado en la técnica probabilística Relational Topic Models (RTM). Consta
de dos pasos: Identificar la “amistad entre métodos” e Identificar la clase envidiada.
El primer paso consiste en extraer la información textual y estructural del código fuente. Toda
esta información se almacena en diferentes matrices que luego son procesadas por el RTM
(Figura 3.1).
Figura 3.1: Proceso utilizado por MethodBook para encontrar recomendaciones
La información textual es representada por palabras en comentarios e identificadores en el
código fuente. Se almacena en la “Matriz de Documento Término a Término”. Es utilizada
por el RTM para definir relaciones semánticas entre métodos y su modelo de distribución.
La información estructural es diversa, por lo cual MethodBook hace un análisis estático para
obtener las dependencias estructurales entre métodos. Almacena los llamados a métodos en
la “Matriz de Interacción de Llamados” y el uso de variables compartidas en la “Matriz de
Datos Compartidos”. Adicionalmente, en la “Matriz de Diseño Original” conserva la
información de a qué clase pertenece cada método, entre otras cosas. Estas matrices
estructurales también son utilizadas para generar el modelo de distribución.
Una vez que posee toda la información, utiliza las matrices de Interacción de Llamados y la
de Datos Compartidos para representar la interacción entre métodos a lo largo de todo el
22
sistema. La Matriz de Diseño Original permite decidir si un refactoring afectará
positivamente la calidad del diseño del sistema.
Con toda esa información, el RTM genera la “Matriz de Similitud RTM”, que representa la
“amistad entre métodos”, es decir, la cantidad de responsabilidades que comparten todos los
pares de métodos, las estructuras de datos que comparten y la relación que tienen con las
mismas características o conceptos dentro del programa.
Una vez completado el paso de Identificación de Amistad entre métodos, se lo debe llevar a
un ámbito en el cual sea posible detectar una Feature Envy. Para comenzar el proceso de
Identificación de Clase Envidiada se analizan las clases a las cuales pertenecen los “mejores
amigos de cada método”. Si un método en la clase A tiene más amigos en la clase B que en
la propia, se presume que comparte responsabilidades con esta última clase, lo cual podría
indicar la presencia de Feature Envy. Por esta razón, lo que hace MethodBook es identificar
como clase envidiada a la que contenga el mayor porcentaje de métodos amigos. Si la clase
envidiada es la propia, no se sugiere ningún refactoring. Si no es el caso, el último paso es
analizar estáticamente el código para verificar que se cumplan todas las precondiciones que
garanticen mantener el comportamiento original luego de aplicar una operación de
refactoring. En caso de cumplirse, sugiere un refactoring. En caso de no cumplirse, elige
como nueva candidata a la próxima clase con más alto porcentaje de métodos amigos. Este
proceso se repite hasta que se obtiene una clase envidiada que cumpla las precondiciones o
la clase envidiada seleccionada sea la propia.
3.2.1.2 MORE
La herramienta MORE [41] es un recomendador automatizado de refactorings. A diferencia
de MethodBook, no se encarga únicamente de analizar Feature Envy. Posee tres objetivos
principales, los cuales son:
1. Mejorar la calidad de diseño.
2. Resolver code smells.
3. Introducir patrones de diseño.
Para recomendar una operación de refactoring, intenta encontrar el mejor trade-off entre estos
tres objetivos utilizando un algoritmo genético llamado “NSGA-III”.
Como se puede inferir, en este trabajo se va a analizar el segundo objetivo de esta
herramienta, centrándose en el code smell Feature Envy.
El esquema general de MORE se puede ver en la Figura 3.2.
23
Figura 3.2: Arquitectura del recomendador de refactorings MORE.
El componente llamado Detector de code smells es el encargado de identificar los diferentes
code smells existentes en el código. Utiliza un conjunto de reglas de detección, las cuales
representan diferentes smells, y las expresa como una combinación lógica de límites de
calidad y métricas, es decir, que define los márgenes de aceptación para decidir si el
componente que se está analizando es un code smell.
Las reglas que representan un método que sufre Feature Envy, son las que el autor clasifica
dentro de los tipos “Restricciones de Similitud basadas en Vocabulario” (VS) y
“Restricciones de Similitud basadas en Dependencias” (DS).
El tipo VS se encarga de definir si dos actores tienen vocabularios similares. Es utilizado para
definir la similitud semántica. El proceso para calcularla consiste en tokenizar los nombres
de los métodos, campos, variables, parámetros, tipos, etc., preprocesando indicadores con la
técnica Camel Case Splitter. Luego, se procesa la información obtenida utilizando la técnica
de similitud del coseno, representando a ambos actores como un vector n dimensional, donde
cada dimensión corresponde a un término del vocabulario. Por ejemplo, para dos actores C1
y C2, la ecuación sería la siguiente:
Donde y son los vectores n dimensionales, y los pesos wi se calculan previamente.
El tipo DS contiene las reglas que definen la conexión y la relación semántica entre dos
actores, para proponer refactorings asociados a cercanía semántica. Estas reglas son:
24
Llamadas compartidas a métodos (SMC): Se calcula utilizando un gráfico de
llamadas, cuyos nodos representan métodos y sus aristas representan llamadas entre
ellos (desde y hacia). Se considera la relación entre dos actores analizando los vecinos
de cada uno de ellos y viendo la relación existente. Se maneja tanto para llamadas
entrantes como salientes. Si se toman dos actores llamados C1 y C2 (clases) las
ecuaciones que defines esta regla son las siguientes:
Se calcula esta métrica usando el promedio entre las dos ecuaciones.
Accesos compartidos a campos (SFA): Se calcula capturando todas las referencias de
los campos usando análisis estático en todo el cuerpo de un método para identificar
dependencias basadas en accesos a los campos (lectura o modificación). Si se
consideran nuevamente los actores C1 y C2, y la función fieldRW(Ci) como aquella
que retorna los campos leídos y modificados por la clase Ci, la forma de calcular esta
regla es la siguiente:
Finalmente, en base a todos los refactorings propuestos, se realiza un cruce para definir
los que se recomendaran efectivamente. Como se indicó anteriormente, para mover un
método, tiene en cuenta los tipos VS y DS:
25
Tabla 3.1: Selección de refactorings basado en reglas de MORE
El cruce final es definido por el algoritmo genético NSGA-III, y se calcula la cantidad de
code smells resueltos con la siguiente ecuación (no hace un cálculo específico para
Feature Envy):
3.2.1.3 c-JRefRec
La herramienta c-JRecRef [42] es una herramienta de recomendación de oportunidades para
la aplicación del refactoring Move Method.
El enfoque de la misma tiene como principal objetivo tener en cuenta la semántica del código,
además del análisis de métricas para medir la efectividad de las recomendaciones.
Adicionalmente, se encarga de detectar las oportunidades de refactoring a medida que el
programador compila su código, basándose en los cambios introducidos por el mismo.
En primera instancia, utiliza el AST Parser del Eclipse Java Development Tools (JDT) para
analizar las relaciones entre clases y métodos. En base a ellas, realiza un grafo direccionado
de dependencias G = (V, E) donde los vértices V representan los métodos y campos de un
programa y las aristas E representan dependencias (llamados a métodos y acceso a campos)
entre ellos. Adicionalmente, obtiene la información semántica utilizada para la
recomendación extrayendo todos los identificadores, incluyendo nombres de paquetes,
clases, métodos, atributos, y parámetros para cada clase.
A su vez, provee 2 vistas para su análisis. La vista Class State View (Figura 3.3) es utilizada
para ver el estado de las clases antes y después de la aplicación de un refactoring.
26
Figura 3.3: Vista Class State View de la herramienta c-JRefRec
Para cada clase, provee 4 columnas con información relevante al análisis de oportunidades
de refactoring:
1. methods(C): Indica la cantidad de métodos definidos en la clase C.
2. edges(C): Indica la cantidad de aristas entrantes y salientes de la clase C.
3. clients(C): Indica la cantidad de clases que utilizan métodos o campos de la clase C.
4. dependents(C): Indica la cantidad de métodos o campos de otras clases accedidos
por la clase C.
Esta vista se refresca automáticamente al guardar/compilar el código fuente, y muestra en
rojo los cambios introducidos para cada indicador en relación al último estado guardado.
Adicionalmente, la herramienta provee una segunda vista llamada Refactoring Candidates
View (Figura 3.4) la cual presenta el método candidato a ser movido, la clase a la cual
debería ser movido y las métricas relacionadas para ayudar al desarrollador a tomar la
decisión.
Figura 3.4: Vista Refactoring Candidates View de la herramienta c-JRecRef
La forma de seleccionar las clases candidatas a ser movidas está dada por la similitud
semántica entre dos clases y por el análisis de dependencias.
27
La similitud semántica entre un método m y una clase c se calcula mediante la fórmula
SS(m, c) = cos(tf -idf(m),tf -idf(c)) utilizando los vectores tf-idf donde los métodos y las
clases son considerados como documentos individuales.
El análisis de dependencias se realiza teniendo en cuenta 3 factores:
1. Δedges(R, C): Es el número de aristas agregados/eliminados de la clase C al aplicar el
refactoring R.
2. Δclients(R, C): Es el número de clases clientes agregadas/eliminadas al aplicar el
refactoring R.
3. Δdependents(R, C): Es el número de dependencias agregadas/eliminadas al aplicar el
refactoring R.
En base a estos 3 indicadores y a la semántica, se definen las oportunidades de aplicación
de Move Method utilizando la siguiente función:
Δedges(R,Coriginal) + Δedges(R,Ctarget) + Δclients(R,Coriginal) + Δclients(R,Ctarget) +
Δdependents(R,Coriginal) + Δdependents(R,Ctarget) < 0 AND SS(m, Coriginal) < SS(m,Ctarget).
Con la presentación de las clases candidatas, concluye el flujo de c-JRecRef, y queda como
responsabilidad para el programador la aplicación o no de los refactorings recomendados.
3.2.1.4 JMove
La herramienta JMove [42] es un recomendador de oportunidades para la aplicación del
refactoring Move Method. Tiene la particularidad de ser más simple que las herramientas
anteriormente analizadas, y de no analizar en ningún momento el impacto de sus
recomendaciones sobre el code smell Feature Envy.
JMove utiliza un coeficiente de similitud, de esta forma, si identifica un método más similar
a una clase que a la clase en la que se encuentra, recomienda la aplicación del refactoring. El
esquema general del algoritmo utilizado consiste en la comparación entre la similitud de un
método f, la clase C en la que se encuentra y la similitud de dicho método con las demás
clases Ci del sistema:
Para lograrlo, la solución se encuentra implementada en 3 módulos:
Módulo de creación de dependencias: Establece la dependencia estructural entre un
método y una clase. Para cada método, establece la cantidad de llamados realizados
por la clase, acceso a atributos e instanciación de variables.
28
Módulo de cálculo de similitud: Para definir la similitud entre dos métodos f’ y f’’ se
utiliza la siguiente función:
donde a es el número de dependencias comunes a los 2 métodos, b es el número de
dependencias que únicamente se encuentran en el método f' y c es el número de
dependencias que únicamente se encuentran en el método f’’. S(f’,f’’) = 1 indica
similitud máxima y S(f’,f’’) = 0 indica que los métodos no tienen dependencias en
común. La forma que utiliza la herramienta para detectar la similitud entre un
método f y una clase C consiste en calcular la media aritmética de la similitud entre
f y todos los métodos de C.
Módulo de recomendación: Finalmente, dado el conjunto de clases T, la función
best_class(f, T) indica la clase más apropiada, es decir, la que posee mayor similitud
con el método.
Como se puede ver en la Figura 3.5, una vez realizado el análisis, JMove presenta los
resultados en la interfaz de Eclipse, indicando la clase candidata a refactorizar y la clase
destino propuesta por el recomendador.
Figura 3.5: Interfaz de JMove
3.2.2 Herramientas de aplicación de refactorings
En esta sección se encuentran las herramientas que implementan el refactoring Move
Method, sin realizar ningún tipo de recomendación o análisis en cuanto al método que se
desea mover, simplemente controlan las precondiciones necesarias para asegurar que no se
modifique el comportamiento de sistema y no se introduzcan errores de sintaxis.
29
3.2.2.1 Eclipse
La API nativa de Eclipse, posee la capacidad de realizar el refactoring Move Method. Es
importante aclarar que no hace ninguna recomendación, simplemente realiza la operación
on-demand.
Al intentar realizar un Move Method, en primera instancia analiza un conjunto de
precondiciones para garantizar la no modificación del comportamiento original del sistema
y la no generación de errores de sintaxis. Entre las más comunes, se encuentran la no
existencia de llamados recursivos y la comprobación de que el método no esté definiendo un
método abstracto en la jerarquía de herencias.
Posteriormente, Eclipse presenta las clases hacia las cuales es posible mover el método.
Únicamente tiene en cuenta las clases de los parámetros del mismo, y de variables de
instancia usadas. En caso de no existir parametrización o uso de variables de instancia, no se
permite realizar el Move Method al no tener candidatos.
3.2.3 Herramientas de recomendación y aplicación de
refactorings
En esta sección se encuentran las herramientas que realizan por completo el proceso de
eliminación de code smells, es decir, se encargan de recomendar posibles refactorings y
aplicarlos en caso de ser seleccionados. Son las únicas que automatizan por completo el
proceso de refactorización de Feature Envy.
3.2.3.1 JDeodorant
JDeodorant [25] es la única herramienta que actualmente se encarga de identificar,
recomendar y aplicar el refactoring Move Method para la resolución del code smell Feature
Envy. A diferencia de los recomendadores analizados anteriormente (sección 3.2.1), este
plugin de Eclipse no realiza un complejo análisis para la recomendación, simplemente utiliza
el ASTParser del Eclipse Java Development Tool (JDT) para analizar las relaciones entre
entidades y aplicar el refactoring.
El verdadero aporte de esta herramienta es la aplicación correcta del refactoring Move
Method al realizar una completa pre-evaluación de todos los posibles impactos sobre la
calidad del diseño del sistema y aplicar la más efectiva.
La forma de utilizar la herramienta es relativamente sencilla. Se debe abrir la ventana de
navegación para Identificar los code smells. Luego se accede a la pestaña específica de
Feature Envy para poder visualizar los refactorings propuestos por la herramienta, y
aplicarlos posteriormente desde el botón Aplicar Refactorings, como se ve en la Figura 3.6.
30
Figura 3.6: Presentación de Feature Envy de JDeodorant
Como se puede ver, la herramienta propone un ranking de refactorings a aplicar. Para
completar el proceso, se puede seleccionar un refactoring propuesto y presionar el botón
“Apply Refactoring” para implementar la solución sugerida.
Al realizar un análisis del código interno de JDeodorant, se puede apreciar que la
comprobación de pre-condiciones para realizar un Move Method es extremadamente
compleja y tiene en cuenta todos los inconvenientes posibles que podrían imposibilitar su
aplicación.
Finalmente, se ha comprobado que la recomendación y aplicación se condice con la
propuesta por diferentes autores, por los que esta herramienta, a nivel de refactoring de
Feature Envy, se considera correcta y de alta utilidad.
3.3 Criterios de comparación
En esta sección se definen los criterios para realizar la comparación entre las distintas
herramientas analizadas en la sección 3.2.
Categoría de la herramienta: se categoriza cada herramienta según la etapa de
refactoring que soluciona.
Una vez categorizada, se tienen en cuenta los siguientes criterios:
o Solución de Feature Envy: Define si la herramienta intenta solucionar el code
smell o no.
o Tipo: Define si la herramienta requiere asistencia del programador en alguna
de sus fases (automática o semi-automática)
o Errores post-refactoring: Define si la herramienta introduce errores de
compilación o cambia el funcionamiento del sistema.
31
3.3.1 Comparación y conclusiones
En la Tabla 3.2 se muestra cada categoría y la etapa de refactoring que intenta solucionar. La
mayoría de las herramientas disponibles se centran en la recomendación del refactoring Move
Method, debido a que existe muy poco soporte en la API de Eclipse para su implementación.
Únicamente JDeodorant aplica automáticamente este refactoring al realizar una compleja
implementación del análisis completo de pre-condiciones que se deben cumplir para poder
realizar el refactoring. Sin embargo, esta herramienta no se centra en un análisis complejo
para la recomendación, por lo que en muchas ocasiones no provee una recomendación óptima
para aplicar el refactoring Move Method.
Herramienta Enfoque de
recomendación
de Move
Method
Enfoque de
aplicación
de Move
Method
Enfoque de
recomendación
y aplicación de
Move Method
Sección
JDeodorant X 3.2.3
JMove X 3.2.1
MORE X 3.2.1
MethodBook X 3.2.1
c-JRecRef X 3.2.1
Nativa del IDE Eclipse X 3.2.2
Tabla 3.2: Categorías de las herramientas
En la Tabla 3.3 se pueden ver las herramientas junto con las prestaciones que proveen. Se
pueden encontrar datos sobre el enfoque de solución de Feature Envy, la participación del
desarrollador en el proceso de refactoring y los errores que introducen las herramientas al
realizar el refactoring.
Herramienta Soluciona
Feature Envy
Automática / Semi -
Automática
Errores post
refactoring
JDeodorant Sí Automática Sí
JMove No Semi-Automática No
MORE No Semi-Automática No
MethodBook No Semi-Automática No
c-JRecRef No Semi-Automática No
Nativa del IDE Eclipse No Semi-Automática No
Tabla 3.3: Características de las herramientas
Solo JDeodorant intenta solucionar automáticamente las Feature Envys detectadas en un
proyecto debido a que posee un enfoque de recomendación y aplicación de Move Method.
Esto se encuentra muy relacionado a la intervención del desarrollador en el proceso. La gran
mayoría de las herramientas tienen un enfoque orientado a facilitar la tarea del programador
mediante la identificación de oportunidades de refactoring. Sin embargo, no aplican
automáticamente el refactoring Move Method, por lo cual el programador está obligado a
32
mover manualmente el método seleccionado y realizar el control de dependencias,
asegurándose de no modificar el comportamiento del sistema. Es por esto que las demás
herramientas se consideran semi-automáticas, debido a que no pueden completar el proceso
sin la intervención del desarrollador.
La columna de errores post-refactoring muestra cuales son las herramientas que introducen
errores al aplicar el refactoring. JDeodorant es la única que lo hace debido a que es la única
que aplica el refactoring luego de una recomendación. A pesar de poseer un completo control
de pre-condiciones, se detectaron casos en los cuales genera errores detectables en tiempo de
compilación luego de realizar un Move Method. Por su parte la API Nativa de Eclipse, a
pesar de aplicar el refactoring, es más restrictiva y no permite la aplicación de Move Method
si detecta que se va a introducir un error.
A partir del análisis de los datos se puede determinar que las propuestas se centran en
identificar oportunidades del refactoring Move Method sin tener en cuenta la eliminación de
Feature Envy. Adicionalmente, se puede señalar que las herramientas recomiendan mover el
método completo a la clase candidata. Por esta razón, resulta interesante plantear un enfoque
que intente realizar una extracción previa al Move Method, para eliminar una Feature Envy
moviendo a la clase candidata únicamente las porciones de código que generan esta anomalía
de diseño.
33
Capítulo 4: Un enfoque iterativo para la
refactorización de Feature Envy
4.1 Refactorización de Feature Envy
Es común que con el paso del tiempo se degrade la calidad de un sistema, debido a los
cambios paulatinos que los desarrolladores deben introducir durante la evolución del
software, ya que muchas veces se realizan sin el total conocimiento de la arquitectura del
sistema y de sus requerimientos iniciales. El uso de malas prácticas, denominadas code
smells, ha sido establecido como un concepto para identificar patrones o aspectos del diseño
de software que pueden causar problemas para el desarrollo o el mantenimiento del sistema
[32].
Uno de los 21 code smells catalogados por Lanza y Marinescu [3] es Featury Envy. Este code
smell indica la existencia de métodos que parecen más interesados en los datos de otras clases
que en lo de su propia clase. Estos métodos acceden directamente o vía métodos accesores a
una gran cantidad de datos de otras clases [3]. Esto puede ser una señal de que el método está
ubicado en un lugar incorrecto y debe ser movido a otra clase.
Es necesario refactorizar las Feature Envy para mejorar la cohesión y evitar los “efectos
cascada” [3]. Es importante poner en una misma clase las cosas que cambiarán juntas [2].
Adicionalmente, la existencia de Feature Envy está relacionada directamente con la
existencia de otros code smells como God Class o Data Class (Figura 4.1), por lo que es
posible eliminar otros code smells al solucionar las Feature Envy de un sistema.
Figura 4.1 Correlación entre code smells. Lanza y Marinescu [3].
En este trabajo se propone un enfoque para la eliminación de las Feature Envy de un sistema
que facilite su evolución y mantenimiento. El enfoque consiste en el análisis del código de
34
un método identificado como Feature Envy para definir si es posible mover el mismo o un
fragmento del mismo a una clase candidata, y luego la aplicación automática de dichas
acciones. Estas acciones conllevarán a la eliminación del code smell, aumentando la
modificabilidad y extensibilidad del sistema. Además, se permite la visualización de las
soluciones generadas para que el desarrollador pueda analizarlas, observando las métricas
propuestas, y así encontrar la más adecuada para luego aplicar al proyecto.
En la resolución del code smell Feature Envy intervienen 2 refactorings diferentes: Extract
Method para obtener el fragmento de código y Move Method para moverlo a la clase a la que
debería pertenecer. Estos refactorings no son triviales debido al conjunto de precondiciones
a tener en consideración para no modificar la funcionalidad del sistema. Por ejemplo, para el
refactoring Move Method, se deben tener en cuenta un conjunto de precondiciones para
definir si es posible la aplicación del mismo
1. La clase objetivo no debe heredar un método que posea el mismo nombre que el
método a mover.
2. El método a ser movido no debe sobreescribir un método heredado en su clase
original.
3. El método a ser movido no debe ser synchronized.
4. El método a ser movido no debe contener asignaciones a campos de la clase origen
(incluyendo campos heredados).
5. El método a ser movido debe tener una relación uno a uno con la clase objetivo.
Es importante tener en cuenta estos factores para la aplicación del enfoque propuesto.
4.2 Esquema general de la solución iterativa de Feature Envy
El enfoque para la refactorización sigue un ciclo iterativo donde la entrada es una Feature
Envy y la salida es un conjunto de soluciones a la misma en caso de existir. Estas soluciones
son el conjunto de refactorings realizados junto con sus métricas asociadas.
Este enfoque consta de 6 actividades, aunque dependiendo las características del método,
puede requerir actividades adicionales para realizar extracciones.
1. Obtener características del método: Esta actividad recibe como entrada un método
el cual ha sido identificado previamente como Feature Envy. El objetivo de esta
actividad es recuperar las características específicas del método que ayudarán a
decidir cuál será la mejor forma de refactorizarlo.
2. Elegir las clases candidatas: En esta actividad se definen cuáles son las clases de las
cuales envidia el método, y se las prioriza para seleccionar las candidatas a las cuales
se moverá el método o un fragmento del mismo. El objetivo de esta actividad es
seleccionar las clases más apropiadas para intentar asegurar la eliminación de la
Feature Envy, de lo contrario puede ocurrir que la Feature Envy siga existiendo en la
nueva clase.
35
3. Seleccionar el fragmento de código a mover: En esta actividad se decide cuál es el
fragmento del método que no corresponde a la clase en la que se encuentra. Utilizando
la información obtenida en el paso 1, se puede decidir por no extraer ningún
fragmento del método y moverlo completamente. Finalmente, se aplican los
refactorings seleccionados solucionando de esta manera la Feature Envy.
4. Calcular métricas de la solución generada: Una vez encontrada la solución, se
procede con esta actividad, que consiste en calcular las métricas del código
pertinentes a la existencia de Feature Envy. De esta forma, el desarrollador puede
evaluar la calidad de la solución y definir si le parecen aceptables los valores
obtenidos.
Como se ve en la Figura 4.2, el proceso itera en las actividades 3 y 4 hasta encontrar
soluciones o hasta agotar las clases que pueden ser consideradas como candidatas para
realizar el refactoring.
Figura 4.2: Esquema general de la solución de Feature Envy.
Como se puede observar, se itera por cada clase candidata seleccionando el fragmento de
código a mover recomendada, acompañando cada solución con sus métricas. En este punto
se pueden dar 3 escenarios:
36
No se encontró solución a la Feature Envy.
El programador no desea aplicar ninguna solución propuesta.
El programador elige una solución.
Los primeros dos escenarios conllevan a la finalización del flujo de ejecución, dando como
resultado la no refactorización del code smell Feature Envy. El tercer caso permite continuar
el flujo con las últimas dos actividades:
5. Aplicar el refactoring: Cuando el desarrollador selecciona la solución que considera
más óptima, se procede a la aplicación efectiva de los refactorings que generan dicha
solución.
6. Corregir errores: Esta actividad es la única que queda completamente a cargo del
desarrollador. Se debe verificar si el refactoring Move Method ha introducido algún
error de código detectable en tiempo de compilación y corregirlo.
En cada iteración, se deben priorizar de manera lo más precisa posible las clases candidatas,
y seleccionar el mejor statement a extraer (o el método completo) para iterar la menor
cantidad de veces posible. La selección de clase se prioriza utilizando la métrica ATDF,
mientras que la selección de statement es dependiente de la heurística utilizada.
De esta forma, se itera hasta agotar las clases que pueden ser candidatas.
Para la aplicación de este enfoque, se optó por extender la herramienta Bandago [20]
perteneciente al plugin JSpIRIT [13] de Eclipse. Por lo tanto, la solución presentada es
aplicada para el lenguaje Java. JSpIRIT analiza código estáticamente y provee el método
catalogado como Feature Envy que se utiliza de entrada. Bandago provee la estructura
general para poder cumplir el ciclo de ejecución y presentar los resultados obtenidos de una
forma sencilla.
4.3 Desarrollo del enfoque iterativo para la refactorización de
Feature Envy
A continuación se detalla cada actividad involucrada en el enfoque junto con un ejemplo
guía. Este ejemplo consiste en un método afectado por el code smell Feature Envy y un
seguimiento de cada uno de los cambios realizados por cada actividad sobre el código Java
del mismo.
4.3.1 Actividad 1: Obtener características del método
Esta actividad recibe como entrada un método catalogado como Feature Envy. Esta entrada
es provista por la herramienta JSpIRIT. Como se ve en la Figura 4.3, JSpIRIT presenta una
lista de code smells junto con el método Java asociado. Se tomará como ejemplo el método
mapEntry perteneciente a la clase OptionsService tomado de la aplicacion jMoney, uno de
los casos de estudios analizados.
37
Figura 4.3: JSpIRIT Smells View
Como se puede ver en la Figura 4.3, se identifican diferentes tipos de code smells, y es el
usuario el que debe seleccionar la Feature Envy que servirá como entrada para la
refactorización. Para realizar esta acción, se utilizará la interfaz de la extensión de JSpIRIT,
llamada Bandago, la cual permite seleccionar un método afectado por un code smell y aplicar
un refactoring en caso de ser posible.
En esta actividad, se identifican todos los llamados a métodos propios y uso de variables de
instancia de la clase origen. En la Figura 4.4 se muestra la identificación variables de
instancia.
Figura 4.4: Llamados a variables de instancia de la propia clase del método ejemplo.
Al observar el método se puede definir que utiliza variables de instancia. Las variables
utilizadas son “entryStates”, “entryToOldCategoryMap” y “em”. Esta detección es realizada
mediante la interfaz provista por JSpIRIT. Al analizar la métrica Locality of Attribute
Accesses (LAA), la cual establece el porcentaje de uso de atributos locales, se define que se
38
están utilizando variables de instancia cuando dicha métrica es mayor a cero. Esta métrica se
calcula utilizando la siguiente fórmula:
Para el ejemplo presentado, el número de accesos a variables de instancia es 3, debido a que
se contabilizan los 3 accesos señalados en la Figura 4.4. En cuanto al número total de accesos,
se deben sumar los 3 accesos a variables de instancia y todos los accesos a parámetros y
variables locales del método. En este caso, se deben sumar todos los accesos a los parámetros
“e” y “oldEntry”, dando como resultado un total de 19 accesos. De esta forma, al reemplazar
en la ecuación presentada, puede observarse que la métrica LAA posee un valor mayor a 0:
El análisis de esta información para definir el refactoring a utilizar se realizará
posteriormente en la actividad 3.
4.3.2 Actividad 2: Elegir la clase candidata
Una vez identificadas las características del método, se procede a identificar la clase
candidata a la cual se debe mover el método. Con este objetivo, nuestro enfoque utiliza la
métrica Access to Foreign Data (cantidad de atributos de otras clases que utiliza el método)
debido a que se encuentra directamente relacionada con la existencia de Feature Envy. La
misma se obtiene calculando el número de llamados directos o indirectos (vía métodos getters
y setters) a campos de clases externas.
Teniendo en cuenta esta métrica, se analizan en profundidad las incidencias que generaron
que el valor de la misma supere el umbral considerado como normal, es decir, se contabiliza
la cantidad de llamados a clases externas. De esta forma, al identificar individualmente los
accesos a atributos o métodos de otras clases, se puede definir cuál es la clase que posee más
accesos utilizados por el método. Se seleccionó esta métrica porque, de las métricas
relacionadas con Feature Envy definidas por Lanza y Marinescu [3], es la que se encuentra
directamente relacionada con las clases utilizadas en exceso por el método, provocando el
code smell Feature Envy.
39
Figura 4.5 Identificación de llamados a clases externas
La Figura 4.5 muestra la identificación de llamados a clases externas involucradas en el
ejemplo presentado. Para obtener el valor de la métrica ATFD se debe contabilizar el total
de dichos llamados, por lo cual el valor de la misma para el ejemplo presentado es 17. Se
puede observar que se debió detallar el path completo de las clases externas que intervienen
debido a que poseen el mismo nombre. Para definir las clases que pueden ser consideradas
candidatas, se calcula el valor de la métrica ATFD para cada una de las clases extranjeras
involucradas.
Ranking Nombre de la clase Nombre del
parámetro
Valor ATDF
1 name.gyger.jmoney.model.Entry e 9
2 net.sf.jmoney.model.Entry oldEntry 8
Tabla 4.1: Priorización de clases externas accedidas por la Feature Envy
Como se detalla en la Tabla 4.1, se considera la clase name.gyger.jmoney.model.Entry como
la clase más envidiada (primera en el ranking) al ser la que recibe la mayor cantidad de
llamados por parte del método catalogado como Feature Envy. Al analizar el valor de ATDF,
se puede observar que la cantidad de llamados a net.sf.jmoney.model.Entry también es
significativa.
4.3.3 Actividad 3: Seleccionar el fragmento de código a mover
En esta actividad se utiliza la información obtenida en la actividad 1 (Sección 4.3.1) para
definir cuál es el fragmento del método que no corresponde a la clase en la que se encuentra.
Es decir, se analizarán las características propias del método para tomar la decisión.
El primer aspecto a tener en cuenta es si el método analizado utiliza variables de instancia de
su propia clase. El motivo de este control está dado por la posibilidad de no eliminar la
Feature Envy al mover el método a la clase candidata, debido a que los accesos a llamados
40
de variables de instancia de la clase en la cual se encuentra el método generen una Feature
Envy al encontrarse en una nueva clase.
En caso de no utilizar ninguno, se considera que el método puede ser movido completamente
a la clase candidata seleccionada en la actividad anterior (Sección 4.3.2) y la actividad actual
finaliza.
En caso de existir algún acceso a variables de instancia de la clase, se debe seleccionar el
fragmento de código del método que al ser movida de la clase original, elimina la existencia
de la Feature Envy identificada sin generar este code smell en la nueva clase. Para lograr este
objetivo, se optó por la utilización de una heurística que consta de dos pasos:
1. Identificar la primera y última ocurrencia de un llamado a un método o atributo de la
clase candidata.
2. Seleccionar el statement o conjunto de statements más pequeño que contiene ambos
llamados. Este paso evita la rotura de flujos de control, por ejemplo, cortar una
sentencia IF a la mitad.
Figura 4.6: Selección de statement o conjunto de statements a extraer
Como se ve en la Figura 4.6, estos pasos se repiten para cada clase candidata identificada.
Para el método ejemplo, esta actividad genera dos resultados. El primero se encuentra
detallado en la Figura 4.7.
41
Figura 4.7: Selección del statement candidato a ser extraído para la clase
name.gyger.jmoney.model.Entry
Como se puede observar, en este caso la primera y última ocurrencia no se encuentran en
ningún flujo de control, por lo cual es posible seleccionar un statement que comience en la
primera ocurrencia y termine en la última. Otro factor importante es la existencia de una
variable de instancia de la clase original en dicho statement, pero se puede corroborar
analizando la métrica LAA (Locality of Atribute Acceses) que la relación entre el uso de
variables locales y llamados externos no es significativa. Su cálculo se obtiene mediante la
siguiente ecuación:
Para el statement del ejemplo, el número de accesos a variables de instancia es 1, ya que
únicamente se realiza un acceso a la variable de instancia entryStates. En cuanto al número
total de accesos, se incluye el acceso antes mencionado y todos los llamados a métodos de
los parámetros e y oldEntry, dando como resultado un total de 16 accesos.
De esta forma, se visualiza que el statement seleccionado se sigue encontrando en los límites
establecidos por Lanza y Marinescu [3] (LAA < ONE THIRD), y se procede a seleccionarlo
como candidato a ser extraído.
4.3.4 Actividad 4: Calcular las métricas de la solución generada
Una vez seleccionado el fragmento de código que debe ser movido a la clase candidata, el
objetivo de esta actividad es analizar el fragmento seleccionado para el cálculo de métricas.
Para lograr este objetivo, se procede a realizar una copia de la clase objetivo. En esta copia
se aplicará el refactoring Move Method del fragmento seleccionado para poder calcular las
métricas sin afectar la clase original. Una vez realizado el cálculo, la copia es eliminada del
proyecto.
42
Las métricas permiten al desarrollador evaluar la calidad de cada solución. Las métricas
calculadas son las tres asociadas a la existencia de Feature Envy (ATFD, LAA y FDP). La
métrica Access to Foreign Data (ATFD) indica el uso directo de atributos de otras clases. La
métrica Locality of Attribute Accesses (LAA) indica la relación entre el acceso a atributos
locales y el acceso a atributos extranjeros. Finalmente, la métrica Foreign Data Providers
(FDP) indica la cantidad de clases que proveen atributos extranjeros al método.
En la Figura 4.8 se observa el cálculo de las métricas de la solución generada. Al comparar
los valores del método original con los de la solución propuesta, se puede observar que la
métrica ATDF disminuyó su valor considerablemente. Esto se debe a que una gran parte de
los accesos a clases extranjeras (los cuales se contabilizan para obtener el valor de esta
métrica) pertenecen a la clase a la cual se moverá el método, por lo que dichos llamados
dejarán de ser extranjeros y pasarán a ser locales a la clase en la que se encuentran. Por esta
misma razón, la relación entre número de accesos locales y número total de accesos aumenta,
dando como resultado un valor más elevado al calcular la métrica LAA. El valor de la métrica
FDP disminuye al reducirse el número de clases extranjeras utilizadas por el método.
Figura 4.8: Cálculo de las métricas de la solución generada (Bandago View)
El análisis que debe realizar el desarrollador debería basarse en los siguientes conceptos:
ATFD: Se debe considerar positiva la disminución del valor de esta métrica. Esto
implicaría que la solución accede a una menor cantidad de datos de clases externas.
LAA: Se debe considerar positivo el aumento del valor de esta métrica. Esto
implicaría que la solución utiliza un mayor porcentaje de variables propias en relación
al uso total de variables.
FDP: El aumento significativo en el valor de esta métrica implica la eliminación de
la Feature Envy. Esto se debe a que el uso de variables y métodos externos no se
concentraría únicamente en un pequeño número de clases.
4.3.5 Actividad 5: Aplicar el refactoring
Esta actividad consiste en la aplicación efectiva de la solución seleccionada.
Una vez presentadas las métricas para las soluciones generadas, el desarrollador podrá
seleccionar una de ellas para la aplicación efectiva del refactoring. La herramienta se encarga
de mostrar a la izquierda el método original y a la derecha el fragmento de código que se
extraerá.
43
Figura 4.9: Selección de una solución para Feature Envy (Bandago Wizard)
De esta forma, el desarrollador puede ver aplicada la solución propuesta, en la cual se extrae
el statement o conjunto de statements identificados por la actividad 3.
4.3.6 Actividad 6: Corregir errores
Esta actividad es la única que queda completamente a cargo del desarrollador. Se debe
verificar que la aplicación del refactoring Move Method no haya introducido errores de
código detectables en tiempo de compilación.
Figura 4.10: Método movido a la clase candidata
En la Figura 4.10 se puede ver que el refactoring ha introducido un error detectable en tiempo
de compilación a causa del llamado a una variable de instancia de la clase original. Queda a
cargo del desarrollador la corrección de ese error para completar el refactoring.
44
4.4 Implementación de la solución
En esta sección se describen los aspectos relevantes involucrados en la implementación de la
solución.
4.4.1 Aplicación de refactorings
Para el caso de Extract Method, JDT ya tiene implementado el control de precondiciones
necesarias para decidir si es posible la aplicación del refactoring sin introducir errores de
compilación o modificar el comportamiento del sistema.
Para el caso de Move Method, es insuficiente depender únicamente del conjunto de
precondiciones establecidas por el IDE Eclipse. Esto se debe a que Eclipse implementa
precondiciones débiles para este refactoring [44, 45, 46]. Se denominan precondiciones
débiles cuando el conjunto de precondiciones implementadas son insuficientes para
garantizar la preservación del comportamiento del sistema al aplicar un refactoring. Por esta
razón, es necesario analizar las cinco precondiciones adicionales propuestas por la
herramienta JDeodorant y mencionadas por Sales et al. [47]:
1. La clase objetivo no debe heredar un método que posea el mismo nombre que el
método a mover.
2. El método a ser movido no debe sobreescribir un método heredado en su clase
original.
3. El método a ser movido no debe ser synchronized.
4. El método a ser movido no debe contener asignaciones a campos de la clase origen
(incluyendo campos heredados).
5. El método a ser movido debe tener una relación uno a uno con la clase objetivo.
Este enfoque propone encapsular el Move del método realizando un Extract Method en todas
las situaciones, incluso cuando se pretende mover completamente el método. En la Figura
4.11 se presenta un ejemplo de la refactorización realizada por el enfoque propuesto. En la
parte izquierda se puede ver el método original. Este es el código analizado por JSpIRIT, el
cual es enviado a Bandago para hallar un conjunto de soluciones. En la parte derecha de la
figura se puede ver el fragmento de código extraído por la heurística y cómo este es
reemplazado en el método original. En lugar de mover el método completo a la clase
candidata, se realiza un extract previo que previene los conflictos señalados en las
precondiciones 1 y 2, así como inconsistencias en los llamados ya existentes a dicho método
en todo el sistema, debido a que el método original conserva el mismo nombre.
45
Figura 4.11: Extracción de un método previo a ser movido.
En cuanto a la precondición 4, este escenario particular introduce errores detectables en
tiempo de compilación que deben ser solucionados manualmente por el desarrollador. Estos
errores se consideran aceptables con el objetivo de restringir una menor cantidad de
refactorizaciones. Estos casos se analizarán en profundidad durante el desarrollo del enfoque,
debido a que la corrección de errores es una actividad contemplada por el esquema de la
solución planteada.
Con respecto a las precondiciones 3 y 5, no se realizó ningún control debido a la dificultad
que plantea la detección de estos escenarios.
4.4.2 Vista arquitectónica de Bandago
Se presenta en la Figura 4.12 un diagrama de contexto [43] de Bandago. JSpIRIT detecta los
Code Smells de un proyecto, priorizados según su importancia de refactorización. De este
conjunto de Code Smells, el desarrollador selecciona uno para hallar las posibles soluciones.
La Figura 4.12 describe la interacción entre JSpIRIT y Bandago en el caso que el Code Smell
seleccionado sea una Feature Envy. El sistema solo recibe como entrada la Feature Envy
seleccionada por el desarrollador. Luego, el desarrollador elige una de las soluciones
provistas para aplicar efectivamente en el código original, generando una solución final al
problema seleccionado con anterioridad en la herramienta JSpIRIT.
46
Figura 4.12: Diagrama de contexto de Bandago.
La Figura 4.12 presenta una visión de la arquitectura de Bandago usando la vista de
componentes y conectores [43]. Todos los componentes de este proyecto se ejecutan
utilizando la plataforma Eclipse como soporte.
En el catálogo de elementos de la tabla 4.2 se detalla cada elemento de la arquitectura
representado en la vista.
Elemento Descripción
JSpIRIT Esta es una herramienta externa que se encarga de encontrar todos
los Code Smells de un sistema.
Bandago genera una extensión a una vista de esta herramienta y se
acopla a su vista.
Eclipse JDT Es la plataforma brindada por Eclipse para poder generar,
comprobar y ejecutar una refactorización al código Java. Se encarga
de la modificación directa de la ICompilationUnit.
Eclipse Platform Eclipse es una plataforma de integración de herramientas de código
abierto. Esta contiene un ambiente de desarrollo de programación
Java ofreciendo un alto nivel de productividad y flexibilidad.
Además, puede ser ejecutado en una gran variedad de sistemas
operativos. Bandago fue desarrollado sobre Eclipse.
47
Eclipse Platform
Runtime
Execution
Eclipse provee el runtime event manager para el manejo y control
de las interfaces de usuario. El mismo implementa el estilo
arquitectónico implicit invocation. Cuando el event manager
publica un evento generado por una acción de usuario como un
click de un botón, draganddrop, etc., entonces los componentes que
están suscritos a estos eventos serán invocados y activados.
Bandago
Refactoring Core
Este componente contiene toda la funcionalidad para soportar el
enfoque de eliminación del Code Smell Feature Envy, generando
varias soluciones al problema mediante el uso de una heurística que
respeta una interfaz. De esta manera, se brinda la posibilidad de
desarrollar distintas heurísticas a futuro y poner el foco en distintas
estrategias para analizar el Code Smell. En base a esto, se puede
decidir el fragmento de código a extraer. La idea principal es
desacoplar el análisis que se realiza para decidir el fragmento de
código a mover, de todo lo necesario para realizar el refactor
propiamente dicho, dando la posibilidad de analizar el code smell
desde diferentes enfoques.
Cuando se quiere eliminar las Feature Envy de un proyecto se
interactúa con la herramienta JSpIRIT para obtener todos los Code
Smells y luego con la User Interface views & controls se solicita
cuál de estas desea eliminar. Luego se muestran en otra vista (Code
Smells Solutions) todas las soluciones generadas con sus
respectivas métricas al usuario.
User Interface
views & controls
Es un conjunto de componentes de interfaces de usuario (vistas,
cuadros de dialogo and action handlers) que componen a Bandago.
Estos presentan la interfaz de usuario y a través de ella se provee la
funcionalidad que los desarrolladores van a utilizar. El usuario
puede interactuar con los wizards para realizar las refactorizaciones
encadenadas. Además, se puede visualizar las soluciones
propuestas.
ICompilationUnit Este es el archivo que contiene todo el código Java. Es la manera de
representar y modificar todo el acceso al código fuente de un
proyecto en la plataforma de Eclipse. Es donde se aplica la
refactorización y se mantiene un archivo de estos por cada solución
generada.
Code Smell
Feature Envy
Este archivo contiene la información que genera la herramienta
JSpIRIT. Contiene el código fuente del Code Smell identificado y
más información relevante como el tipo, donde se encuentra y qué
clases están afectadas.
Tabla 4.2: Elementos de la arquitectura de Bandago.
48
Figura 4.13: Arquitectura de alto nivel de Bandago.
El componente Bandago Refactoring Core es considerado el más importante ya que se
encarga de generar y ejecutar todas los posibles refactorizaciones. También este componente
se encarga de hacer el traspaso de información entre el plugin JSpIRIT y Bandago,
obteniendo así, todos los code smells de un proyecto con sus respectivos rankings. Todas las
decisiones tomadas por el desarrollador, como la elección del Code Smell a refactorizar, son
a través del componente User Interface views & controls que a su vez se comunica con el
Eclipse Runtime.
49
Capítulo 5: Casos de estudio
5.1 Proyectos evaluados y operatoria de la evaluación
En este capítulo se evalúa el enfoque propuesto respondiendo tres preguntas de investigación:
RQ#1: ¿Qué porcentaje de Feature Envy son automáticamente solucionadas por el
enfoque propuesto, sin necesidad de intervención del desarrollador?
RQ#2: ¿Solucionar las Feature Envy permite solucionar otros Code Smells?
RQ#3: ¿Son complementarias las soluciones identificadas por el enfoque propuesto
y por JDeodorant en la refactorización de Feature Envy?
Para responder las preguntas de investigación (Research Questions) se tomaron 10 proyectos
Java para ser analizados por Bandago, los cuales fueron obtenidos de Qualitas Corpus [44],
una colección de sistemas open source utilizados para fines de investigación. En la tabla 5.1
se listan los proyectos utilizados.
Nombre del sistema Cantidad de clases
Apache-jspf-resolver 140
Fitjava 95
Jmoney 47
Jparse 75
Jpf 139
Junit 1077
MobileMedia 51
Oscache 115
Quickserver 199
Squirrel 73
Total 2011
Tabla 5.1: Proyectos evaluados
50
Para llevar a cabo los experimentos, se tomaron como entrada las Feature Envy encontradas
por el plugin JSpIRIT [13]. Luego, se ejecutó el enfoque sobre cada una de las entradas
identificadas para su análisis.
Se analizaron individualmente las Feature Envy y se refactorizaron para intentar solucionar
el code smell. Como resultado se obtuvieron los códigos fuente de cada una de las clases
refactorizadas que luego fueron analizados.
Para realizar el análisis de los resultados, fueron tomados los siguientes datos de cada
sistema, obtenidos a partir de la ejecución de la herramienta:
Se creó un listado con los métodos identificados como Feature Envy.
Se generó un archivo que contiene los Code Smells del sistema, tanto para el código
original como para el sistema refactorizado.
Se calcularon las métricas individuales de cada método identificado como Feature
Envy, tanto para el original como para el refactorizado. También se recolectó la
información de la cantidad de soluciones identificadas y de si se introdujeron errores
detectables en tiempo de compilación.
Se generó un log que contiene las métricas de cada Feature Envy resuelta.
Para facilitar el análisis y visualización de los datos se decidió plasmar la información de los
code smells identificados por JSpIRIT en una base de datos, para facilitar la visualización de
la información obtenida. Se crearon dos tablas, una con la información relativa a la cantidad
de code smells de cada sistema analizado antes de refactorizar todas las Feature Envy
posibles, y otra con la misma información post-refactoring. De esta forma fue posible analizar
tanto las Feature Envy solucionadas como el impacto de dichas soluciones sobre los otros
code smells de un sistema.
Se calcularon las métricas asociadas a la existencia de Feature Envy (ATFD, LAA y FDP).
La métrica Access to Foreign Data (ATFD) indica el uso directo de atributos de otras clases.
La métrica Locality of Attribute Accesses (LAA) indica la relación entre el acceso a atributos
locales y el acceso a atributos extranjeros. Finalmente, la métrica Foreign Data Providers
(FDP) indica la cantidad de clases que proveen atributos extranjeros al método. En cuanto a
la obtención de las mismas, debido a que no fue posible encontrar una herramienta de análisis
de métricas que identificara las métricas relacionadas con Feature Envy se analizaron
individualmente al refactorizar cada Feature Envy y se persistieron en la base de datos para
su análisis.
El análisis realizado se lleva a cabo refactorizando cada Feature Envy encontrada en un
sistema. El proceso de refactorización es aplicado automáticamente por el enfoque
implementado.
Como se puede observar en la Figura 5.1, la operatoria del experimento consiste en recibir
como entrada un proyecto Java y para cada Feature Envy encontrada, calcular mediante una
heurística, el conjunto de soluciones posibles. Estas soluciones y sus respectivas métricas se
51
almacenan en una base de datos para su posterior análisis. Para completar la salida, se obtiene
el conjunto de proyectos refactorizados.
Figura 5.1: Diagrama de la operatoria del experimento
5.2 Características de las Feature Envy
Al avanzar en la recolección de datos, fue posible identificar las características generales de
las Feature Envy identificadas en los sistemas analizados.
En primer lugar, se define el universo de Feature Envy utilizadas para el caso de estudio. En
la Tabla 5.2, se enumeran la cantidad de Feature Envy de cada sistema.
Nombre del sistema Cantidad de Feature Envy
Apache-jspf-resolver 28
Fitjava 31
Jmoney 9
Jparse 50
Jpf 43
Junit 46
52
MobileMedia 10
Oscache 42
Quickserver 45
Squirrel 41
Tabla 5.2: Cantidad de Feature Envy por proyecto
De esta forma, se puede ver que fueron analizadas un total de 345 Feature Envy para obtener
los datos utilizados en el caso de estudio.
Una vez definido el universo de análisis, fue posible centrarse en características propias de
las Feature Envy identificadas. Como aspecto importante, se pueden observar los valores
promedio de las métricas relacionadas a este code smell obtenidas del análisis de todos los
sistemas.
Figura 5.2: Boxplot para la métrica ATFD
Como se ve en la Figura 5.2, la métrica ATFD tiende a ser muy alta, con una mediana de
5,295 considerando el total de los sistemas analizados. Esto significa que los métodos
identificados utilizan una elevada cantidad de atributos o métodos pertenecientes a otras
clases. A su vez, al poseer valores bajos de la métrica FDP, fue posible identificar clases
candidatas que recibían una gran cantidad de accesos a sus atributos desde el método
identificado como Feature Envy.
53
Figura 5.3: Boxplot para la métrica LAA
Como se ve en la Figura 5.3, para la segunda métrica, LAA, el valor promedio dio un
resultado inesperadamente bajo, con una mediana de 0,02. Esto significa que la mayoría de
los métodos identificados como Feature Envy no utilizaban ninguna variable de instancia o
método propio, con lo cual toma aún más sentido la necesidad de mover dicho método de
una clase a la cual no pertenece.
Figura 5.4: Boxplot para la métrica FDP
En último lugar, como se puede observar en la Figura 5.4, se identificó el promedio de clases
envidiadas por cada Feature Envy. Como era esperado, el resultado de la mediana fue 1,5.
Adicionalmente, se puede observar que la mayoría de los valores se encuentran contenidos
entre la mediana y el cuartil 1 (q1), con lo cual la tendencia es cercana a 1. Esto se debe a los
bajos valores de la métrica FDP para los métodos, un factor necesario para estar en presencia
de una Feature Envy, el cual reduce el universo de posibles clases envidiadas.
54
5.3 RQ#1: ¿Qué porcentaje de Feature Envy son automáticamente
solucionadas por el enfoque propuesto, sin necesidad de intervención del
desarrollador?
En esta sección se abordó la RQ#1 con el objetivo de analizar el porcentaje de Feature Envy
que se logran solucionar, diferenciando las soluciones completamente automatizadas de las
que requieren intervenciones adicionales por parte del desarrollador.
5.3.1 Hipótesis
Para analizar el porcentaje de Feature Envy solucionadas se analiza el conjunto de code
smells identificados por JSpIRIT a partir del código original de cada proyecto. Luego se
compara con el conjunto de code smells identificados luego de refactorizar todas las Feature
Envy posibles. Además, se tiene en cuenta si dicha refactorización necesitó la intervención
del desarrollador para dejar el código del método en un estado consistente, sin errores
detectables en tiempo de compilación. La hipótesis es que la herramienta permite solucionar
de los proyectos al menos un 25% de las Feature Envy detectadas por JSpIRIT.
Se establece este número como umbral para la hipótesis presentada por dos motivos:
Al utilizar la API JDT de Eclipse, como se mencionó en el capítulo 3, existirá un
número considerable de métodos que no cumplirán con las condiciones requeridas
para realizar el refactor Move Method.
Debido a que el objetivo del enfoque es la identificación de soluciones y no la
implementación del conjunto de precondiciones y postcondiciones para asegurar la
no introducción de errores luego de la aplicación del refactoring Move Method, un
alto porcentaje de soluciones contiene errores, por lo que requieren intervención del
desarrollador.
Formalizando:
H0: La herramienta soluciona al menos un 25% de las Feature Envy
H1: La herramienta soluciona menos de un 25% de las Feature Envy
Se prueba esta hipótesis comparando el conjunto de Feature Envy que afectan a cada proyecto
antes de ser refactorizado con el conjunto de Feature Envy obtenidas luego de refactorizarlos
con la herramienta. De esta manera se puede encontrar el porcentaje de resolución de Feature
Envy de la herramienta. Conjuntamente se analiza el porcentaje de Feature Envy que se
refactorizaron de forma completamente automática y aquellas que requirieron la intervención
del desarrollador para corregir errores.
5.3.2 Análisis e Interpretación
A partir de comparar los conjuntos de code smells de cada proyecto realizando el cruce de
datos pertinente en la base de datos generada, se realizaron la Tabla 5.3 y la Tabla 5.4.
Analizando la primera tabla se puede concluir que de un total de 345 Feature Envy
detectadas, el 4,06% fueron solucionadas sin la intervención del desarrollador. Analizando
55
la Tabla 5.4 el porcentaje se eleva considerablemente, concluyendo que de las 345 Feature
Envy el 33,33% fueron solucionadas con la intervención del desarrollador. Esto ocurre
debido a que el enfoque está orientado a resolver el code smell Feature Envy, siendo una
tarea que excede a este trabajo el control de precondiciones para no introducir errores al
realizar un Move Method. El mejor porcentaje de resolución obtenido para un proyecto fue
21,43% automáticamente (apache-jspf-resolver) y 73,17% luego de la corrección de errores
(Squirrel). En cuanto a los peores porcentajes obtenidos, se identificó un 0%
automáticamente para 6 proyectos diferentes y un 4,34% luego de la intervención del
desarrollador para el proyecto junit. El alto número de proyectos con 0% de resolución
automática se debe a que, como se mencionó en el planteo de la hipótesis, el enfoque no está
centrado en identificar el conjunto de precondiciones y postcondiciones previos a la
aplicación del refactoring Move Method. Esto conlleva a que la gran mayoría de las
soluciones identificadas requieran intervención del desarrollador.
Nombre del sistema Cantidad de FE
detectadas
Cantidad de FE
solucionadas
Porcentaje
Apache-jspf-resolver 28 6 21,43%
Fitjava 31 3 9,67%
Jmoney 9 0 0%
Jparse 50 2 4%
Jpf 43 2 4,76%
Junit 46 0 0%
MobileMedia 10 0 0%
Oscache 42 0 0%
Quickserver 45 0 0%
Squirrel 41 1 2,44%
Totales 345 14 4,06%
Tabla 5.3: Resultados de Feature Envy analizadas y resueltas automáticamente
56
Nombre del sistema Cantidad de FE
detectadas
Cantidad de FE
solucionadas
Porcentaje
Apache-jspf-resolver 28 7 25%
Fitjava 31 14 45,16%
Jmoney 9 4 44,44%
Jparse 50 12 24%
Jpf 43 15 35,71%
Junit 46 2 4,34%
MobileMedia 10 2 20%
Oscache 42 13 30,23%
Quickserver 45 16 35,55%
Squirrel 41 30 73,17%
Totales 345 115 31,30%
Tabla 5.4: Resultados de Feature Envy analizadas y resueltas luego de la intervención por
parte del desarrollador
Realizando un análisis integral de porcentaje de resolución, sin discriminar los resultados de
acuerdo a la intervención del desarrollador, es posible observar en la Tabla 5.5 que de las 345
Feature Envy detectadas, el 37,39% fueron resueltas. El mejor resultado obtenido sigue
siendo 75,61% (Squirrel). En cuanto al peor porcentaje obtenido, se identificó un 4,34% para
el proyecto junit.
57
Nombre del sistema Cantidad de FE
detectadas
Cantidad de FE
solucionadas
Porcentaje
Apache-jspf-resolver 28 13 46,43%
Fitjava 31 17 54,84%
Jmoney 9 4 44,44%
Jparse 50 14 28%
Jpf 43 17 40,47%
Junit 46 2 4,34%
MobileMedia 10 2 20%
Oscache 42 13 30,23%
Quickserver 45 16 35,55%
Squirrel 41 31 75,61%
Totales 345 129 37,39%
Tabla 5.5: Resultados de Feature Envy analizadas y resueltas
A partir del análisis de las Feature Envy, se detectó un alto porcentaje de métodos en los
cuales fue necesario extraer completamente el mismo y no solo una porción (89,15%),
como se puede ver en la Figura 5.5.
58
Figura 5.5: Extracción Total vs Extracción Parcial
Esto se debe a dos grandes factores. El más importante es que, cómo se indicó en la sección
5.2 (Características de las Feature Envy), un gran porcentaje de las mismas no posee accesos
a atributos (LAA = 0), por lo cual, de acuerdo a la estrategia del enfoque, se define extraer
completamente el método. En segundo lugar, una gran cantidad de métodos en un sistema
poseen el último acceso a una clase extranjera dentro de un statement indivisible (Por
ejemplo, un FOR) y por lo tanto se debe mover la totalidad del método para no alterar el
comportamiento del sistema.
El otro comportamiento detectado es la identificación de más de una solución. Como se puede
ver en la Figura 5.6, la cantidad de Feature Envy en las cuales se identifica más de una
solución es realmente baja.
Figura 5.6: Cantidad de soluciones identificadas
59
Para comprender esta relación, es necesario tener en cuenta cómo funciona la API JDT de
Eclipse, la cual fue utilizada para la aplicación del refactoring Move Method. El universo de
clases a las cuales se permite mover un método es limitado. Para que sea posible realizar este
refactoring sobre una clase candidata, es decir, mover el método a dicha clase, es necesario
que los accesos a la clase candidata sean realizados a través de un parámetro del método
catalogado como Feature Envy, o a través de una variable de instancia de la clase original.
Esta limitación genera una baja importante en el universo de soluciones, debido a que, para
poder aplicar una solución, es necesario seleccionar una clase candidata y que a su vez
Eclipse permita la aplicación del refactoring. Esta limitación puede observarse en la Figura
5.7 tomando el ejemplo del método MusicAlbumData.getMusicFromRecordStore del
proyecto MobileMedia.
Figura 5.7: Limitaciones de Eclipse al aplicar el refactoring Move Method
Con los resultados obtenidos se puede concluir que la hipótesis H0 es rechazada ya que el
enfoque, sin introducir errores, soluciona el 4,06% de las Feature Envy detectadas,
aceptándose la hipótesis H1.
5.4 RQ#2: ¿Solucionar las Feature Envy permite solucionar otros code
smells?
En esta sección se analizan los code smells relacionados con las Feature Envy y su efecto
luego de que las Feature Envy fueron refactorizadas.
5.4.1 Hipótesis
Para responder la research question se realiza una comparación entre el listado de code smells
generado por JSpIRIT a partir del código original de cada proyecto con respecto al generado
luego de realizar el refactoring. Dichos listados son persistidos en una tabla de una base de
datos para cada proyecto analizado. Se analizan únicamente los code smells detectados por
JSpIRIT que estén relacionados con la Feature Envy que son God Class, Intensive Coupling,
Shotgun Surgery, Tradition Breaker y Data Class. Formalizando:
60
H0: El enfoque soluciona code smells relacionados con el refactoring de Feature
Envy.
H1: El enfoque no soluciona code smells relacionados con el refactoring de Feature
Envy.
Se prueba esta hipótesis comparando los listados antes mencionados, analizando los casos
donde los code smells fueron solucionados y donde fueron creados.
5.4.2 Análisis e Interpretación
Como se señaló en la RQ#1, se logró solucionar, en promedio, un 37,99% de las Feature
Envy de los proyectos que fueron refactorizados, sin analizar la intervención del
desarrollador para la corrección de errores introducidos. Este code smell, a su vez, se
encuentra relacionado con otros code smells, teniendo un impacto positivo en algunos casos,
y negativo en otros.
En la Tabla 5.6 se compara la cantidad de smells del sistema Squirrel antes y después de
aplicar la refactorización de Feature Envy. En este caso se puede observar la cantidad de
Feature Envy que había originalmente (41), las solucionadas (23) y las creadas (0).
Code smell Cantidad pre-
refactoring
Cantidad post-
refactoring
Solucionad
os
Creados
Brain Class 1 1 0 0
Brain Method 2 2 0 0
Dispersed Coupling 1 1 0 0
Feature Envy 41 18 23 0
God Class 3 3 0 0
Intensive Coupling 5 4 1 0
Shotgun Surgery 2 2 0 0
Tabla 5.6: Comparación de Code Smells pre y post refactoring
En primer lugar, se analizaron los smells solucionados luego de refactorizar todas las Feature
Envy posibles de un sistema. Como se puede ver en la Figura 5.8, la cantidad de code smells
adicionales afectados positivamente es muy baja. Esto se debe principalmente al bajo
porcentaje de Feature Envy solucionadas para cada sistema. Además, es necesario examinar
las características de cada smell adicional solucionado.
61
Figura 5.8: Cantidad de smells solucionados por el enfoque
Los smells solucionados al menos una vez fueron God Class, Shotgun Surgery e Intensive
Coupling, como se puede ver en la Figura 5.9.
Para el caso de God Class, se comprende el bajo porcentaje obtenido (3,54% en promedio
para todos los proyectos) debido a que la mayoría de las Feature Envy, como se vio en la
RQ#1, fueron movidas completamente, por lo que, en caso de ser una God Class,
simplemente se movió este code smell a una nueva clase, sin solucionarlo.
En cuanto a Intensive Coupling, el bajo porcentaje (2,70% en promedio para todos los
proyectos) cobra sentido al comprender que es necesario que la Feature Envy refactorizada
sea a su vez una Intensive Coupling y la clase a la que es movida sea la misma que genera
Intensive Coupling. Esto no es común, debido a que el smell Intensive Coupling depende de
que los llamados a métodos proveedores sean múltiples, es decir, a diferentes métodos, y una
Feature Envy simplemente se genera cuando los llamados exceden un umbral (ATFD >
FEW) que no necesariamente está compuesto de múltiples operaciones.
En cuanto a Shotgun Surgery, el bajo porcentaje (3,54% en promedio para todos los
proyectosse comprende al analizar uno de los factores clave para que este smell se produzca.
Esto es, el número de proveedores para que este smell se genere debe ser alto (CC > MANY),
con lo cual es poco probable que un método afectado por Shotgun Surgery sea también
2
1
1
12
13
4
13
16
2
2
10
15
231
-1
1
1
-1
-1
-1
-1
apache-jspf-resolver
fitjava
jmoney
jparse
jpf
junit
MobileMedia
oscache
Quickserver
Squirrel
Cantidad solucionada
Pro
yect
o
Data Class Tradition Breaker God Class Intensive Coupling Feature Envy Shotgun Surgery
62
considerado Feature Envy. Sin embargo, si se da el caso que la Feature Envy movida genere
una Shotgun Surgery en la clase a la cual fue movida, la Feature Envy movida podría
solucionar una de las clases proveedoras, solucionando también este smell.
Figura 5.9: Porcentajes de smells solucionados
En segundo lugar, se analizaron los smells creados luego de refactorizar todas las Feature
Envy posibles de un sistema. Como se puede ver en la Figura 5.10, la cantidad de code smells
adicionales afectados negativamente también es muy baja. Esto se debe principalmente al
bajo porcentaje de Feature Envy solucionadas para cada sistema. Además, es necesario
examinar las características de cada smell adicional creado.
Figura 5.10: Cantidad de smells creados por el enfoque
3,54%
2,70%
4,35%
0,00% 20,00% 40,00% 60,00% 80,00% 100,00%
Shotgun Surgery
Intensive Coupling
God Class
Porcentaje sobre el total
Co
de
Smel
ls s
olu
cio
nad
os
1
1
1
1
1
apache-jspf-resolver
jparse
junit
Quickserver
Cantidad creada
Pro
yect
o
Data Class Tradition Breaker God Class
63
Los smells creados al menos una vez fueron Tradition Breaker, Data Class y God Class, como
se puede observar en la Figura 5.11.
Para el caso de God Class, el porcentaje es muy bajo (4,35% en promedio para todos los
proyectos) y para poder comprender cómo se generó este smell, hubo que analizar el caso
encontrado individualmente, debido a que se generó por una situación muy particular de un
sistema (apache-jspf-resolver). Lo que ocurrió, fue que este sistema poseía una gran cantidad
de clases similares con métodos similares. Entre estos métodos se encontraba una Feature
Envy que siempre envidiaba de la misma clase. El resultado fue que la refactorización de
todas las Feature Envy implicaba mover ese método a la misma clase, lo que dio como
resultado la sobrecarga de una única clase con todos los métodos similares que envidiaban
de ella, generando una God Class.
En cuanto a Tradition Breaker, el porcentaje obtenido (14,28% en promedio para todos los
proyectos) se comprenden debido a que al mover una Feature Envy, no se tienen en cuenta
las características del método al cual se mueven. Por ello es que, si la clase candidata elegida
es hija en una jerarquía de herencia, y se especializa excesivamente al recibir el método
movido por el enfoque, es posible generar este smell.
En cuanto a Data Class, también ocurrió la creación de este smell por un caso particular. Se
trataba de una clase muy simple en la cual el único método que añadía complejidad resulto
ser una Feature Envy. Al ser movido, se generó este smell. El porcentaje también fue muy
bajo (2,17% en promedio para todos los proyectos)
Figura 5.11: Porcentajes de smells creados
Finalmente, para comprender el análisis total de los resultados obtenidos, se puede ver en la
Figura 5.12 el total de code smells afectados por la refactorización de Feature Envy.
14,28%
2,17%
4,35%
0,00% 20,00% 40,00% 60,00% 80,00% 100,00%
Tradition Breaker
Data Class
God Class
Porcentaje sobre el total
Co
de
Smel
ls c
read
os
64
Figura 5.12: Code Smells afectados por el enfoque
Este análisis permite concluir que el enfoque no posee un alto impacto en la solución de otros
code smells como consecuencia de la solución de Feature Envy aceptándose así la hipótesis
H1. Los resultados confirman la solución de un 3,53% de los code smells relacionados con
Feature Envy, el cual es considerado muy bajo para ser considerado relevante. Por otro lado,
también se confirma que no se generaron impactos negativos (code smells creados)
significativos.
5.5 RQ#3: ¿Son complementarias las soluciones identificadas por el
enfoque propuesto y por JDeodorant en la refactorización de Feature
Envy?
En esta sección se analizarán las Feature Envy resueltas por JDeodorant y por el enfoque
propuesto con el objetivo de comparar ambas herramientas.
5.5.1 Hipótesis
El objetivo de esta evaluación es comparar el enfoque propuesto con la herramienta
JDeodorant. Para responder esta pregunta se analizarán los resultados teniendo en cuenta dos
universos diferentes de soluciones:
Las Feature Envy identificadas por ambas herramientas simultáneamente.
65
Cantidad total de Feature Envy identificadas, independientemente de si fueron
detectadas por una o ambas herramientas.
Nuestra hipótesis es que ambas herramientas son complementarias, aumentando
significativamente el universo de Feature Envy refactorizadas en un proyecto al usarse
simultáneamente.
Formalizando:
H0: Los enfoques utilizados simultáneamente mejoran significativamente el
porcentaje de resolución de Feature Envy de un sistema.
H1: Los enfoques utilizados simultáneamente no mejoran significativamente el
porcentaje de resolución de Feature Envy de un sistema.
Se probará esta hipótesis comparando los universos antes mencionados, analizando las
resoluciones identificadas por ambas herramientas.
5.5.2 Análisis e Interpretación
En primer lugar, como se indicó anteriormente, se tomó el conjunto de Feature Envy
identificadas por ambas herramientas. Se utilizaron los 10 proyectos presentados
inicialmente en el caso de estudio. Es importante aclarar que JDeodorant únicamente
identifica aquellas Feature Envy sobre las cuales encuentra una solución. En cambio,
JSpIRIT (herramienta sobre la cual se implementó el enfoque propuesto) genera el listado
completo de Feature Envy de un proyecto, y luego se le aplica el enfoque para definir si existe
solución. Por lo tanto, la intersección de Feature Envy identificadas resulta en un conjunto
de métodos mucho más reducido, debido a que JDeodorant identifica una cantidad mucho
menor de Feature Envy que JSpIRIT, como se ve en la Figura 5.13.
Figura 5.13: Cantidad de Feature Envy identificadas por JDeodorant y JSpIRIT
Sin embargo, el universo obtenido resulta en un conjunto de métodos sobre los cuales
JDeodorant tiene un 100% de efectividad a la hora de identificar un refactoring para la
66
solución del code smell. De todas formas, como se ve en la Figura 5.14, el enfoque propuesto
consiguió obtener una solución en el 90% de los casos.
Figura 5.14: Porcentaje de resolución de ambas herramientas sobre la intersección
El foco principal en el desarrollo de la herramienta JDeodorant en cuanto a refactorización
de Feature Envy fue la implementación del máximo número de controles de precondiciones
y postcondiciones necesarias para la aplicación del refactoring Move Method sin introducir
errores detectables en tiempo de compilación ni cambios en el comportamiento de un sistema.
En este aspecto, al analizar los métodos resueltos, se puede detectar una importante mejora
en la calidad de las soluciones planteadas por JDeodorant, debido a que el enfoque propuesto
utiliza la API JDT de Eclipse y no implementa particularmente el extenso conjunto de
condiciones necesarias para evitar la introducción de errores.
Finalmente, para profundizar el análisis, se revisó el método resuelto por JDeodorant que no
pudo ser resuelto por JSpIRIT, para comprender cuál es la causa de que el enfoque propuesto
no pudiera identificar una solución.
Figura 5.15: Método solucionado por JDeodorant y no solucionado por el enfoque
propuesto
67
El método es MaxCore.buildRunner del proyecto Junit. Al analizar la naturaleza del método,
se puede observar el alto número de sentencias return que posee. El enfoque propuesto, al
intentar realizar una aproximación heurística para definir una estrategia que implique extraer
una porción y no su totalidad, selecciona la extracción parcial del método, desde la primer
ocurrencia del uso de la clase extranjera hasta la última, como se ve en la Figura 5.15. Sin
embargo, al intentar hacer esta extracción, los controles de la API JDT para el refactoring
Extract Method impiden la operación, debido a que ésta alteraría el normal comportamiento
del método al extraer algunas sentencias return y otras no. JDeodorant no presenta esta
complicación porque siempre mueve completamente el método seleccionado.
Posteriormente, se analizó el universo completo de Feature Envy, formado por la unión de
Feature Envy identificadas, es decir, aquellas identificadas por JDeodorant, por JSpIRIT o
por ambas. Como se pudo ver en la Figura 5.13, JDeodorant identifica 47 Feature Envy,
mientras que JSpIRIT identifica 345 Feature Envy. De esta forma, teniendo en cuenta que 10
Feature Envy son identificadas por ambas herramientas, el universo total de Feature Envy
identificadas es de 382. Como JDeodorant identifica las Feature Envy que resuelve, esta
herramienta resuelve 47 Feature Envy. Por su parte, el enfoque propuesto no resuelve la
totalidad de Feature Envy identificadas por JSpIRIT, dando un total de 129, como se ve en
la Figura 5.16.
Figura 5.16: Cantidad de Feature Envy resueltas por ambas herramientas
Finalmente, se puede observar en la Figura 5.17 el porcentaje de resolución de Feature Envy
de cada herramienta sobre el universo total considerado. JDeodorant resuelve un 12,30% del
total de Feature Envy, mientras que JSpIRIT alcanza un porcentaje de resolución de 33,77%
129
47
0 20 40 60 80 100 120 140
JSpIRIT
Jdeodorant
Canitdad total de Feature Envy resueltas
Her
ram
ien
ta
68
Figura 5.17: Porcentaje de Feature Envy resueltas por ambas herramientas
Teniendo en cuenta que 9 Feature Envy son resueltas por ambas herramientas como se vio
en el análisis previo de la intersección, entre ambas herramientas se resuelven 167 Feature
Envy, lo cual corresponde a un porcentaje total de resolución de 43,72%.
Éste análisis permite concluir que ambas herramientas son complementarias a la hora de
lograr mejores resultados en la resolución de Feature Envy de un sistema, cumpliéndose así
la hipótesis H0. Los resultados confirman que la intersección de ambos universos de
resoluciones es pequeña en comparación al universo total, y que ambas herramientas
resuelven diferentes Feature Envy por su estrategia de identificación, por lo que el porcentaje
de resolución total se ve significativamente mejorado al aplicar ambas herramientas
simultáneamente.
69
Capítulo 6: Conclusión
6.1 Conclusiones finales
Los code smells son síntomas útiles para la identificación de problemas estructurales de un
sistema que se relacionan con problemas de modificabilidad. Surgen por la utilización de
“malas prácticas” al desarrollar un sistema. Los CS son decisiones pobres de implementación
que hacen que un sistema orientado a objetos sea difícil de mantener [35]. Son las
descripciones generales de código problemático y sirven para ayudar a los desarrolladores a
decidir cuándo un código necesita refactorización [36], es decir, su detección permite
identificar oportunidades de refactorización de código para la mejora de su calidad. Una vez
aplicado el refactoring apropiado, en la mayoría de los casos se mejoran diversos aspectos de
calidad como mantenibilidad, comprensibilidad y reusabilidad. [37]. Feature Envy puede ser
considerado el síntoma más común relacionado con problemas de acoplamiento y cohesión
[38]. Es un método que parece más interesado en los datos de otra clase que en los de su
propia clase [3]. Este problema puede ser solucionado aplicando el refactoring Move Method
únicamente, o aplicando Extract Method y Move Method en conjunto. Existen herramientas
para la recomendación y aplicación de Move Method para la solución de este code smell. Sin
embargo, ninguna se encarga de proponer la posibilidad de aplicación del refactoring Extract
Method previo al Move Method, ya que requiere realizar un análisis más detallado del
código.
En este trabajo se abordaro el problema de identificación de oportunidades de refactoring de
Feature Envy y su aplicación mediante la presentación de un enfoque realizado sobre la
extensión Bandago del plugin JSpIRIT [13], brindándole al desarrollador más de una
solución en caso de ser posible, y analizando oportunidades de realizar una extracción de
código del método previo a ser movido a otra clase. El enfoque se basa en un algoritmo
heurístico para la identificación de posibilidades de aplicación de Extract Method, y cada
solución propuesta es presentada al desarrollador acompañada con las métricas relacionadas
con el code smell Feature Envy. El enfoque fue implementado en el lenguaje Java.
Para poder validar los beneficios del enfoque se realizó un caso de estudio con tres research
questions. Estas research question corroboraron la efectividad del enfoque, permitiendo
además analizar varios aspectos del mismo. En la primer research question, se analizaron
todas las Feature Envy que se lograron solucionar automáticamente. Si bien el porcentaje
promedio resultó ser bajo, se corroboró que al considerar las soluciones que requerían
intervención por parte del desarrollador, se obtiene un porcentaje completamente aceptable
cuando se necesita identificar soluciones para un smell complejo como lo es Feature Envy.
En la segunda research se analizó si la solución de Feature Envy permite solucionar otros
code smells detectados por JSpIRIT. En este caso, se rechazó la hipótesis inicial al comprobar
que la solución de Feature Envy tenía una baja incidencia sobre los demás code smells de
todo un sistema. Para la tercera research question se comparó el enfoque propuesto con
JDeodorant, la única herramienta que propone un enfoque de recomendación y resolución de
Feature Envy. Se comprobó que el enfoque detecta una mayor cantidad de soluciones y que
70
ambas herramientas pueden ser utilizadas complementariamente para la resolución de un
conjunto de Feature Envy significativamente mayor.
6.2 Contribuciones
La contribución más importante de este trabajo es asistir al desarrollador al refactorizar las
Feature Envy de un sistema, analizando posibilidades de extracción y de múltiples
soluciones. Específicamente, se pueden resaltar las siguientes contribuciones:
Automatización del proceso de refactorización: Si bien es cierto que el proceso
requiere la intervención del desarrollador para la corrección de errores, se automatiza
el análisis y aplicación de los refactorings Extract Method y Move Method. Se
corroboró que a excepción de JDeodorant, las otras herramientas existentes se limitan
a la recomendación de refactorizaciones.
Múltiples soluciones: El enfoque le brinda al desarrollador varias soluciones en caso
de existir, acompañadas por sus métricas. Esto permite al desarrollador hacer un
análisis de las métricas para decidir qué solución desea aplicar.
Posibilidades de aplicación de Extract Method previo al Move Method: El enfoque
analiza la posibilidad de extraer una parte del método para no mover código
innecesario a otra clase. De esta forma, solo se mueve la porción de código que
realmente está generando el code smell.
Rápido tiempo de respuesta: Al estar basado en un enfoque heurístico, la herramienta
genera soluciones en pocos segundos.
Información detallada: Todas las soluciones generadas muestran información
adicional para la toma de decisiones del desarrollador. Se presenta el conjunto de
métricas relacionadas con Feature Envy para cada solución.
Extensibilidad: Se brinda la posibilidad de agregar nuevas heurísticas para la
detección de refactorizaciones posibles respetando una interfaz común.
6.3 Limitaciones
Si bien la herramienta ayuda a resolver las Feature Envy de un sistema, se hallaron algunas
limitaciones:
Introducción de errores: Move Method es un refactor sensible que requiere el control
de un gran conjunto de pre-condiciones y post-condiciones para evitar la introducción
de errores al ser ejecutado. Actualmente no existe soporte para dichas condiciones, y
este trabajo no se enfocó en el control de los mismos. Por este motivo, el esquema
general de la solución es dependiente de la intervención del desarrollador para el
control y corrección de los mismos.
Sólo Java: El enfoque fue desarrollado sobre un plugin para el IDE Eclipse que sólo
trabaja con el lenguaje Java. Aun así, como Java es uno de los lenguajes más
utilizados, no resulta una gran limitación.
71
Universo de clases candidatas: El universo de clases candidatas identificadas por la
herramienta se ve limitado por la posibilidad de realizar el refactor Move Method a
dicha clase, debido a que actualmente únicamente se permite la aplicación de dicho
refactor sobre clases pertenecientes a parámetros del método o a variables de instancia
de la clase. El enfoque no intenta extender este universo de soluciones.
6.4 Trabajos futuros
Desde el enfoque presentado en esta tesis, y los resultados obtenidos, se identifican varias
líneas de investigación futuras.
En primer lugar, como punto más importante, se puede analizar e incluir el control del
conjunto de pre-condiciones y post-condiciones para la aplicación del refactoring Move
Method sin introducir errores en el código. La herramienta JDeodorant es la más avanzada
en este aspecto, pero incluso dicha herramienta puede llegar a introducir errores detectables
en tiempo de compilación. Esto se debe a la gran cantidad de problemas que pueden
presentarse cuando se mueve un método o fragmento de un método desde su clase original a
una nueva clase.
Otro aspecto que podría mejorarse es la vista previa de la refactorización. Podría agregarse
un análisis más detallado de la solución generada y la clase candidata a la cual se decidió
mover el método. Para poder realizar un mejor análisis de las soluciones, debería extenderse
la actual vista y crearse reportes más detallados de las métricas y los refactors aplicados.
Por último, la investigación podría continuar en torno dos grandes aspectos. En primer lugar
se deberían analizar la aplicación de nuevas heurísticas para identificar una mayor cantidad
de posibilidades de extracción previa al Move Method, debido a que la heurística actual
identifica un porcentaje bajo sobre el total de soluciones. Finalmente, se podríacontinuar con
la eliminación de otros code smells, debido a que es posible que varias técnicas utilizadas en
el enfoque para eliminar Feature Envy pueden ser reutilizadas para eliminar otros code
smells.
72
Bibliografía
[1] Steidl, Daniela, and Sebastian Eder. "Prioritizing maintainability defects based on
refactoring recommendations." Proceedings of the 22nd International Conference on
Program Comprehension. ACM, 2014.
[2] Fowler, Martin. “Refactoring: improving the design of existing code”. Pearson Education
India, 2002.
[3] Lanza, Michele, and Radu Marinescu. Object-oriented metrics in practice: using software
metrics to characterize, evaluate, and improve the design of object-oriented systems.
Springer Science & Business Media, 2007.
[4] Ettinger, Ran. Refactoring via program slicing and sliding. Diss. University of Oxford,
2006.
[5] Harman, Mark, and Robert Hierons. "An overview of program slicing." Software Focus
2.3 (2001): 85-92.
[6] Komondoor, Raghavan, and Susan Horwitz. "Effective, automatic procedure extraction."
Program Comprehension, 2003. 11th IEEE International Workshop on. IEEE, 2003.
[7] Lakhotia, Arun, and Jean-Christophe Deprez. "Restructuring programs by tucking
statements into functions." Information and Software Technology 40.11 (1998): 677-689.
[8] Weiser, Mark. "Program slicing." Proceedings of the 5th international conference on
Software engineering. IEEE Press, 1981.
[9] De Lucia, Andrea, et al. "Unions of slices are not slices." Software Maintenance and
Reengineering, 2003. Proceedings. Seventh European Conference on. IEEE, 2003.
[10] Pattanaik S., Praksh Boy S., Mohanty R. “Simulated Annealing based placement
algorithms and research challenges: A survey”. Journal of Global Research in Computer
Science Volume 3, No 6, 2012 35-36.
[11] Tsantalis, Nikolaos, and Alexander Chatzigeorgiou. "Identification of extract method
refactoring opportunities for the decomposition of methods." Journal of Systems and
Software 84.10 (2011): 1757-1782.
[12] International Organization for Standardization. ISO 8402: 1994: Quality Management
and Quality Assurance-Vocabulary. International Organization for Standardization, 1994.
[13] Vidal, Santiago A., Claudia Marcos, and J. Andrés Díaz-Pace. "An approach to
prioritize code smells for refactoring." Automated Software Engineering (2014): 1-32.
[14] Nazin H. Madhavji, Juan C. Fernandez-Ramil, Dewayne E. Perry. "Software Evolution
and Feedback" John Wiley & Sons, Ltd. (2006).
[15] Petito, Michael. "Eclipse refactoring." http://people. clarkson. edu/~
dhou/courses/EE564-s07/Eclipse-Refactoring. Pdf 5 (2007): 2010.
[16] Belady, Laszlo A., and Meir M. Lehman. "A model of large program development."
IBM Systems journal 15.3 (1976): 225-252.
[17] Murphy-Hill, Emerson, and Andrew P. Black. "Breaking the barriers to successful
refactoring." Software Engineering, 2008. ICSE'08. ACM/IEEE 30th International
Conference on. IEEE, 2008.
[18] Beck, Kent. Extreme programming explained: embrace change. Addison-Wesley
Professional, 2000.
[19] Kim M., Zimmermann T., Nagappan N. "A Field Study of Refactoring Challenges and
Benefits." Microsoft Research, Redmond., 2012.
73
[20] Berra, Iñaki and Zuliani Held, Santiago. "Refactorización Automatizada para la
Eliminación de Brain Methods" Tesis de grado. Facultad de Ciencias Exactas, UNICEN
(2015).
[21] Murphy-Hill, Emerson, Chris Parnin, and Andrew P. Black. "How we refactor, and how
we know it." Software Engineering, IEEE Transactions on 38.1 (2012): 5-18.
[22] Ben-Menachem, Mordechai, and G. S. Marliss. Software Quality: Producing Practical,
Consistent Software, Slaying the Software Dragon Series. Boston, MA: International
Thomson Computer Press, 1997.
[23] Garcia, Rubio, and Mario Piattini. "Calidad en el desarrollo y mantenimiento del
software." RA-MA (2003).
[24] C. SenthilMurugan and S.Prakasam Ph.D. "A literal Review of Software Quality
Assurance." International Journal of Computer Applications Volume 78. No.8 (2013).
[25] Fokaefs, M. and Tsantalis, N. “JDeodorant: Identification and Removal of Feature Envy
Bad Smells” Department of Applied Informatics, University of Macedonia. (2007)
[26] Anqueril, N., Oliveira, K., de Sousa K., Batista Dias M. “Software Maintenance seen
as knowledge management issue”. Catholic University of Brasilia, 2006. [27] M.M. Lehman and J.F. Ramil. An approach to a theory of software evolution. In Proceedings
of the 4th international Workshop on Principles of Software Evolution (IWPSE '01), pages 7074,
Vienna, Austria. ACM, 2001.
[28] T.M. Pigoski, “Practical Software Maintenance: Best Practices for Software Investment”, John
Wiley & Sons, Inc., 1996.
[29] Černý, Vladimír. "Thermodynamical approach to the traveling salesman problem: An efficient
simulation algorithm." Journal of optimization theory and applications 45.1 (1985): 4151.
[30] Opdyke, W. “Refactoring object-oriented frameworks” Universitu of Wisconsin – Madison,
1982.
[31]Bomarius, F. Oivo, M. Jaring, P. and Abrahamson P. “Product-Focused Software Process
Improvement” 10th International Conference, PROFES 2009, 2009.
[32] Yamashita, A. “Code Smells as system-level indicators of maintainability: An empirical study”.
The Journal of Systems and Software, Elsevier, 2013.
[33] Wanberg, R. D., “A literature Review on Code Smells and Refactoring”, University of Oslo,
Department of informatics, 2010.
[34] A. O’connor, M. Shonle and W.Griswold. “Star diagram with automated refactorings for
Eclipse” In Proceedings of the 2005 OOPSLA Workshop on Eclipse Tecnology Exchange, pages 16-
20, San Diego, California ACM, 2005.
[35] Khomn F., Di Penta M. and Guéhéneuc Y. “An Exploratory Study of the Impact of Code Smells
on Software Change-proneness” École Polytechnique de Montréal, Canada. University of
Sannio,Benevento, Italy, 2009.
[36] Mäntylä M. V., Lasseniuss C., “Subjective evaluation of software evolvability using code smells:
An empirical study”. Springer Science + Business Media, LLC 2006.
[37] Chatzigeorgiou, A., Manakos A. “Investigating the Evolution of Bad Smells in Object-Oriented
Code” Department of Applied Informatics, University of Macedonia, 2010.
[38] Oliveto, R., Bavota G., Gethers M., Poshyvanyk D., De Lucia A. “Identifying Method Friendship
to Remove The Feature Envy Bad Smell (NIER Track)”. University of Molise, Pesche, Italy.
University of Salerno, Fisciano, Italy. The College of William and Mary, USA. 2011.
[39] Weiser, M. “Program Slicing”. IEEE Transactions on Software Engineering. Vol – SE-10. 1984.
[40] Bavota G., Oliveto R., Gethers M., Poshyvanyk D., De Lucia A. “MethodBook: Recommending
Move Method Refactorings via Rational Topic Models” IEEE Transactions on Software Engineering,
2014.
74
[41] Ali O., Marouane K., Mel O., Houari S., Kalyanmoy D., Katsuro I., “MORE: A Multi-Objective
Refactoring Recommendation Approach to Introducing Design Patterns and Fixing Code Smells”.
Journal of Software: Evolution and Process. 2017.
[42] Ali, O., Katsuro I., Takashi I., Naoya U. “c-JRefRec: Change-Based Identification of Move
Method Refactoring Opportunities”. Department of Computer Science and Software Engineering,
CIT, UAE University, 2016.
[42] Sales V., Terra R., Miranda L. F., Valente M., “JMove: Seus Métodos em Classes Apropiadas”.
Departamento de Ciencia da Computaçao, Universidade General de Minas Gerais, 2013.
[43] P. Clements, F. Bachmann, L. Bass, D. Garlan, J. Ivers, R. Little, R. Nord and J. Stafford.
“Documenting Software Architectures – Views and Beyond”. AddisonWesley, 2003.
[44] Qualitas web page: http://qualitascorpus.com