Un inconveniente con la forma de muestreo de resultados tradicional de JSpIRIT es que un desarrollador debe recorrer todas las clases del paquete en busca de los smells que forman la aglomeración en cuestión. En paquetes con pocas clases no es un problema mayor, pero cuando los paquetes contienen varias clases es engorroso y se vuelve una pérdida de tiempo para el desarrollador. A esto hay que sumarle que algunas clases contienen varios marcadores de smells o aglomeraciones encontrados por JSpIRIT, y es necesario revisarlos para ubicar aquel que corresponde a la aglomeración que se está analizando. Además, una característica deseable en la visualización de aglomeraciones es la posibilidad de explorar los smells que las conforman, en qué cantidad y en qué clases y métodos se extienden para establecer a priori una relación entre ellos si fuera posible. Estos datos son extensos para ser representados en forma de texto y aún si así fuera muchos desarrolladores no se tomarían el tiempo de leer cada una de las descripciones de cada aglomeración. Sin embargo, este tipo de métricas puede ser representada en forma sencilla e intuitiva por medio de entidades gráficas como se puede ver en la vista desarrollada en este trabajo (Figura 7.7).
La visualización ofrece de manera rápida una perspectiva general del sistema poniendo a disposición del desarrollador la siguiente información: ● Distribución de las aglomeraciones en los paquetes. ● Paquetes con mayor cantidad de aglomeraciones. ● Cantidad de smells por aglomeración.
● Elementos de código afectados por los smells que forman cada aglomeración.
● Relaciones de dependencia entre los paquetes afectados.
Figura 7.7: Vista de aglomeraciones IntraComponent/Hierarchical.
Figura 7.8: Paquete healthwatcher.data.rdb.
Haciendo zoom sobre el paquete central y de mayor concentración de smells,
healthwatcher.data.rdb (Figura 7.8), se pueden apreciar tres aglomeraciones en el mismo. Al deslizarse con el puntero sobre los smells de las aglomeraciones es posible visualizar la información contenida en la Tabla 7.4.
Tipo de smells Elemento de código Ranking
Feature Envy Feature [email protected] 45 Feature [email protected] 38 Feature [email protected] 31 Feature [email protected] 44 Feature [email protected] 30 Feature [email protected] 49 Feature [email protected] 25
Dispersed Coupling Dispersed [email protected] 46 Dispersed [email protected] 29 Dispersed [email protected] 28 Dispersed [email protected] 47 Dispersed [email protected] 50 Intensive Coupling Intensive [email protected] 12 Intensive [email protected] 13 Intensive [email protected] 11 Tabla 7.3: Aglomeraciones del paquete healthwatcher.data.rdb.
En el detalle de las aglomeraciones se observa claramente una aglomeración Feature Envy (Tabla 7.3). Se trata de un conjunto de métodos presentes en varias clases que implementan una interfaz llamada
IDiseaseRepository. La misma define un método cuya signatura es la siguiente:
public boolean exists(int code)
Todas las clases afectadas definen este método de manera similar, en todos se realiza la misma consulta en una tabla SQL utilizando como filtro el código parametrizado. La pequeña diferencia entre las implementaciones es la tabla en la cual se realiza la consulta que es lo único que varía de una implementación a otra. Una posible solución a esta repetición de código podría ser parametrizar la tabla utilizada para la consulta y abstraer el comportamiento del método hacia la interfaz, convirtiéndola en una clase abstracta.
En la parte superior (Figura 7.8) se observa una aglomeración de smells del tipo Intensive Coupling . Los métodos afectados comparten una característica: además de pertenecer a la misma clase (ComplaintRepositoryRDB), en su código concentran una gran cantidad de invocaciones a métodos de instancias de la clase Complaint (Figura 7.9), lo que los convierte en candidatos válidos para el tipo de smell Intensive Coupling.
Figura 7.9: Intensive Coupling en métodos de la clase ComplaintRepositoryRDB.
Por otro lado, dando un recorrido por la vista de aglomeraciones
IntraClass (Figura 7.10) puede verse que los smells Intensive Coupling no son los únicos afectando a la clase ComplaintRepositoryRDB, que según la vista se trata de una de las más afectadas del sistema.
Figura 7.10: Vista de aglomeraciones IntraClass.
Sobre la derecha del paquete más afectado de la vista de aglomeraciones
IntraComponent (Figura 7.7) puede verse el paquete
healthwatcher.view.command. Al concentrar la atención en este paquete pueden verse 3 aglomeraciones. La más grande de estas corresponde al grupo de smells
Dispersed Coupling que afectan a los métodos execute() de las clases que implementan la interfaz Command, que fueron señalados por la vista de Heat Map durante el análisis de smells (Sección 7.1.1). A su vez este grupo de smells forman una aglomeración del tipo Hierarchical como señala la visualización resaltando los smells con un contorno rojo cuando se ubica el cursor sobre uno de los smells (Figura 7.11), señalando que el problema se extiende en toda la jerarquía. En este ejemplo es notable cómo esta vista ayuda a establecer relaciones entre los smells facilitando la formulación de hipótesis, que sería más compleja si estos fuesen analizados individualmente.
Figura 7.11: Aglomeraciones del paquete healthwatcher.view.command.
Finalmente las aglomeraciones restantes que aparecen en el paquete (Figura 7.11) contienen los smells de los tipos Shotgun Surgery yBrain Method
listados en la Tabla 7.1, producto de los resultados mostrados en la vista de Heat Map. Todas estas aglomeraciones están relacionadas ya que pertenecen a la misma jerarquía de clases (especializaciones de la clase Command).
Continuando el análisis, en la esquina superior izquierda en el paquete
healthwatcher.model.complaint (Figura 7.7) se observa una aglomeración del tipo Hierarchical con smells del tipo Refused Parent Bequest (Figura 7.12) sobre la jerarquía de clases que extiende a la clase Complaint. La clase abstracta modela el estado de una queja realizada al sistema almacenando ciertos atributos relevantes al mismo. Sus especializaciones definen distintos tipos de quejas que el sistema soporta, el problema es que estas definen objetos diferentes para almacenar el estado, con lo cual la herencia deja de tener sentido, o , en otras palabras, es “rechazada” por las subclases. Esto convoca a un replanteo de la jerarquía estableciendo los atributos en común entre las clases y realizando las abstracciones correspondientes.
Figura 7.12: Aglomeraciones del paquete healthwatcher.model.complaint.
7.3 Resultados
En los análisis anteriores se pudo comprobar como las vistas agregan información relevante para el análisis de resultados. Si bien con el análisis realizado con la vista tradicional de JSpIRIT es posible encontrar falencias en el código, hubiese sido necesario explorar varios smells de la lista para encontrar una relación entre estos y poder determinar que algunos de ellos indican un problema que se extiende a todo un paquete, como se logró rápidamente mediante las visualizaciones.
Las visualizaciones representan el sistema de una manera más estructural, lo que permite ver las relaciones entre los elementos de código afectados más rápidamente, sin necesidad de explorar el código del sistema, y por otro lado advierten al desarrollador de los componentes más afectados por smells y aglomeraciones en general, en caso de que se desee concentrar los esfuerzos de refactoring en alguno de ellos en particular.
Por otro lado la representación de las dependencias en la vista de heatmap es de suma utilidad a la hora de buscar problemas de acoplamiento de
componentes, o en situaciones donde la implementación viola la arquitectura pretendida del sistema.
En el caso de los análisis del paquete healthwatcher.view.command el ranking otorgado por JSpIRIT en base a los criterios introducidos fué variado (Tabla 7.1). Muchos de los smells que eran parte del problema fueron rankeados en puestos mayores al #20. Muchos de ellos incluso fueron posicionados a partir del puesto #40, lo que da la pauta de que si bien el ranking es una herramienta importante y debe ser tenido en cuenta, no sería del todo eficiente conducir un análisis en base a este solamente. Ver un problema desde diferentes perspectivas agrega información que puede ser relevante para su resolución [78].
7.4 Riesgos de la validez de los resultados
A continuación se analizan los riesgos de los cuatro tipos de validación para este estudio.
Validación de conclusión: Este riesgo tiene que ver con el análisis estadístico de los resultados. En este caso, la principal preocupación es que el estudio fue realizado sobre una sola aplicación con un desarrollador. Esto podría reducir la habilidad de presentar resultados concretos. Por esta razón, se cree que son necesarios más experimentos con diferentes sujetos y aplicaciones para poder generalizar los resultados.
Validación de construcción: Este riesgo tiene que ver con el diseño del experimento.
● El estudio fue realizado por los autores de este trabajo que tomaron el rol de un desarrollador en búsqueda de problemas en el código de un sistema. En la realidad se espera que el desarrollador conozca de antemano el sistema o que incluso haya formado parte en su producción, lo que le