code metrics - studio - ¿Cuál es la fascinación con las métricas de código?
metricas de codigo visual studio 2017 (18)
Últimamente, he visto varias preguntas relacionadas con las "métricas de código" en SO, y me pregunto ¿cuál es la fascinación? Aquí hay algunos ejemplos recientes:
- qué métricas de código lo convencen de que el código proporcionado es malo
- cuando, si alguna vez es la cantidad de líneas de código, una métrica útil
- redacción de pruebas de calidad
En mi opinión, ninguna métrica puede sustituir una revisión del código, sin embargo:
- algunas métricas a veces pueden indicar lugares que necesitan ser revisados, y
- cambios radicales en las métricas en marcos de tiempo cortos pueden indicar lugares que deben revisarse
Pero no puedo pensar en una sola métrica que, por sí misma, siempre indique el código "bueno" o "malo"; siempre hay excepciones y razones para cosas que las mediciones no pueden ver.
¿Hay algún conocimiento mágico que obtener de las métricas de código que he pasado por alto? ¿Los programadores / gerentes perezosos buscan excusas para no leer el código? ¿Las personas se presentan con bases de código de legado gigantes y buscan un lugar para comenzar? ¿Que esta pasando?
Nota: He hecho algunas de estas preguntas sobre los hilos específicos, tanto en respuestas como en comentarios, y no obtuve respuestas, así que pensé que debería preguntarle a la comunidad en general, ya que quizás me esté perdiendo algo. Sería bueno ejecutar un trabajo por lotes de métricas y no tener que leer el código de otras personas (o el mío) nunca más, ¡simplemente no creo que sea práctico!
EDITAR: Estoy familiarizado con la mayoría, si no con todas las métricas que se discuten, simplemente no veo el objetivo de ellas en forma aislada o como estándares arbitrarios de calidad.
Aquí hay algunas Métricas de Complejidad de stan4j (http://stan4j.com/).
Una herramienta de análisis de estructura de clase Eclipse.
Me gusta esta herramienta y las métricas. Trato las métricas como estadísticas, indicadores, mensajes de advertencia. En algún momento debido a algunos métodos o algunas clases realmente tiene una lógica complicada que los hace complejos, lo que se debe hacer es vigilarlos, revisarlos para ver si hay una necesidad de refactorizarlos o revisarlos cuidadosamente, debido a que normalmente son propensos a errores También lo uso como herramienta de análisis para aprender el código fuente, debido a que me gusta aprender de complejo a simple. De hecho, incluye algunas otras métricas como Robert C. Martin Metrics, Chidamber y Kemerer Metrics, Count Metrics. Pero me gusta este el mejor.
Métricas de Complejidad
Métrica de complejidad ciclomática
Complejidad ciclomática (CC) La complejidad ciclomática de un método es el número de puntos de decisión en el gráfico de flujo de control del método incrementado en uno. Los puntos de decisión se producen en las sentencias if / for / while, cláusulas case / catch y elementos de código fuente similares, donde el flujo de control no es solo lineal. El número de puntos de decisión (código de bytes) introducidos por una sola instrucción (código fuente) puede variar, dependiendo, por ejemplo, de la complejidad de las expresiones booleanas. Cuanto mayor es el valor de complejidad ciclomática de un método, más casos de prueba se requieren para probar todas las ramas del gráfico de flujo de control del método.
Complejidad ciclomática promedio Valor promedio de la métrica Complejidad ciclomática sobre todos los métodos de una aplicación, biblioteca, árbol de paquete o paquete.
Métricas de grasa La métrica de grasa de un artefacto es el número de aristas en un gráfico de dependencia apropiado del artefacto. El tipo de gráfico de dependencia depende de la variante de métrica y del artefacto elegido:
Fat La métrica Fat de una aplicación, biblioteca o árbol de paquetes es el recuento de bordes de su gráfico de dependencia de subárbol. Este gráfico contiene todos los elementos del artefacto en la jerarquía del árbol de paquetes, por lo que también incluye paquetes de hojas. (Para ver el gráfico apropiado en la Vista de composición, se debe deshabilitar el alternar Paquetes planos del Explorador de estructuras. El alternador Mostrar bibliotecas debe habilitarse si el artefacto elegido es una biblioteca, de lo contrario, debe deshabilitarse).
La métrica Fat de un paquete es el recuento de bordes de su gráfico de dependencia de unidades. Este gráfico contiene todas las clases de nivel superior del paquete.
La métrica Fat de una clase es el recuento de bordes de su gráfico miembro. Este gráfico contiene todos los campos, métodos y clases de miembros de la clase. (Este gráfico y el valor de Grasa solo están disponibles si el análisis del código se realizó con el miembro del nivel de detalle, no de la clase).
Grasa para dependencias de biblioteca (Fat - Libraries) La métrica Fat de dependencias de biblioteca de una aplicación es el recuento de bordes de su gráfico de dependencia de biblioteca. Este gráfico contiene todas las bibliotecas de la aplicación. (Para ver el gráfico apropiado en la Vista de composición, se debe habilitar la opción Mostrar bibliotecas de Structure Explorer).
Grasa para dependencias planas de paquetes (grasa - paquetes) La métrica de las dependencias de paquete de grasa para aplicaciones planas es el recuento de bordes de su gráfico de dependencia de paquete plano. Este gráfico contiene todos los paquetes de la aplicación. (Para ver el gráfico apropiado en la Vista de composición, se debe habilitar la opción Paquetes planos del Explorador de estructuras y se debe desactivar la opción Mostrar bibliotecas).
La métrica Fat For Flat Package Dependencies de una biblioteca es el conteo de bordes de su gráfico de dependencia de paquete plano. Este gráfico contiene todos los paquetes de la biblioteca. (Para ver el gráfico apropiado en la Vista de Composición, los Paquetes Planos del Explorador de Estructura y los Cambios de Bibliotecas de Muestra deben estar habilitados).
Grasa para dependencias de clase de nivel superior (Unidades de grasa) La métrica de una aplicación o biblioteca de Grasa para nivel superior de dependencias de clase es el recuento de bordes de su gráfico de dependencia de unidad. Este gráfico contiene todas las clases de nivel superior de la aplicación o biblioteca. (Para aplicaciones razonables, es demasiado grande para visualizarse y, por lo tanto, no se puede mostrar en la Vista de composición. Los gráficos de dependencia de unidad solo se pueden mostrar para paquetes).
Estoy de acuerdo con usted en que las métricas del código no deben sustituir una revisión del código, pero creo que deberían complementar las revisiones del código. Creo que vuelve al viejo dicho de que "no se puede mejorar lo que no se puede medir". Las métricas de código pueden proporcionarle al equipo de desarrollo "olores de código" cuantificables o patrones que pueden necesitar una mayor investigación. Las métricas que se capturan en la mayoría de las herramientas de análisis estático son típicamente las métricas que se han identificado en el curso de la investigación en la corta historia de nuestro campo para tener un significado significativo.
Hay una métrica de código en la que creo.
Estoy trabajando en un gran sistema. Cuando me llega un nuevo requisito, me puse a codificarlo. Cuando termino y obtengo los errores, lo comprobo en el sistema de control de versiones. Ese sistema hace una diferencia y cuenta todos los cambios que hice.
Cuanto menor sea ese número, mejor.
La mejor métrica que he usado es la puntuación CRAP. http://www.artima.com/weblogs/viewpost.jsp?thread=215899
Básicamente es un algoritmo que compara la complejidad ciclomática ponderada con la cobertura de prueba automatizada. El algoritmo se ve así: CRAP(m) = comp(m)^2 * (1 – cov(m)/100)^3 + comp(m)
donde comp (m) es la complejidad ciclomática del método m, y cov (m) es la cobertura del código de prueba provista por pruebas automáticas.
Los autores del artículo antes mencionado (por favor, léelo ... vale la pena su tiempo) sugieren una calificación máxima de 30 de CRAP que se desglosa de la siguiente manera:
Method’s Cyclomatic Complexity % of coverage required to be
below CRAPpy threshold
------------------------------ --------------------------------
0 – 5 0%
10 42%
15 57%
20 71%
25 80%
30 100%
31+ No amount of testing will keep methods
this complex out of CRAP territory.
Como ve rápidamente, el código de escritura de recompensas métricas no es complejo, junto con una buena cobertura de prueba (si está escribiendo pruebas unitarias, y debería hacerlo, y no está midiendo la cobertura ... bueno, probablemente disfrutaría escupiendo en el viento también). ;-)
Para la mayoría de mis equipos de desarrollo intenté realmente conseguir el puntaje CRAP por debajo de 8, pero si tenían razones válidas para justificar la complejidad añadida que era aceptable siempre que cubrieran la complejidad con suficientes pruebas. (Escribir código complejo siempre es muy difícil de probar ... una especie de beneficio oculto para esta métrica).
A la mayoría de las personas les resultaba difícil escribir código que superaría la calificación CRAP. Pero con el tiempo escribieron mejor código, código que tenía menos problemas y código que era mucho más fácil de depurar. Fuera de cualquier métrica, esta es la que tiene menos preocupaciones y el mayor beneficio.
Las métricas de ellos mismos no son particularmente interesantes. Es lo que haces con ellos lo que cuenta.
Por ejemplo, si estuviera midiendo el número de comentarios por línea de código, ¿qué consideraría un buen valor? ¿Quién sabe? O quizás más importante, todos tienen su propia opinión.
Ahora, si reúne suficiente información para poder correlacionar el número de comentarios por línea de código con el tiempo necesario para resolver un error o el número de errores encontrados que se atribuyen a la codificación, entonces puede comenzar a encontrar un número empíricamente útil. .
No hay diferencia entre usar métricas en el software y usar cualquier otra medida de rendimiento en cualquier otro proceso: primero se mide, luego se analiza y luego se mejora el proceso. Si lo único que estás haciendo es medir, estás perdiendo el tiempo.
editar: en respuesta a los comentarios de Steven A. Lowe, eso es absolutamente correcto. En cualquier análisis de datos uno debe tener cuidado de distinguir entre la relación causal y una mera correlación. Y la selección de las métricas sobre la base de la idoneidad es importante. No tiene sentido tratar de medir el consumo de café y atribuir la calidad del código (aunque estoy seguro de que algunos lo han intentado ;-))
Pero antes de que pueda encontrar la relación (causal o no), debe tener los datos.
La selección de los datos para recopilar se basa en qué proceso desea verificar o mejorar. Por ejemplo, si intenta analizar el éxito de los procedimientos de revisión de código (utilizando su propia definición de "éxito", ya sea que reduzca los errores o errores de codificación reducidos, o tiempos de respuesta más cortos o lo que sea), seleccione métricas que midan la tasa total de errores y la tasa de errores en el código revisado.
Por lo tanto, antes de recopilar los datos, debe saber qué desea hacer con ellos. Si las métricas son los medios, ¿cuál es el final?
Las métricas no son un sustituto de la revisión del código, pero son mucho más baratas. Son un indicador más que nada.
Las métricas pueden ser útiles para determinar la mejora o la degradación en un proyecto, y ciertamente pueden encontrar violaciones de estilo y convención, pero no hay sustituto para hacer revisiones de códigos de pares. Posiblemente no pueda conocer la calidad de su código sin ellos.
Ah ... y esto supone que al menos uno de los participantes en la revisión del código tiene una pista.
Las métricas y las pruebas automatizadas no están pensadas para reemplazar las revisiones completas del código.
Simplemente aceleran las cosas. Con un comprobador automático, es muy fácil ver qué convenciones ha olvidado seguir, que está usando los paquetes y métodos designados, etc. Puede ver lo que puede arreglar sin utilizar el tiempo de otras personas.
A los gerentes también les gustan las métricas porque sienten que están obteniendo una cifra exacta de la productividad (aunque a menudo no es el caso) y deberían ser capaces de hacer malabarismos con las personas mejor.
Las medidas solo son útiles si:
- El equipo los desarrolló
- El equipo estuvo de acuerdo con ellos
- Se están utilizando para identificar un área específica
En general, cualquier métrica que no encaje en eso sufrirá que el equipo lo optimice. ¿Quieres medir líneas de código? Por Dios, ¡mira cuántos pueden escribir! ¿Quiere medir la cobertura del código? ¡Por Dios, mire cómo cubro ese código!
Creo que las métricas pueden ser útiles para identificar tendencias y, de hecho, he visto algunas útiles, como trazar cuando se rompe la compilación, cambio de código (número de líneas de código que cambian a lo largo del proyecto) y otras cosas. Pero si el equipo no los presenta, o no están de acuerdo o no los entienden, es probable que estés en un mundo de dolor.
Las personas se sienten atraídas por la idea de formas mecanicistas para comprender y describir el código. Si es cierto, piense en las ramificaciones de la eficiencia y la productividad.
Acepto que una métrica para "bondad del código" es tan sensata como una métrica para "buena prosa". Sin embargo, eso no significa que las métricas sean inútiles, sino que quizás solo se utilicen indebidamente.
Por ejemplo, los valores extremos para algunas métricas señalan el camino a posibles problemas. Un método de 1000 líneas de largo probablemente no se puede mantener. Código con cobertura de código de prueba de unidad cero probablemente tiene más errores que código similar con muchas pruebas. Un gran salto en el código agregado a un proyecto justo antes del lanzamiento que no es una biblioteca de terceros probablemente sea motivo de atención adicional.
Creo que si usamos las métricas como una sugerencia, una bandera roja, quizás puedan ser útiles. El problema es cuando las personas comienzan a medir la productividad en SLOC o la calidad en porcentaje de líneas con pruebas.
Las respuestas en este hilo son algo extrañas, ya que hablan de:
- "el equipo", como "el único y único beneficiario" de las métricas mencionadas;
- "las métricas", como si significaran algo en sí mismas.
1 / Metrics no es para una población, sino para tres :
- desarrolladores: se preocupan por las métricas instantáneas del código estático con respecto al análisis estático de su código (complejidad ciclomática, calidad de comentarios, número de líneas, ...)
- Líderes de proyectos: les preocupan las métricas diarias del código en vivo provenientes de pruebas unitarias, cobertura de códigos, pruebas de integración continua
- patrocinadores de negocios (siempre son olvidados, pero son los interesados, el que paga por el desarrollo): se preocupan por las métricas semanales del código global relacionadas con el diseño arquitectónico, la seguridad, las dependencias, ...
Todas esas métricas pueden ser observadas y analizadas por las tres poblaciones, por supuesto, pero cada tipo está diseñado para ser mejor utilizado por cada grupo específico.
2 / Las métricas, por sí mismas, representan una instantánea del código, y eso significa ... ¡nada!
Es la combinación de esas métricas y las combinaciones de esos diferentes niveles de análisis que pueden indicar un código "bueno" o "malo", pero lo más importante es que la tendencia de esas métricas es significativa.
Esa es la repetición de esas métricas que darán el valor agregado real, ya que ayudarán a los gerentes de negocios / líderes de proyectos / desarrolladores a priorizar entre las diferentes correcciones de código posibles.
En otras palabras, su pregunta sobre la "fascinación de las métricas" podría referirse a la diferencia entre:
- código "bello" (aunque eso siempre está en el ojo del codificador-espectador)
- código "bueno" (que funciona, y puede probar que funciona)
Entonces, por ejemplo, una función con una complejidad ciclomática de 9 podría definirse como "bella", a diferencia de una larga y complicada función de complejidad ciclomática de 42.
Pero si:
- la última función tiene una complejidad constante , combinada con una cobertura de código del 95%,
- mientras que el primero tiene una complejidad creciente , combinado con una cobertura de ... 0%,
uno podría argumentar:
- el último representa un código " bueno " (funciona, es estable y, si necesita cambiar, se puede verificar si funciona después de las modificaciones),
- el primero es un código " malo " (aún necesita agregar algunos casos y condiciones para cubrir todo lo que tiene que hacer, y no hay una manera fácil de hacer alguna prueba de regresión)
Entonces, para resumir:
una sola métrica que por sí misma siempre indica [...]
: no mucho, excepto que el código puede ser más "bello", lo que en sí mismo no significa mucho ...
¿Hay algún conocimiento mágico que obtener de las métricas de código que he pasado por alto?
Solo la combinación y la tendencia de las métricas proporcionan la verdadera "visión mágica" que busca.
Mi opinión altamente subjetiva es que las métricas del código expresan la fascinación institucional irresistible de ser capaz de cuantificar algo intrínsecamente incuantificable.
Tiene sentido, en cierto modo, al menos psicológicamente: ¿cómo puedes tomar decisiones sobre algo que no puedes evaluar o comprender? En última instancia, por supuesto, no puede evaluar la calidad a menos que esté bien informado sobre el tema (y sea al menos tan bueno como lo que está tratando de evaluar) o pregúntele a alguien que esté bien informado, lo cual, por supuesto, solo le devuelve el problema Un paso.
En ese sentido, tal vez una analogía razonable sería evaluar a los estudiantes que ingresan a la universidad por puntajes SAT, es injusto y pierde todo tipo de sutileza, pero si necesita cuantificar, debe hacer algo.
No digo que creo que es una buena medida, solo que puedo ver la irresistabilidad institucional de la misma. Y, como señaló, probablemente haya algunas medidas razonables (muchos métodos de línea de más de 500, alta complejidad, probablemente malos). Sin embargo, nunca he estado en un lugar que haya aceptado esto.
No creo que los pequeños cambios en las métricas sean significativos: una función con complejidad 20 no es necesariamente más limpia que una función con complejidad 30. Pero vale la pena ejecutar métricas para buscar grandes diferencias.
Una vez estuve inspeccionando un par de docenas de proyectos y uno de los proyectos tuvo un valor máximo de complejidad de alrededor de 6.000, mientras que cualquier otro proyecto tuvo un valor de alrededor de 100 o menos. Eso me golpeó en la cabeza como un bate de béisbol. Obviamente, algo inusual, y probablemente malo, estaba ocurriendo con ese proyecto.
Para mí, la medida más importante que identifica el código incorrecto es la complejidad ciclomática. Casi todos los métodos en mis proyectos están por debajo de CC 10 y los errores se encuentran invariablemente en métodos heredados con CC por encima de 30. El CC alto por lo general indica:
- código escrito con prisa (es decir, no hubo tiempo para encontrar una solución elegante y no porque el problema requiriera una solución compleja)
- código no probado (nadie escribe pruebas para tales bestias)
- código que fue parcheado y reparado en numerosas ocasiones (es decir, plagado de ifs y comentarios pendientes)
- un objetivo principal para la refactorización
Somos programadores Nos gustan los números.
Además, ¿qué vas a hacer, NO describir el tamaño de la base de código porque "las líneas de métricas de código son irrelevantes"?
Definitivamente hay una diferencia entre una base de código de 150 líneas y una de 150 millones, para tomar un ejemplo tonto. Y no es un número difícil de obtener.
Tenía un proyecto que hice hace un mes como un trabajo de una persona, medido por la complejidad ciclomática. Esa fue mi primera exposición a este tipo de métricas.
El primer informe que recibí fue impactante. Casi todas mis funciones no pasaron la prueba, incluso las (muy) muy simples. Pasé por alto la complejidad al mover la subtarea lógica a subrutinas, incluso si solo se han llamado una vez.
Para la otra mitad de las rutinas, mi orgullo como programador comenzó y traté de reescribirlos de una manera que hagan lo mismo, simplemente más simple y más fácil de leer. Eso funcionó y pude obtener la mayor parte del umbral de complejidad yclomatic clientes.
Al final, casi siempre pude encontrar una mejor solución y un código mucho más limpio. El rendimiento no sufrió por esto (créanme, estoy paranoico en esto y verifico el desensamblaje de la salida del compilador con bastante frecuencia).
Creo que las métricas son buenas si las usas como motivo / motivación para mejorar tu código. Sin embargo, es importante saber cuándo detenerse y solicitar una multa de infracción.
Las métricas son guías y ayudan, no fines en sí mismo.
Una buena revisión del código no sustituye a una buena herramienta de análisis estático, que por supuesto no sustituye a un buen conjunto de pruebas unitarias, ahora las pruebas unitarias no son buenas sin un conjunto de pruebas de aceptación ...
Las métricas de código son otra herramienta para poner en su caja de herramientas, no son una solución por sí mismas, son solo una herramienta para usar según corresponda (¡con todas las demás herramientas en su caja, por supuesto!).
Una parte de la respuesta es que algunas métricas de código pueden dar una respuesta inicial muy rápida a la pregunta: ¿Cómo es este código?
Incluso las ''líneas de código'' pueden darle una idea del tamaño de la base de código que está mirando.
Como se menciona en otra respuesta, la tendencia de las métricas le brinda la mayor información.