La gestión de la complejidad es uno de los principales retos a los que nos enfrentamos a la hora de desarrollar software. Recientemente Patrick Smacchia me invitó a probar NDepend, una potente herramienta que nos proporciona, de forma muy visual e interactiva, una gran cantidad de información sobre ensamblados .NET.

Su utilización simplifica la gestión de una base de código compleja al poder realizar medidas objetivas sobre el código y poder comparar su evolución en el tiempo. También  facilita la comunicación al poder ver de forma muy visual la estructura y dependencias del código. Además, combinada con reflector (herramienta con la que se puede integrar), nos puede facilitar enormemente la tarea de entender o evaluar ensamblados no escritos por nosotros.

Los diferentes gráficos y resultados mostrados a continuación son el resultado del análisis mediante NDepend a una sencilla aplicación que escribí hace tiempo. Se puede observar el informe HTML que fue generado automáticamente por la herramienta aquí.

NDepend facilita ver la estructura y las interrelaciones entre los diferentes componentes de un proyecto de software así como responder a preguntas sobre la calidad u otros aspectos del software en base a los numerosos indicadores o métricas incluidos. Además, podemos realizar nuestras propias preguntas sobre el código utilizando CQL (Code Query Language), un lenguaje de consultas similar a SQL.

Al cargar un conjunto de ensamblados en NDepend se realiza un completo análisis de los mismos. A partir de ese momento tendremos a nuestra disposición una gran cantidad de información que podemos visualizar bajo una agradable interface. Al termino del análisis también se generará un informe en HTML con la información más relevante.

Métricas

Tenemos diferentes métricas a nuestra disposición, las cuales pueden operar a diferentes niveles: espacios de nombres, ensamblados, tipos, métodos y campos. Las métricas nos permiten detectar potenciales problemas en la arquitectura del software y nos pueden indicar la necesidad de reestructurar el código (refactoring).

En la siguiente imagen se observa un gráfico generado por la herramienta que representa el número de líneas de código de cada uno de los métodos de una aplicación. Cada recuadro sombreado representa un método, y su tamaño es proporcional al número de líneas de las que está compuesto. Además, los métodos están agrupados dentro de los tipos que les contienen, por lo que podemos ver su peso especifico dentro de la aplicación.

La cantidad de información que proporciona el gráfico anterior es muy elevada, siendo además interactivo por lo que nos permite navegar a las estructuras representadas dentro del proyecto.

Entre las diferentes métricas a nuestra disposición destacamos las siguientes (tenemos un listado completo en el sitio web de la herramienta):

  • Longitud: en instrucciones de lenguaje intermedio (IL), o en líneas de código. Una gran longitud en nuestros tipos o clases podría indicar un exceso de responsabilidad para estas y por lo tanto aconsejar la necesidad de refactorización.
  • Aferencia: la aferencia es el número de vías de entrada o referencias hacia la entidad bajo observación. En otras palabras, si estamos trabajando a nivel de métodos, la aferencia de un método nos indicará el número de métodos que dependen de este método bajo observación. Este indicador nos muestra la ‘importancia’ que tiene una determinada entidad. Si una entidad es muy ‘importante’ será más difícil modificarla, porque el número de entidades que depende de ella será elevado y al hacerlo, alguno de ellos podría dejar de funcionar.
  • Eferencia: indica el número entidades de las que depende esta entidad. Por ejemplo, a nivel de tipo o clase, nos indicaría el número de clases de las que depende la clase bajo observación. En general, nos interesa mantener este número bajo. Idealmente, un tipo solo debería depender de los tipos inmediatamente inferiores a el en la jerarquía.

CQL

Las consultas predeterminadas que NDepend realiza sobre nuestro proyecto durante su análisis principal se agrupan en las categorías que muestra la siguiente figura.

Esta consultas nos proporcionan una evaluación de nuestro código en base a diferentes parámetros de calidad y son totalmente personalizables.

Dentro de cada uno de los grupos podemos ver cada una de las consultas y las partes del software que no han superado la prueba. Al seleccionar una de las consultas, además, dichas partes se resaltaran tanto en el gráfico como en el visor de resultados.

<h3>Dependencias</h3>  <p>Un alto nivel de dependencias generalmente significará mayores problemas a la hora de realizar cambios o ampliar la funcionalidad de una aplicación. A través de la matriz de dependencias, podemos observar de forma gráfica e interactiva las dependencias entre los componentes del proyecto, lo cual nos facilita mantener dichas dependencias dentro de un nivel razonable. Por ejemplo, el que la segunda línea de la figura siguiente esté completa indica que todos los tipos de la aplicación dependen de tipos definidos en el ensamblado ‘mscorlib’, lo cual es de esperar ya que es el ensamblado principal del FrameWork.</p>  <p><img src="/images/07-11/2008-11-ndepend-dependency-matrix.png" /> </p>  <p>La herramienta nos proporciona también diagramas en los que el grosor de las líneas entre nodos indica el grado de dependencia con respecto a un ensamblado concreto.</p>  <p><img src="/images/07-11/2008-11-ndepend-dependencies.png" /></p>  <h3>Comparaciones y otras características</h3>  <p>Otra característica de NDepend es la comparación entre las diferentes versiones de un conjunto de ensamblados con lo que podemos ver su evolución y observar, por ejemplo, la efectividad de una etapa de refactorización del código. </p>  <p>Podemos ver un ejemplo de este escenario, así como de otros escenarios interesantes en <a target="_blank" href="http://www.ndepend.com/">el sitio web de NDepend bajo ‘Online Demos’</a>.</p>