Avançar para a área de conteúdo

ir para o conteúdo principal

developerWorks Brasil  >  Tecnologia Java  >

Arquitetura Evolucionária e Design Emergente: O design emergente pelas métricas

Usando métricas e visualizações para localizar e coletar o design oculto no seu código

developerWorks
Opções de documento

Opções de documento que necessitam de JavaScript não são exibidas


Classificar esta página

Ajude-nos a melhorar este conteúdo


Nível: Intermediário

Neal Ford, Application Architect, ThoughtWorks Inc.

30/Jun/2009

As métricas de software podem ajudá-lo a localizar elementos de design ocultos no seu código, permitindo que eles aflorem em padrões idiomáticos. Este capítulo da Arquitetura Evolucionária e Design Emergente mostra como o uso inteligente de métricas e visualizações permite a descoberta de importantes elementos do código que são obscurecidos pela complexidade acidental.

Uma das dificuldades do design emergente repousa na localização de padrões idiomáticos e de outros elementos de design ocultos no código. As métricas e visualizações são úteis para identificar partes importantes do código e permitem que você as extraia como elementos de design de primeira classe. As duas métricas em que me concentrarei neste artigo são complexidade ciclomática e acoplamento aferente. A complexidade ciclomática é a medida da complexidade relativa de um método em relação a outro. O acoplamento aferente representa a contagem de quantas classes diferentes usam a classe atual. Você conhecerá algumas ferramentas para visualização e compreensão das métricas, e verá como a combinação delas revela as características do design.

Sobre esta série

Esta série visa prover uma nova perspectiva sobre conceitos de arquitetura e design de software frequentemente discutidos, mas elusivos. Por meio de exemplos concretos, Neal Ford oferece a você um embasamento sólido nas práticas ágeis da arquitetura evolucionária e do design emergente. Por adiar decisões importantes sobre arquitetura e design até o último momento responsável, é possível impedir a complexidade desnecessária oriunda da subavaliação dos projetos de software.

Eu abordei a complexidade ciclomática em "Design Movido a Testes, Parte 2", mas existem algumas nuanças que não discutidas. Um fator complicador das medições de complexidade ciclomática via ferramentas Java™ é a unidade de trabalho. A complexidade ciclomática é uma medição no nível do método, mas a unidade de trabalho na programação Java é a classe. Consequentemente, essas medições geralmente chegam como a soma ou a média da complexidade de todos os métodos em uma classe. Ambas as medições são interessantes.

Por exemplo, é possível o cenário abaixo. Uma classe que apresenta massivamente um método complexo (CC = 40), mas que também possui uma grande quantidade de métodos muito pequenos (por exemplo, os pares de métodos get/set comuns no código Java). Com uma ferramenta como o JavaNCSS (consulte Recursos) que informa a métrica como a soma de todos os métodos, a complexidade ciclomática será um número alto para toda a classe. Se você usar uma ferramenta do tipo Cobertura, — que informa a complexidade ciclomática como uma média da classe — esta não parecerá mais tão má, pois a inundação de métodos simples amortizará o efeito causado por esse método altamente complexo. Em face dessa incompatibilidade de unidade de trabalho, o bom senso diz que, ao calcular a complexidade ciclomática, tanto a soma total quanto a média das medições devem ser examinadas. Se você considerá-las independentemente, o ruído poderá impregnar os resultados. O uso de ambos os números esvazia essa possibilidade.

Métricas de software versus métricas físicas

Em software, uma métrica significa aplicar uma medição de objetivo a artefatos de desenvolvimento a fim de determinar características bem específicas. Diferentes da métrica física (por exemplo, uma régua), a maioria das métricas de software não refletem nenhuma característica no mundo real. Um número de complexidade ciclomática (por exemplo, 5) não tem nenhuma unidade de medida e não diz nada sobre qualquer propriedade física do código. Esse número faz sentido apenas quando comparado à complexidade ciclomática de outro código.

As outras métricas de interesse para o design são os dois números de acoplamento: acoplamento eferente e aferente. O acoplamento eferente mede o número de classes às quais a classe atual faz referência. É fácil de determinar por uma inspeção simples: abra a classe em questão e conte as referências (nos campos e parâmetros) a outras classes. O acoplamento aferente é mais difícil de determinar e muito mais valioso. Significa quantas classes diferentes usam a classe atual. É possível usar a linha de comando fu para determinar isso ou recorrer a uma das muitas ferramentas que compreendem essa métrica. Um a delas é o ckjm, uma ferramenta de código livre para execução do conjunto de métricas orientadas a objeto de Chidamber e Kemerer (consulte Recursos). Embora sua preparação e execução sejam um pouco complicadas, ela fornece a complexidade ciclomática (informada como a soma da complexidade ciclomática de todos os métodos de uma classe) e os números dos acoplamentos eferentes e aferentes.

Depois de ter esses números em mãos, o que eles significam, principalmente em termos de design? Os números gerados como métrica fornecem uma dimensão única das informações sobre o seu código, no entanto, os números em si, frequentemente, não significam grande coisa. É possível gerar informações úteis a partir das métricas de dois modos. Um deles, é examinar como determinado valor se altera no decorrer do tempo e nas principais tendências. O outro é combinar métricas para enriquecer a densidade das informações (essa é a abordagem que mostrarei mais tarde neste artigo).

Métricas e design

Eu tenho torturado a base de códigos do Struts nos diversos artigos desta série — não por ter alguma coisa contra o Struts, mas porque ele é um projeto de código livre muito conhecido. Acredite-me: você pode encontrar características de design indesejáveis na maioria do código disponível no mundo! Como já comecei com o Struts, permanecerei com ele para ilustrar meus pontos.

A saída do ckjm é texto, que pode ser convertido para XML (e para outros formatos, depois de diversas transformações com XSLT). A Figura 1 apresenta a combinação de várias métricas do ckjm, onde WMC (Weight Methods per Class) é a soma da complexidade ciclomática dos métodos da classe e Ca é o acoplamento aferente:


Figura 1. Resultados das métricas do ckjm em forma de tabela
Tabular view of ckjm metrics results

A Figura 2 mostra a mesma tabela, classificada por WMC:


Figura 2. Métricas do ckjm, classificadas por WMC
ckjm results, sorted by WMC

Apenas olhando esse resultado, podemos dizer que DoubleListUIBean é a classe mais complexa na base de códigos do Struts. Isso sugere que ela é uma boa candidata para ser refatorada para remover um pouco da sua complexidade e tentar localizar padrões repetitivos e abstratos. No entanto, o número WMC não diz se o investimento na refatoração dessa classe, para melhorar seu design, será um bom uso do tempo. Observe que o Ca da classe é 3. Ou seja, ela é utilizada apenas por três classes diferentes, o que sugere que não vale a pena investir muito tempo para melhorar seu design.

A Figura 3 apresenta os mesmos resultados do ckjm, agora classificados por Ca:


Figura 3. Resultados do ckjm, classificados por acoplamento aferente
ckjm results, sorted by CA

Essa visualização combinada mostra que a classe mais utilizada no Struts é Component (o que não é nenhuma surpresa, já que o Struts é uma estrutura da Web). Embora Component não seja tão complexa, ela é usada por 177 classes diferentes, o que a torna uma boa candidata para aprimoramentos de design. Tornar o design de Component melhor repercute sobre um grande número de outras classes.

A combinação de WMC e Ca é o melhor modo para interpretar a perspectiva oferecida na Figure 3. Ela informa o que é mais importante e o que é mais complexo na base de código, em uma única visualização. Se você chegou à base de códigos sem nenhum conhecimento anterior, essa visão oferece insights sobre onde seus esforços produzirão potencialmente melhores resultados. Embora não seja infalível, agora você tem mais informações sobre a base de códigos do que conseguiria derivar simplesmente examinando resmas de código.

As métricas numéricas fornecem insight sobre o código, mas elas subsistem em um nível extremamente baixo, fornecendo informações sobre classes específicas, sem contribuir muito para a aquisição de uma visão holística de uma base de códigos. Há muita ferramentas disponíveis agora para elevar as métricas ao próximo nível por meio de visualizações.



Voltar para parte superior


Visualizações de métricas

Esse recurso fornece visualizações alternativas de dimensões específicas, tanto individualmente quanto agregando várias dimensões. A comunidade do Smalltalk criou um número imenso de visualizações de métricas (incluindo uma plataforma, denominada Moose, para ativar esses tipos de visualizações; consulte Recursos). Muitas das técnicas de métricas desenvolvidas por essa comunidade migraram para a programação do Java.

O iPlasma e os padrões de mercado

Algumas das questões comuns relativas à complexidade ciclomática são "Como comparar meu código ao de outros?" e "Qual é a quantidade ideal para determinada classe?" O projeto do iPlasma responde a essas questões (consulte Recursos). O iPlasma é uma plataforma, criada como um projeto em uma universidade na Romênia, para avaliação da qualidade do design orientado a objeto. Ele gera uma pirâmide e apresenta as principais métricas do projeto e a comparação dessas aos valores padrão do mercado.

Ao executar o iPlasma, você aponta para um diretório de códigos de origem e, depois de algum agito, produz uma pirâmide de métricas como a ilustrada na Figura 4 que se baseia na base de códigos do Struts 2.0.11:


Figura 4. Pirâmide de métricas do iPlasma
iPlasma metrics pyramid

Essa pirâmide estará cheia de informações, assim que você começar a compreendê-la. Cada linha tem uma porcentagem colorida derivada da proporção do número nessa linha em relação ao número abaixo dele. A Tabela 1 mostra o que os números indicam, de cima para baixo:


Tabela 1. Compreendendo a pirâmide do iPlasma
CódigoDescrição
NDDNúmero de descendentes diretos
HITAltura da árvore de hierarquia
NOPNúmero de pacotes
NOCNúmero de classes
NOMNúmero de métodos
LOCLinhas de código
CYCLOComplexidade ciclomática
CALLChamadas por método
FOUTFan out (número de outros métodos chamados por determinado método)

Os números indicam as proporções; as cores indicam onde as proporções se encaixam no faixa de valores padrão do mercado (derivados dos inúmeros projetos de código livre). As proporções podem ser verde (dentro do intervalo), azul (abaixo do intervalo) ou vermelho (acima do intervalo). Para a base de códigos do Struts, NDD e CYCLO estão fora do padrão de mercado, e LOC e NOM estão abaixo. Os intervalos usados são exibidos na Tabela 2:


Tabela 2. Valores padrão de mercado para as métricas do iPlasma
BaixoMédioAlto
CYCLO / Linha0.160.200.24
LOC / método71013
NOM / classe4710
NOC / pacote61726
CALLS / método2.012.623.20
FANOUT / chamada0.560.62 0.68

O iPlasma também gera conselhos com base na pirâmide, que são mostrados na exibição do iPlasma imediatamente abaixo da pirâmide. A Figura 5 mostra o conselho para o Struts:


Figura 5. Conselho do iPlasma
iPlasma advice

Os números que o iPlasma gera servem para dois propósitos. Primeiro, eles permitem que você compare a sua base de códigos ao de outros, e com várias dimensões. Segundo, esses números indicam os lugares onde você pode querer expandir seus esforços para melhorar a higiene e o design do código. Por exemplo, no caso do Struts, o iPlasma indica que a profundidade da árvore de hierarquia é muito grande e que os métodos tendem a ser muitos complexos. Contudo, você deve compreender esses números no contexto. Uma estrutura da Web como o Struts tenderá a ter uma hierarquia muito elaborada, o que significa que o número NDD provavelmente não causa preocupação. O número CC, no entanto, não tem nada a ver com o contexto — ele está muito alto e indica cheiro de design no nível do método.

Para fins de comparação, a Figura 6 mostra uma pirâmide do iPlasma para o projeto Vuze, um BitTorrent Client escrito na linguagem Java (consulte Recursos):


Figura 6. Pirâmide do iPlasma para o Vuze
iPlasma pyramid for Vuze

O Vuze é um projeto de grande porte (mais de 500.000 linhas de código), com problemas de design potencial quanto à profundidade da árvore de hierarquia, ao número de métodos em cada classe, ao número de linhas do código por método e ao número de chamadas por método.

Dependências

O design emergente requer visibilidade em relacionamentos e outras abstrações de alto nível no seu código. Tente perceber esses conceitos de alto nível nas chamadas do código de origem tendo em mente aquela famosa parábola dos cegos que tentavam compreender um elefante apenas pelo tato. Cada parte do elefante se parece com alguma coisa diferente, no entanto, o tato é muito localizado para permitir uma visão holística.

A determinação das dependências entre classes e objetos sofre do mesmo tipo de problema de localização. Ferramentas como o iPlasma permitem que você consulte um resumo das características gerais do código, no entanto, não informam os pontos específicos que devem ser investigados. Felizmente, outras ferramentas podem ajudá-lo a ver o elefante de diferentes prismas.

A comunidade do Smalltalk criou uma ferramenta denominada CodeCrawler (consulte Recursos), baseada na plataforma Moose, que oferece uma representação gráfica do código, com dimensões para tamanho da classe, comprimento do método e algumas outras métricas. É possível colocar o CodeCrawler para trabalhar com o código Java, mas isso é temerário. Felizmente, você não precisa lutar essa batalha porque o projeto X-Ray já venceu a guerra (consulte Recursos).

O X-Ray é um plug-in do Eclipse que gera várias visualizações úteis para ser ter a visão da estrutura geral do código, incluindo visualizações de setores circulares das dependências entre classes, conforme ilustrado para o Struts na Figura 7:


Figura 7. Visualizações do X-Ray das dependências de classes
X-Ray class dependencies view

Cada elemento, junto à borda do círculo, é uma classe e as linhas indicam as dependências entre classes. A espessura da linha indica a intensidade da dependência. Um clique na classe revela suas informações e um clique duplo a abre no editor do Eclipse. É óbvio que a visualização inclui muito mais informações úteis. Felizmente, é possível aplicar um zoom para ver as linhas individuais. As linhas em negrito indicam um forte dependência entre as classes (acoplamento eferente), e talvez signifiquem uma deficiência de projeto, quando o inter-relacionamento de duas classes é excessivo.

O X-Ray também inclui uma visualização similar das dependências entre pacotes, como ilustrada na Figura 8:


Figura 8. Visualizações do X-Ray das dependências dos pacotes
X-Ray view of package dependencies

Estrutura geral

Outro recurso do X-Ray, também baseado no CodeCrawler, apresenta uma visualização útil do código. A visualização da complexidade do sistema retrata a sua base de códigos como um gráfico no qual a hierarquia de descendentes aparece como uma visualização em árvore descendente, o tamanho da caixa reflete o número de linhas do código na classe e a largura da caixa, o número de métodos. A Figura 9 ilustra a visualização da complexidade do sistema:


Figura 9. Visualização da complexidade do sistema X-Ray
X-Ray system-complexity view

A visualização representa ainda as chamadas de saída (acoplamento eferente) como linhas rosas e as chamadas de entrada (acoplamento aferente) como linhas vermelhas. Como nas visualizações anteriores, clicar em uma das caixas abrirá a classe no Eclipse. Esse nível de informações fornece uma perspectiva única, difícil de se obter simplesmente olhando para o código. A localização de deficiências de projetos em aspectos específicos fica mais fácil quando é possível filtrar rapidamente determinada dimensões e estreitar as partes do código que necessitam de investigação adicional.



Voltar para parte superior


Resumo

O X-Ray e o iPlasma representam apenas um conjunto pequeno dos tipos de visualizações disponíveis para o código Java. O uso criterioso deles estreita rapidamente seu foco para aspectos do projeto que jazem ocultos nos porões do código. A localização de padrões idiomáticos é um dos capacitadores-chave do design emergente, e as ferramentas que facilitam a identificação de padrões (bons e maus) reduzem grandemente os esforços investigativos, o que libera mais tempo para refatorar o código e torná-lo melhor.



Recursos

Aprender

Obter produtos e tecnologias

Discutir


Sobre o autor

Neal Ford

Neal Ford é um arquiteto de software e Meme Wrangler, na ThoughtWorks, uma consultoria global de TI. Projeta e desenvolve aplicativos, materiais de instrução, artigos para revistas, treinamentos e apresentações em vídeo/DVD, e é autor ou editor de livros que abordam uma variedade de tecnologias, inclusive The Productive Programmer Seu enfoque é o projeto e construção de aplicativos corporativos de grande porte. Também é orador internacionalmente aclamado nas conferências de desenvolvedores ao redor do mundo. Conheça seu Web site.




Avalie esta página


Reserve um instante para completar este formulário para nos ajudar a servi-lo melhor.



 


 


Não
são úteis
Extremamente
úteis
 






Voltar para parte superior


Java e todas as marcas registradas baseadas em Java são marcas registradas da Sun Microsystems, Inc. nos Estados Unidos e/ou em outros países. Outros nomes de empresas, produtos e serviços podem ser marcas registradas ou marcas de serviço de terceiros.