archivo

Archivo de la etiqueta: Sonar

En Sonar, a la hora de revisar el cumplimiento de reglas, una de las que aparece muy frecuentemente en el software que nos entregan es la regla PMD “Security – Array is stored directly” que se produce cuando uno de los parámetros que aparece en la definición de un método, de un constructor o de un setter (es bastante frecuente que cuando los accesores son autogenerados por el IDE o por generador de código se produzca este tipo de incumplimientos, salvo que se haya tenido en cuenta previamente) es un array y en el interior del método se realiza una asignación de dicho objeto a otro (que no es local) sin realizarse previamente una clonación (se tendría lo que algunos denominan acoplamiento entre objetos por compartir direcciones de memoria).

Si no clona el objeto resulta muy peligroso, ya que el número de objetos que apuntan a las mismas direcciones de memoria aumenta y en consecuencia se incrementa la posibilidad de errores colaterales, los cuales además en estos casos no son siempre triviales de localizar.

Nos centramos mucho en los requisitos funcionales y en cierto modo es lógico que así sea, ya que si una aplicación no cumple el propósito y expectativas que se tiene sobre la misma de nada vale que la calidad del producto y del desarrollo sea impecable.

Parto de la base de que no es nada fácil conseguir lo que el usuario o el cliente busca, entre otras cosas porque es complicado que ambos tengan del todo claro lo que quieren (sí lo pueden tener en la cabeza, pero una aplicación son muchos detalles y es difícil que tengan en cuenta todos) y también que los analistas entiendan e interpreten a la perfección lo que les están contando.

Precisamente porque el desarrollo de un producto tiene asociado inherentemente tareas de mantenimiento correctivo y evolutivo es necesario ir más allá de que el producto funcione, entendiendo que el diseño y codificación realizados deben hacerse pensando en que habrá que modificar la aplicación, para ello desde un primer momento hay que pensar también en la calidad de la aplicación desde el punto de vista de la arquitectura, diseño y construcción.

No tener en cuenta estos detalles provocarán en el sistema desarrollado una deuda técnica que se arrastrará en los mantenimientos y tenderá a empeorar salvo que se decida atajar, ya que el software tiende a deteriorarse con los mantenimientos, siendo este deterioro muy sensible en aquellos casos donde el producto no ha tenido una ejecución buena desde el punto de vista de la calidad del código.

Sonar permite ver de manera muy sencillo lo que esconden las aplicaciones debajo de la alfombra a través de las diferentes métricas que permite obtener. Es cierto que solo son un conjunto de métricas y que hay que saber interpretarlas de manera individual, colectiva y en el contexto de cada aplicación, pero permiten dar una visión objetiva y externa tanto a clientes como a proveedores, ya que no hay trampa ni cartón si ambas partes conocen el juego de métricas y reglas que se le van a pasar al código.

Desde mi punto de vista Sonar es una herramienta de implantación obligatoria en los departamentos de desarrollo y/o de calidad del software, ya que además de permitir detectar aspectos del desarrollo que generan deuda técnica, permiten determinar la complejidad (y por tanto tiempo y esfuerzo) de los mantenimientos y puede ser utilizada para establecer determinados acuerdos de niveles de servicio en cuanto al software que se entrega.

Haciendo una revisión de algunos incumplimientos de reglas detectados por Sonar, nos llamó mucho la atención a un proveedor y a mi un incumplimiento que se repetía en distintas partes del código de una aplicación Java basado en una regla de CheckStyle denominada “Parameter Assignment”, ya que ninguno de los dos entendíamos por qué.

¿Cuándo se produce el incumplimiento de esta regla? Cuando dentro del cuerpo de un método se asigna un valor a un parámetro de entrada.

Para intentar entender los motivos acudí a Internet y al libro “Refactoring: improving the design of existing code” de Martin Fowler y Kent Beck y básicamente es el siguiente:

Mejorar la comprensibilidad de los métodos por la confusión que existe en muchos casos con el paso de parámetros a los métodos en Java. En Java siempre se realiza un paso de parámetros por valor, es decir, el método trabaja con una copia del parámetro enviado por el método llamante por lo que cualquier posible cambio en dicho parámetro dentro del mismo no afecta hacia fuera de él, no obstante la confusión la tenemos cuando el parámetro que se envía es un objeto en lugar de un tipo primitivo, en ese caso también existe un paso por valor, pero la copia en esta caso es una referencia a memoria por lo que los cambios en este caso si pueden tener su reflejo en el método llamante. Como pese a que el paso del parámetro es siempre por valor, pero el comportamiento varía en función de si lo que se pasa es un objeto o un tipo primitivo una forma de darle un tratamiento homogéneo es tratar el parámetro de entrada como una “constante” y que si hay que hacer operaciones se haga con variables u objetos temporales.

Además de tratarse de una regla de estilo (claridad, comprensión y homogeneización), en mi opinión (y es solo mi opinión) también es una forma de prevenir cambios no deseados en el valor de un objeto mediante al acceso a su contenido en los métodos donde se pasa el valor de su referencia en memoria.

Sonar permite calcular muchas métricas de carácter individual, como por ejemplo Cobertura, Duplicated Lines, Complejidad Ciclomática, RFC, LCOM4, etc…, pero también dispone de métricas que ofrecen resultados en función de poner en relación una serie de métricas diferentes.

Un ejemplo de ello lo tenemos en Technical Debt (base como he comentado en otros artículos de lo que es la filosofía y fin último de Sonar, tal y como dice su lema “Put your technical debt under control) y otro lo tenemos por ejemplo en las métricas proporcionada por el plugin de Sonar denominado SIG Maintainability Model.

Como indica la página que el plugin tiene en Sonar, se trata de una implementación del Modelo de Mantenimiento del Software Improvement Group (SIG).

¿Qué es el Software Improvement Group? Es una firma de consultoría holandesa con sedes en otros países europeos, que según especifica en su página web se basa en dar una serie de resultados, basados en hechos (métricas objetivas) y no en opiniones, proporcionando evaluciones de riesgos imparciales, objetivas,verificables y cuantitativas relacionados con los sistemas de información corporativos que se quieran estudiar.

Uno de los servicios que proporciona la empresa SIG es la certificación de la mantenibilidad de los productos software según el estándar internacional ISO/IEC 9126. Dicho estándar clasifica la calidad del software en una serie de aspectos, uno de los cuales es la mantenibilidad basándose el mismo en la obtención de las siguientes métricas: Estabilidad, Facilidad de análisis, Facilidad de cambios y Facilidad de Pruebas.

Por tanto el plugin de Sonar SIG Maintainability Model, permite calcular dichas métricas, las cuales resultan significativas ya que determinan el grado de mantenibilidad de un software basado en un estándar internacional.

Una vez que hemos podido apreciar lo relevante que resulta este plugin, toca analizar como calcular cada una de sus métricas.

El cálculo se basa en la obtención en primer lugar de una serie de métricas más simples (ya que las métricas finales indicadas anteriormente son el resultado de la combinación de las mismas) y clasificando los resultados de dichas métricas en cinco posibles escalas (las cuales voy a ordenar de menor a mejores resultados desde el punto de vista de la mantenibilidad):

Volumen: Se obtiene a partir del número de líneas de código de la aplicación.

Escalas:

–: > 1310000 líneas de código.
-: > 655000 líneas de código.
0: > 246000 líneas de código.
+: > 66000 líneas de código.
++: > 0 líneas de código.

Duplicidades: Se obtiene a partir del porcentaje de líneas duplicadas en la aplicación:

Escalas:

–: > 20% líneas duplicadas
-: > 10% líneas duplicadas
0: > 5% líneas duplicadas
+: > 3% líneas duplicadas
++: > 0% líneas duplicadas

Pruebas unitarias: Se obtiene a partir del grado de cobertura del código a través de pruebas unitarias.

Escalas:

–: > 95% cobertura
-: > 80% cobertura
0: > 60% cobertura
+: > 20% cobertura
++: > 0% cobertura

Complejidad: Se obtiene a partir de la complejidad ciclomática de los métodos.

La forma de cálculo es un poco más compleja ya que se realiza en dos pasos:

1) Clasificar cada método en uno de los siguientes rangos en función de su complejidad ciclomática:

Muy alta: > 50
Alta: > 20
Media: > 10
Baja: > 0

2) A continuación la escala se obtiene a partir del porcentaje de métodos que se encuentran en los rangos definidos en el paso 1):

Escalas:

–: Resto de casos
-: C.C. Media <50%; C.C. Alta <15%; C.C. Muy Alta <5%
0: C.C. Media <40%; C.C. Alta <10%; C.C. Muy Alta <0%
+: C.C. Media <30%; C.C. Alta <5%; C.C. Muy Alta <0%
++: C.C. Media <25%; C.C. Alta <0%; C.C. Muy Alta <0%

Tamaño unitario: Se obtiene a partir del número de líneas de código de los métodos.

La forma de cálculo es un poco más compleja ya que se realiza en dos pasos:

1) Clasificar cada método en uno de los siguientes rangos en función de su número de líneas de código (LOC):

Muy alta: > 100
Alta: > 50
Media: > 10
Baja: > 0

2) A continuación la escala se obtiene a partir del porcentaje de métodos que se encuentran en los rangos definidos en el paso 1):

Escalas:

–: Resto de casos
-: LOC Media <50%; LOC Alta <15%; LOC Muy Alta <5%
0: LOC Media <40%; LOC Alta <10%; LOC Muy Alta <0%
+: LOC Media <30%; LOC Alta <5%; LOC Muy Alta <0%
++: LOC Media <25%; LOC Alta <0%; LOC Muy Alta <0%

Una vez calculadas las métricas simples, se calculan las métricas complejas que son las que definen la métrica de mantenibilidad de la ISO/IEC 9126, realizando una simple media de las escalas obtenidas en las métricas que definen cada métrica compleja:

Analizabilidad (Analysability) (A): [VOLUMEN], [DUPLICIDADES], [PRUEBAS UNITARIAS], [TAMAÑO UNITARIO].
Modificabilidad (Changeability) (C): [DUPLICIDADES], [COMPLEJIDAD]
Estabilidad (Stability) (S): [PRUEBAS UNITARIAS]
Testeabilidad (Testability) (T): [PRUEBAS UNITARIAS], [COMPLEJIDAD], [TAMAÑO UNITARIO].

De esta manera los valores de A, C, S y T oscilará cada uno entre — (valor más malo) y ++ (valor más bueno).

Estos cuatro valores se representarán en un gráfico donde cada eje representa el valor de estas métricas, teniendo cada eje tres escalas que estarán más separadas de la posición (0,0) que se corresponde con el valor (–) conforme más buena sea la métrica. En sentido horario, los ejes representan respectivamente a T, A, C y S.

Además de esa representación, el color del gráfico también es identificativo de la mantenibilidad de la aplicación, ya que tendrá un color entre el rojo (todas las métricas –) y verde (todas las métrica ++).

En demasiadas ocasiones intentamos buscar soluciones sin analizar antes cuál es el problema, de esta forma encontrar la posible solución se convierte en casualidad.

Esto es aplicable también al desarrollo de software.

Como ya he tratado en artículos anteriores, hemos implantado Sonar en nuestra organización y aunque todavía tenemos que avanzar mucho (sobre todo en definir un conjunto de reglas a analizar que se adapte más a nuestra organización que las que te vienen por defecto, las cuales por otra parte tampoco están nada mal) las métricas que estamos obteniendo son muy interesantes, ya que además de poder analizar la evolución de la calidad del software conforme va evolucionando una aplicación, permite como es lógico estudiar cómo está la misma en un momento dado del tiempo.

Eso precisamente hemos hecho con una aplicación que estaba presentando problemas en su mantenimiento debido a síntomas evidentes de alto acoplamiento. Una revisión rápida de las métricas de Sonar nos mostraba clases con RFC mayor que 200 (incluso alguna con un valor mayor que 300), lo que quiere decir que la suma de los métodos de la clase más la invocación de métodos de clases distintas lleva a esos valores, lo que da una idea del acoplamiento existente y de las repercusiones que puede tener hacia fiera modificaciones en dichas clases y dependencias cíclicas entre paquetes. De esta forma podemos determinar de forma sencilla dónde puede encontrarse el centro del problema (existe un alto acoplamiento, con métricas que hacen evidente este problema), después tocará ver cuál es la solución más adecuada que puede pasar desde el rediseño de las clases problemáticas hasta la posibilidad de rehacer gran parte de la aplicación (dependerá también de estudiar cómo está construida y cuál es la solución más rentable de cara a reducir la deuda técnica y a facilitar la mantenibilidad de las aplicaciones).

Hace poco implantamos Sonar en nuestra organización con el objetivo de ir controlando la calidad del software que se nos iba entregando, ya que estamos bastante preocupados por la mantenibilidad del software, algo que todavía se acusa más en épocas como la actual donde cada céntimo de euro importa.

Una de las principales curiosidades que tenía era observar a través de las métricas que ofrece Sonar si efectivamente, desde el punto de vista de la complejidad y de la mantenibilidad del software, la realización de sucesivos mantenimientos correctivos y evolutivos empeoraba dichos indicadores, tal y como establece la teoría, así como multitud de estudios empíricos realizados sobre la materia.

Pese a que haría falta más tiempo para poder tener una mayor cantidad de datos y no he entrado en detalle en todas las métricas, se puede empezar a concluir que efectivamente en la mayoría de proyectos donde se han realizado tareas de mantenimiento correctivo y evolutivo se han empeorado indicadores. Hay excepciones, ya que en algunos casos existen métricas que han mejorado y otros en las que prácticamente conservan sus valores.

Las principales métricas que se han visto empeoradas han sido: LCOM4, líneas duplicadas, la complejidad ciclomática y los comentarios de las APIs públicas. Resulta en cierto modo lógico que se incremente la complejidad ciclomática, ya que ésta depende directamente del tamaño del código. Si hubiéramos tenido unos valores de cobertura de código aceptables, podrían haberse extraido conclusiones también sobre esta métrica, algo que no ha sido posible, porque como comenté en otro artículo, la mayoría de las aplicaciones que tenemos no bienen acompañadas de pruebas unitarias y por tanto no es posible bajar del 0%.

Por tanto, la deuda técnica lejos de reducirse, se está incrementando, lo que provoca que el software sea cada vez menos mantenible y en consecuencia cueste más realizar modificaciones en el mismo y exista una mayor probabilidad de que el software se entregue con errores.

Nuestra intención con Sonar, no es ser espectadores de sus métricas, sino con el paso del tiempo exigir que el software que se entregue alcance unos umbrales mínimos en las principales métricas, tanto en desarrollos nuevos como en mantenimientos, ya que si no controlamos no conseguiremos mejorar y reducir nuestros costes de mantenimiento y el número de errores del software que llegan a la fase de pruebas o a producción.

La métrica RFC (Response for class) forma parte, como sucede con el caso de LCOM4 del conjunto de métricas enunciadas por Chidamber y Kemerer y que tienen como objeto obtener valores de referencia sobre el diseño orientado a objetos de una determinada aplicación.

En el caso de RFC lo que se mide es el acoplamiento entre clases, ya que su valor se obtiene a partir del número total de métodos que pueden potencialmente invocados en respuesta a un mensaje enviado a un objeto de la clase, es decir, el número de métodos que pueden ser ejecutados, cuando un método de la clase es invocado.

Dicho de otra manera, vendría a ser el número de métodos de una clase más el número de métodos de otras clases que son invocados por métodos de la clase (no contando más de una vez cada método, es decir si un método de una clase Y puede ser invocado por tres métodos de una clase X sólo se suma una unidad).

¿Qué es el acoplamiento? Es el grado de dependencia entre clases, por lo que cuando nos encontramos con situaciones donde el acoplamiento es alto crecerán las posibilidades de que el mantenimiento de las clases sea más complejo, ya que un cambio en el comportamiento de un método puede afectar a todos los que lo llaman y un cambio de interfaz del método puede provocar la necesidad de modificar el código de los métodos que lo llaman. También se considera que clases con un acoplamiento alto son más complicadas de entender y dificultan las tareas de testeo.

Un ejemplo de acoplamiento, fuera del mundo de la orientación a objetos, lo tenemos por ejemplo en la dependencia entre una aplicación y una serie de objetos (por ejemplo tablas o vistas) de un esquema de base de datos de otra, en este caso, sobre todo si las aplicaciones son gestionadas por equipos distintos y todavía no están lo suficientemente maduras, se correrá el riesgo permanente de que un cambio en el modelado de datos provoque que la aplicación que hace uso de ellos deje de funcionar adecuadamente. Además se podrá ver afectada por otros factores (cambio de instancia del esquema, cambio de sistema de gestión de base de datos, etc…).

El acoplamiento entre clases es inevitable, ya que los objetos cooperan y precisamente ofrecen servicios a través de sus APIs públicas para poder ser utilizados por otros. No se trata por tanto de eliminar el acoplamiento ya que eso no será posible, sino de intentar conseguir niveles de acoplamiento entre clases bajos, ya que permitirán reducir el número de efectos colaterales en el mantenimiento del sistema, haciendo más sencillas estas tareas y reduciendo las tasas de errores en tiempo de compilación y en tiempo de ejecución (cuando se cambian comportamientos a los métodos). Además de tener en cuenta en el diseño de las clases la existencia de un bajo acoplamiento, se pueden utilizar diferentes estrategias, como por ejemplo la creación de clases donde se centralice ese acoplamiento e incluso se implementen en las mismas fachadas que orquesten llamadas a métodos, de manera que tengamos algunas clases que sí tendrán valores altos o muy altos de RFC, pero que a cambio permitirá que se reduzcan el RFC de un buen número de clases.

A través de Sonar se puede obtener la media de RFC de la aplicación, de cada paquete de la misma y del conjunto de clases que la conforman. Se trata de medias aritméticas puras, sin aplicar ningún tipo de ponderación o umbral de valor de RFC de una clase.

Ahora viene la pregunta de siempre en este tipo de métricas, ¿a partir de qué valor se puede considerar que un RFC es demasiado alto?. Como sucede en el resto de métricas (salvo algunas excepciones como LCOM4) hay interpretaciones para todos los gustos, también como sucede con las otras, queda bastante claro cuando un RFC es muy alto y un RFC es muy bajo, por lo que “desde lejos” se pueden apreciar valores que pueden recomendar el estudio del nivel de acoplamiento de determinadas clases. Se pueden considerar aceptables valores de RFC <= 50.

También es posible obtener valores relacionando el RFC de una clase y su número de métodos (NOM). En programas realizados en Java Se pueden considerar aceptables valores de RFC/NOM <= 10.

LCOM4 es otra métrica que utiliza Sonar y en la cual el concepto también es independiente de la existencia del producto.

Esta métrica mide la falta de cohesión de una determinada clase (forma parte de un conjunto de métricas que cogen su nombre de las iniciales de Lack of Cohesion of Methods). Antes de entrar a analizar cómo funciona esta métrica, es de interés mencionar aunque sea en líneas generales, qué es la cohesión y para qué sirve.

La cohesión mide la especialización (o la proximidad al principio de responsabilidad única) de una determinada clase o lo que es lo mismo cómo de relacionados están los distintos elementos (atributos y métodos) que la componen. Se entiende que clases más especializadas son más mantenibles. Esto es fácil de apreciar cuando por ejemplo miramos el código de una clase cohesionada y el código de una clase Tutti Frutti, en el primer caso veremos que la clase describe un objeto y su comportamiento, considerando dicho objeto como algo “atómico”, en el segundo caso nos podremos encontrar (exagerando mucho) clases que plancharán la ropa, jugarán al fútbol, te hacen un Cola Cao y son capaces de mantener una charla contigo sobre metafísica. Evidentemente, por muy complejo que sea el primer tipo de clases, probablemente el comportamiento, inteligibilidad, mantenibilidad, etc… de la segunda se vea afectado en sentido negativo.

Existen distintos grados de cohesión, según la forma en qué estén relacionados sus elementos. En el párrafo anterior me centré en la de carácter funcional, que es la que me parece más interesante.

¿Cómo funciona LCOM4? Cálcula un valor para una determinada clase, si ese valor es mayor que uno, la clase es sospechosa de falta de cohesión (cuento mayor sea dicho valor, menos cohesión tendrá). Lo que hace Sonar es indicarte el porcentaje de clases respecto al total que tienen un LCOM4 mayor que uno, así como calcularte el LCOM4 medio. Como en el resto de métricas de Sonar, la clave está en definir umbrales, es decir, qué porcentaje de clases con LCOM4 mayor que uno se considera aceptable y cuál es el máximo valor de LCOM4 admisible para las clases. Puede haber casos donde se pueda justificar superar dichos umbrales (suponiendo que dichos umbrales se hayan depurado con la experiencia), en ese caso, el equipo de desarrollo deberá explicar los motivos y ser coherentes si quiere que se le acepte la entrega.

Para el cálculo del LCOM4 de una clase básicamente lo que hace es medir el número de relaciones diferentes que se establecen entre métodos, teniendo en cuenta que un método se considera relacionado con otro si acceden a un atributo común de la clase o si uno llama a otro. Para el cálculo hay métodos que no se tienen en cuenta como por ejemplo los constructores. Tampoco se tienen en cuenta los accesores.

A través de este enlace podréis acceder a un ejemplo bastante bueno para comprender cómo se calcula esta métrica.

Por tanto, la cohesión es un factor a tener en cuenta junto al acoplamiento (entre otros factores) ya que condiciona la mantenibilidad y deuda técnica de los proyectos de desarrollo de software.

Me gusta Sonar y creo que a mis compañeros también. Para ser justo, hay que mencionar también a PMD, Checkstyle y FindBugs porque Sonar debe mucho a esos proyectos.

Las métricas de Sonar asustan porque son muchas y algunas son complicadas de entender tanto en su significado como en su cálculo. Entenderlas es importante, pero tratar de interpretar a corto plazo el significado de todas puede llegar a hacer que sea algo tan abrumador que haga que se pierda el interés en todo lo que te puede proporcionar el producto.

Siguiendo este punto de vista, yo entiendo que la integración de Sonar dentro de nuestros procedimientos de certificación de la calidad del software resulta muy importante, pero también que su incorporación debe ser gradual, consolidando diversas métricas y mediante diferentes iteraciones y con tiempo, definir lo que serán nuestros márgenes de tolerancia, una vez que consigamos esto, ya será mucho más fácil ir incorporando en nuestros análisis nuevas métricas, sin olvidar de la mejora continua de los umbrales que se definan, porque sólo el tiempo y nuestra experiencia nos permitirá definir unos límites acordes a tener una deuda técnica baja, sin que suponga necesariamente un sobrecoste no asumible en los desarrollos, porque los presupuestos que tenemos son los que son y las aplicaciones, sobre todos aquellas que llevan en producción más tiempo, están como están.

Por ese motivo, probablemente nos centremos inicialmente en las siguientes métricas: Cobertura del código por pruebas unitarias, duplicidad de código, complejidad ciclomática y los comentarios, ya que son las más fáciles de interpretar y tienen repercusión directa en la deuda técnica.

Nos tocará definir, como he comentado anteriormente, cuáles serán los umbrales a partir del cual aceptaremos un software entregado, al principio nos equivocaremos y seremos o muy injustos con el proveedor o demasiado blandos, pero eso no me preocupa porque realmente lo importante es consolidar unos umbrales cada vez más acordes con la realidad y que también los proveedores entiendan que para nosotros no sólo es importante que el producto funcione, sino que también que los costes de mantenimiento se vean afectados lo menos posible por esos intereses que genera la existencia de deuda técnica en nuestras aplicaciones.

Probablemente definamos para cada métrica diferentes umbrales, ya que como he comentado en otros artículos, en el nuevo enfoque que tenemos pensado darle en las revisiones de la calidad del software y de su proceso de desarrollo y mantenimiento, vamos a definir diferentes itinerarios de validación en función de las características de la aplicación, ya que no es lo mismo un mantenimiento que un nuevo desarrollo y además todas las aplicaciones no tienen el mismo nivel de criticidad, complejidad, etc…

Soy consciente de que cada itinerario que definamos complicará un poco todo, ya que serán más umbrales los que tenemos que ajustar, pero entiendo que este incremento de complejidad es necesaria, porque umbrales generales no darán buenos resultados porque son precisamente eso, demasiado generales.

Por tanto, tenemos que ser coherentes con el número de itinerarios ya que tampoco es cuestión de tener itinerarios a la carta (para sistemas especialmente críticos sí que puede tener justificación, pero serían excepciones), para de esta forma tanto el ajuste de los umbrales no se nos escape de las manos y para tener en general, en los procesos de verificación del software y del desarrollo una visión de lo que se hace (demasiados caminos o formas de hacer las cosas, hace que la idea de conjunto se difumine y se requiera estar muy encima de todo para saber realmente qué se está haciendo y supondrá un esfuerzo que realmente no creo que merezca la pena).

En paralelo debemos empezar a trabajar con la definición de las reglas, ya que si bien son de utilidad las que Sonar trae de serie, necesitamos algo más, ya que nos gustaría que se verificase hasta donde sea posible el cumplimiento de las directrices de nuestro libro blanco de desarrollo, creado en su día y actualizado desde entonces con el objetivo de dar uniformidad a todos los nuevos desarrollos y mantenimientos evolutivos importantes, para de esta manera acotar su diversidad tecnológica y de arquitectura, facilitando de esta forma futuros mantenimientos y simplificando, hasta donde es posible, las tareas de administración del software que sirve las mismas.

Para ello, tendremos que utilizar los mecanismos de extensión de PMD. Este tema está todavía bastante verde y tocará madurar, ya que será necesario realizar ese desarrollo, pero teniendo claro qué reglas queremos que se verifiquen, además, tenemos que elegir dentro del conjunto de reglas de PMD, Checkstyle y FindBugs con cuáles nos quedamos.

Una vez realizada la extensión, tocará definir los umbrales para las reglas, que también serán variables en función de los itinerarios que se definan. Como podéis ver, si todavía nos queda camino por recorrer con las primeras métricas, no quiero decir nada lo que nos queda por andar en lo que a las reglas se refiere. En cualquier caso es cuestión de ir avanzando, aunque sea lentamente, pero avanzando.

Sonar es un producto bastante interesante y que desde mi punto de vista, debería ser tenido en cuenta en los ecosistemas de verificación de la calidad del software. Cierto es que no te dice si un producto funciona o no (cierto es que están las pruebas unitarias, pero para ello éstas deben estar desarrolladas), ya que para eso están las pruebas funcionales y no el análisis estático de código, pero sí que es bastante útil para poder evaluar la calidad de desarrollo de las aplicaciones, su mantenibilidad y su grado de adecuación a las directrices de desarrollo que se marquen.

También Sonar debería ser un referente para los proveedores de servicios de desarrollo de software, ya que la calidad de lo que se entrega puede ser un aspecto diferencial respecto a la competencia.

La existencia de código duplicado en las aplicaciones es un problema más grande de lo que realmente se suele considerar.

Es importante entender que código duplicado no es exáctamente código exáctamente igual, sino que puede ser código con ligeras adaptaciones. Existen algoritmos, como el que utiliza CPD para la detección de estas duplicaciones. Es cierto que a veces puede haber falsas alarmas, pero su funcionamiento está lo suficientemente depurado como para pensar que los resultados que ofrece deben ser tenidos en cuenta, aunque sea para estudiarlos.

La existencia de código duplicado afecta a la mayoría de los ejes de los que depende la deuda técnica, ya que provocará una mayor complejidad ciclomática (ya comenté en el artículo que dediqué a esta métrica que esta es función de las líneas de código de la aplicación porque es normal que conforme crezca se incrementen el número de posibles caminos lógicos de la misma), un mayor número de pruebas unitarias (lo que afectará al % de cobertura, si no se construyen esas pruebas), una mayor cantidad de código que documentar, un posible incremento del número de reglas incumplidas, ya que todas aquellas reglas que se incumplan en un fragmento de código, se incumplirán en todos aquellas clases y métodos donde se haya duplicado el mismo, etc…

Por tanto, el código duplicado incrementará los costes de mantenimiento del software y esto es un problema.

¿Cómo se llega a la existencia de código duplicado? En primer lugar porque es prácticamente imposible conseguir un código sin duplicaciones, salvo que la cantidad de dinero que se invierta para depurar y depurar sea tan grande que al final, no merezca la pena intentar conseguir un código sin duplicados. En segundo lugar, porque en muchos casos el código duplicado se genera sin querer, generalmente porque hay diversas personas trabajando en el proyecto y existen determinadas funcionalidades comunes que cada uno termina implementándola por su cuenta (se hace más de una vez lo mismo y de la misma manera), esto resulta complicado de controlar en un proyecto con un cierto tamaño, y también porque a veces el proyecto es tan grande y tan largo que te olvidas de que ya has implementado un determinado código y lo vuelves a hacer.

Tambień pesa mucho en todo esto la experiencia y pericia del programador, ya que un técnico de estas características si decide esmerarse en ello, producirá un código con menos duplicaciones que otro que no cuente con su bagaje profesional y/o sus capacidades.

Existen otras situaciones, las típicas urgencias, que también derivan en duplicar código. Hay que resolver un problema, he visto que en esta parte de la aplicación está resuelto de tal manera, tengo poco tiempo, así que copio el código y lo adapto.

PMD a través de CPD o Sonar que a su vez puede hacer uso del mismo, permiten obtener métricas de duplicidad del código y también navegar hasta donde se encuentran esas posibles duplicidades, por lo que pueden ser herramientas de mucha utilidad para estudiar esta métrica en las aplicaciones de tu organización y para tomar medidas para mejorar los datos si se estima conveniente.