Relatório de Modularidade
Equipe
:
Cleivson Siqueira de Arruda (csa3)
Hugo Rafael Azevedo de Alencar (hraa)
Apresentação
O objetivo deste documento é identificar oportunidades de modularidade no projeto da cadeira de Tópicos Avançados em Engenharia de Software utilizando as ferramentas SourceMiner, AOPMetrics e MetricsTool para detectar falhas de modularidade.
Introdução
A técnica utilizada para identificar as oportunidades de modularidade consiste em fazer uma análise do projeto utilizando o SourceMiner e, baseado nos gráficos gerados, analisar possíveis problemas como métodos e classes muito grandes ou interdependentes.
Em seguida, escolhemos concerns baseados em funcionalidades que possam sofrer mudanças com o desenvolver do projeto, podendo gerar um grande retrabalho devido ao espalhamento e entrelaçamento desses concerns ao longo do código. Mapeamos esses concerns na ferramenta AOPMetrics e geramos relatórios que serão utilizados pela ferramenta MetricsTool para gerar informações sobre possíveis problemas no projeto.
Oportunidades Encontradas
Gráficos SourceMiner
TreeMap
Figura - TreeMap usando filtro de 20 linhas para tamanho mínimo de métodos
Analisando esse gráfico, percebemos a presença de alguns métodos potencialmente prejudiciais pelo seu tamanho (a partir de 20 linhas). Porém, analisando o código dos métodos, percebemos que entre, os 13 métodos apontados como grandes pela ferramenta, 4 deles não apresentam oportunidades de refatoramento e, entre os 9 restantes, a grande maioria é o método doPost que tem muitas coisas em comum entre as várias ocorrências e pode ser resolvido com herança. Fora a parte da herança, outra oportunidade de refatorar os métodos doPost é encontrada na
ocorrência da classe AdicionarMembrosServlet, onde foi extraído um método de um trecho do código que é independente e comum entre todas as ocorrências do método doPost. O trecho de código pode ser visto na figura 2.
Figura - Trecho de código que pode ser refatorado
Coupling Matrix
Figura - Coupling Matrix enfatizando quebra de arquitetura em camadas
Na figura podemos perceber que a arquitetura em camadas é em grande parte respeitada pelo sistema. Mas um dos problemas encontrados (grifado em vermelho) foi a quebra da arquitetura, pois um método do pacote útil chama métodos da Fachada para retornar dados do BD, coisa que deveria ser feita pelo respectivo controle. Nas figuras 4 e 5 podemos analisar melhor essa falha.
Figura – Código da dependência entre StringsUtil e Fachada
Polymetric
Figura - Polymetric
Analisando o gráfico de hierarquias podemos perceber dois possíveis problemas. O primeiro é a classe Membro, representada pelo maior retângulo no lado esquerdo. Esse é um possível problema por ser uma classe muito grande, o que poderia indicar que poderia ser dividida em outras classes. Porém, analisando o código da classe, percebemos que o seu tamanho é devido a um grande número de gets e sets e não há muito o que refatorar. O segundo problema é o grande número de classes que herdam de HttpServlet. Observando o código, evidenciamos que há muitas classes de semântica parecida e com métodos muito semelhantes, indicando uma possibilidade de criar novos níveis de hierarquia.
Figura - GridCoupling
Gráfico que mostra o grande número de dependências entre classes, onde uma mudança em uma dessas classes traria um grande impacto para o sistema.
Class Dependency
Outros Problemas
Outros problemas encontrados estão relacionados à qualidade do código além dos apresentados anteriormente. Na figura 9, podemos observar um método mal estruturado que possui um grande overhead de acesso ao banco. Ele recebe uma lista de nomes para carregar e para cada nome ele busca todos os membros do banco, compara com o nome em questão e adiciona na lista de retorno. Isso poderia ser feito com um único acesso ao banco.
Além disso, na linha comentada, há um possível erro de implementação, pois para o primeiro nome analisado ele remove a última letra e para os demais nomes ele lança a exceção
StringIndexOutOfBoundsException.
Outro problema encontrado é mostrado na figura 10, onde vemos um método com código desnecessário e que pode até causar erros na aplicação, pois ele tenta acessar a primeira posição da lista num momento onde a lista pode estar vazia, causando uma exceção de
Análise pelo Metrics Tool
DOT (Degree Of Tangling): é o grau em que um componente (no nosso caso, classe) é dedicado a um ou mais concerns. A análise indicou que o componente ControleMembro teve DOT alto, aproximadamente 0.78222, enquanto todas as outras classes tiveram DOT zero (0). Isto indica que a classe ControleMembro tem muitos concerns e a quantidade de código referente a eles é significativa com relação às linhas totais. Analisando em detalhes, vemos que aquela é a única classe que tem código dos dois concerns e eles, somados, são responsáveis por
aproximadamente 62,5% das linhas de código. As outras classes têm no máximo um concern e a quantidade de linhas de código do concern não é tão representativo.
Análise de complexidade do projeto:
DIT (Depth of Inheritance Tree): É o tamanho do ramo mais longa da árvore de herança do projeto, que teve valo igual a 6, que é alto, indicando que pode haver um mau uso de herança, podendo ter classes mãe e filha que poderiam se tornar uma única classe. Além disso, um ramo grande indica que há classes com uma quantidade de métodos herdados potencialmente grande, tornando-a mais complexa e de comportamento mais imprevisível.
WOM (Weighted Operations in Module): É o número de métodos por módulo. O projeto apresentou 203 métodos, possivelmente tornando o código difícil de se entender, com potencial de ser minimizado através de herança ou parametrização.
LOC (Lines Of Code): É o número de linhas de código totais do projeto. Ele apresentou 1453 linhas de código, podendo ser minimizado através de herança.
CBC (Coupling Between Components): Conta o número de componentes que chamam métodos ou campos de outros. Indica o quão as classes dependenem umas das outras. Teve valor 97. Requer atenção pois uma mudança que ocorra numa classe pode impactar várias outras. É possível minimizar este tipo de efeito utilizando interfaces entre classes.
VS (Vocabulary Size): É o número de assets implementados. O projeto tem 38 classes que pode dificultar o entendimento do sistema. Pode-se minimizar dividindo as classes em pacotes. NOC (Number Of Children): Indica o número de classes-filhas, que são 6. Uma quantidade muito grande indicar que pode haver mal uso de reuso, apesar de também indicar que o reuso é no projeto é maior.
LCO (Lack of Cohesion in Operations): É a diferença entre os pares de métodos que trabalham em campos de classe diferentes e os que trabalham em campos iguais ou similares. Indica a dissimilaridade par-a-par entre operações do mesmo módulo, caracterizando uma grande complexidade e consequente probabilidade maior de haver erros e manutenção mais difícil. Teve valor 578, devendo o projeto ser revisto e ter seu encapsulamento melhorado.
Análise de concerns:
CDC (Concern Diffusion over Components): É a quantidade relativa de componentes que apresentam o concern. Para o concern Dados, aproximadamente 90.90% das classes, enquanto para Persistência é 88.62%. Ambos concerns estão muito espalhados pelas classes. Para Dados, as classes podem ser parametrizadas para diminuir a dependência de dados, mas também tal tarefa pode ser custosa demais. Já para Persistência, uma interface pode ser feita para minimizar a dependência. Para ambos casos também devem ser levados em conta dividir as classes que apresentam os dois concerns, juntar classes com o mesmo concern em um número menor e fazer uma melhor divisão de pacotes para isolar.
DOSC (Degree Of Scattering across Classes): Indica o quão espalhado entre as classes o concern está. Dados tem DOSC 17 enquanto Persistência, 9. Para minimizar esta métrica, deve-se juntar o código de cada concern em clasdeve-ses deve-separadas e em menor quantidade.