Dos personas mirando código de software en una pantalla

¿Qué es la calidad del código?

Calidad del código y cómo mejorarla

La calidad del código se refiere a la robustez del código más allá de si simplemente se ejecuta y cumple su función deseada. El código de alta calidad se distingue por su eficiencia, facilidad de mantenimiento, legibilidad y reutilización, mientras que el código de baja calidad es frágil, difícil de analizar y propenso a acumular deuda técnica con el tiempo.

Los altos estándares de programación son para el proceso de desarrollo de software lo que una buena mise en place y “trabajar de forma ordenada” son para el funcionamiento de una cocina profesional. Las prácticas que elevan la calidad del código pueden traducirse en una mejor funcionalidad a corto plazo, pero sus beneficios más importantes son menos problemas, un progreso más rápido y menores costos de mantenimiento a largo plazo.

Los beneficios a largo plazo de un código de mayor calidad a veces pueden ser difíciles de comunicar para los programadores a la gerencia menos versada en las minucias del ciclo de vida del desarrollo de software. Equilibrar los beneficios holísticos del código óptimo con las presiones inmediatas de las prioridades empresariales a menudo implica complejos sacrificios. Dicho esto, un estudio de 2022 de 39 bases de código de producción patentadas afirmó, entre otros hallazgos,1 que: 

  • La deuda técnica derivada de un código escrito de manera apresurada supone un desperdicio de hasta el 42 % del tiempo de los desarrolladores.

  • El código de baja calidad genera 15 veces más defectos que el código de alta calidad.

  • Resolver problemas en código de baja calidad lleva (en promedio) un 124 % más de tiempo que resolver problemas en código de alta calidad.

Un código de mayor calidad facilita y agiliza la comprensión, la refactorización, la depuración y la incorporación de nuevas características a un código fuente. Un código claro, coherente y bien escrito facilita una coordinación más fluida entre los equipos de desarrollo y reduce la complejidad y las complicaciones derivadas de los cambios en el código. No solo garantiza una alta calidad del software, sino también una excelente experiencia para los desarrolladores y los usuarios.

El hecho de que un fragmento de código compile y ejecute con éxito su propósito en tiempo de ejecución no es suficiente para determinar su calidad general. Escribir código no es como completar un crucigrama, en el que existe una única forma de completar correctamente una tarea: a menudo hay innumerables soluciones a un problema de programación dado. Por lo tanto, la funcionalidad es el único criterio para determinar si un código es aceptable. El valor de un código de alta calidad se manifiesta en sus efectos secundarios sobre el contexto que lo rodea.

¿Qué define a un código de alta calidad?

El código de alta calidad es un concepto relativamente abstracto. La calidad general de un fragmento de código se define tanto por cómo se hace y cómo interactúa con la base de código más amplia en la que existe como por cualquier conjunto específico de métricas de calidad de código discretas y objetivas (aunque existen muchas de esas métricas).

Las características comunes del código de alta calidad incluyen:

  • Legibilidad: la legibilidad del código es esencial para el mantenimiento, la depuración y la coordinación entre equipos y tiempo. ¿Puede otro miembro del equipo entender fácilmente el código? ¿Podrá otro programador, dentro de unos años, interpretar correctamente el código sin que usted esté presente para aportar el contexto necesario?

  • Mantenibilidad: la complejidad del código suele estar inversamente correlacionada con su mantenibilidad. ¿Su código se puede probar fácilmente, lo que permite a su equipo evaluarlo eficientemente en busca de vulnerabilidades de seguridad y oportunidades de optimización? ¿Es lo suficientemente robusto como para agregar nuevas características sin afectar la funcionalidad principal, o es demasiado frágil para ajustarlo sin requerir una refactorización importante? Dar prioridad a un código fácil de mantener puede suponer un esfuerzo inicial adicional, pero a la larga ahorra mucho tiempo y energía.

  • Eficiencia: el código bien escrito puede reducir la latencia y el consumo de recursos de un sistema. Por ejemplo, las estructuras de datos cuidadosamente elegidas pueden minimizar el número de operaciones de CPU necesarias para una función determinada. Las estrategias bien pensadas de almacenamiento en caché de datos reducen las costosas operaciones de entrada/salida (E/S) al eliminar las consultas redundantes a la base de datos y las solicitudes de red, mientras que la liberación rápida de la memoria no utilizada evita la sobrecarga innecesaria de RAM.

  • Confiabilidad: un menor número de defectos y estructuras resistentes a los cambios en el código se traducen en menos fallas y tiempos de inactividad. La confiabilidad es esencial para la experiencia y la confianza del usuario, así como para el estado de los sistemas críticos de los que depende una empresa.

Como creadores de código en Harvard Data Science Review en 2023, los investigadores de Calvin University, Amherst College y Columbia propusieron un marco prescriptivo para un buen código: “Las cuatro C”.2

  • Corrección: el código hace lo que se supone que debe hacer. Los autores enfatizaron dos corolarios de esta obvia inclusión: “Primero, la corrección es una métrica necesaria, pero insuficiente para un buen código. En segundo lugar, los otros objetivos apoyan y promueven la corrección”.

  • Claridad: cualquiera que lea y escriba el código puede saber qué se pretende que haga e intuitivamente realizar modificaciones según sea necesario.

  • Contención: evita la dispersión, la redundancia y las dependencias innecesarias. La contención adecuada implica, entre otras cosas, “usar funciones para contener código reutilizable, y mantener el código utilizado en archivos o proyectos en un módulo o paquete”.

  • Coherencia: una base de código debe mantener la coherencia interna del estilo, las convenciones de nomenclatura, los comentarios, la sangría y otras prácticas.

A medida que el desarrollo de software moderno continúa siendo impulsado cada vez más por asistentes de programación con agentes como IBM Bob, la contención y la congruencia son particularmente útiles para maximizar la eficacia y precisión de las herramientas automatizadas. Dicho esto, la capacidad de las plataformas de próxima generación como IBM Bob para identificar oportunidades de refactorización de IA en tiempo real puede reducir el esfuerzo necesario para aplicar ese nivel de disciplina estilística.

Mejores prácticas para escribir código de alta calidad

Aunque cada lenguaje de programación y cada caso de uso tiene sus propios matices y consideraciones específicas, existen algunas mejores prácticas universales para escribir código de calidad en cualquier situación.

Un enfoque para conceptualizar la alta calidad del código es simplemente pensar en él como un código que evita tantos marcadores de código incorrecto como sea posible, que se explorarán más adelante en este artículo.

Para un enfoque más normativo, el documento Harvard Data Science Review (HDSR) mencionado anteriormente describe una serie de pautas para garantizar la calidad del código. Aunque estas pautas están supuestamente optimizadas para las necesidades de los científicos de datos, la mayoría son aplicables en cualquier disciplina de programación.

Elegir buenos nombres

Las convenciones de nomenclatura sólidas son esenciales para la legibilidad y coherencia del código. Los autores sugieren las siguientes prácticas:

  • La longitud de los nombres debe ser proporcional a su ámbito. Cuanto mayor sea la distancia (ya sea en términos de tiempo, líneas de código o estructura organizacional) entre la definición inicial de un término y su uso, más esencial es que su nombre comunique claramente su función.

  • Mantenga un compendio de abreviaturas. Los nombres de variables cortos o incluso de un solo carácter pueden ayudar a ordenar el código, pero también pueden volverse inescrutables para las personas menos familiarizadas con el proyecto. Mantener una especie de “glosario” mitiga esa compensación.

  • Use las mayúsculas de forma coherente. También es prudente evitar instancias en las que dos nombres se diferencien únicamente por su uso de mayúsculas.

  • Evite nombres anodinos. Aumentan significativamente la dificultad de la interpretación del código.

  • Elige convenciones de nomenclatura de archivos que permitan ordenarlos de forma natural. Por ejemplo, puede adoptar la norma ISO 8601 para la fecha y la hora, o rellenar los números con ceros para garantizar que todos tengan la misma cantidad de dígitos.

Las convenciones de nomenclatura claras y coherentes también pueden simplificar el proceso de dar instrucciones a los asistentes de programación de IA y aumentar la precisión de su resultado. Por ejemplo, en lugar de dar una instrucción a un agente para que inspeccione ciertos tipos de variables o explorar todos los archivos de un determinado rango de fechas, lo que podría requerir que su agente de IA deduzca probabilísticamente del contexto qué variables o archivos cumplen con los criterios, puede dar explícitamente una instrucción a un agente para que explore todos los archivos que comiencen con un número específico o todas las variables con un nombre específico.

Seguir una guía de estilo de manera constante

Además de codificar convenciones de nomenclatura sólidas, una guía de estilo completa debería estandarizar idealmente los elementos de formato, incluido el uso de espacios en blanco y sangrías, comentarios y tipos de datos, así como “dialectos de programación”. En GitHub se puede encontrar una amplia variedad de guías de estilo probadas para diversos lenguajes de programación, como las incluidas en esta lista curada.

Una guía de estilo también es una referencia invaluable para un asistente de programación de IA, que sirve como contexto para tareas específicas o incluso como parte de la instrucción de su agente de IA.

Seleccionar un kit de herramientas coherente y mínimo (pero adecuado)

Aprovechar los kits de herramientas y las bibliotecas es una ventaja natural para la reutilización y la eficiencia del código, ya que ayuda a estandarizar los flujos de trabajo y los resultados en diferentes equipos y acelerar ampliamente la creación de código. Son particularmente útiles cuando el código debe mediar interacciones con sistemas complejos de terceros o manejar problemas repetitivos y “resueltos”.

Pero la dependencia excesiva de los kits de herramientas puede agregar una sobrecarga innecesaria e introducir dependencias externas, lo que reduce la robustez y la capacidad de mantenimiento del código. Además, tienden a ocultar la lógica subyacente del código, lo que reduce su legibilidad. Los autores de HDSR expresan el equilibrio ideal en términos simples: “Queremos que nuestro kit de herramientas sea lo más simple posible, pero no más sencillo”.

Don't repeat yourself (DRY)

Si se encuentra copiando, pegando y modificando con frecuencia los mismos bloques de código, es posible que le resulte mejor una función que encapsule el código repetido en un solo lugar. Los parámetros de esa función pueden reflejar los elementos que cambian de una instancia a otra. Esto limpia el código y simplifica el mantenimiento, ya que le permite ajustar todas las instancias de esa función en un solo paso y lugar (en vez de ajustar individualmente cada duplicado de un bloque de código).

Emplear controles de coherencia

Los controles de coherencia son validaciones automáticas que verifican si los datos potenciales o estados del sistema se ajustan a reglas y convenciones lógicas predefinidas, ayudando a evitar y tener en cuenta conflictos y contradicciones imprevistos en el código. Estas pruebas automatizadas suelen ser un componente estándar y crítico de los pipelines de CI/CD (integración continua/despliegue continuo).

Este es un ejemplo por excelencia de la importancia de la capacidad de prueba del código. Es difícil o imposible diseñar pruebas unitarias que validen exhaustivamente cada función si su código es demasiado complejo o contiene demasiadas dependencias estrechamente acopladas.

Aplicar el control de versiones

Los sistemas de control de versiones ayudan a fomentar la coherencia, el control de calidad, la coordinación y los procesos de revisión de código entre los equipos. Al utilizar marcos de codificación impulsados por IA, especialmente aquellos que podrían ajustar de forma autónoma su base de código, asegúrese de tener un medio para revertir fácilmente cualquier cambio no deseado o adverso. IBM Bob, por ejemplo, crea automáticamente versiones de los archivos del espacio de trabajo en forma de puntos de control para revertir fácilmente los cambios en el código cuando sea necesario.

¿Qué define al código incorrecto?

En términos generales, el código incorrecto es difícil de leer y mantener, frágil a los cambios y nuevas características, ineficiente y poco confiable. A menudo presenta dependencias innecesarias, en las que los distintos módulos están entrelazados entre sí y cualquier cambio en uno requiere un trabajo adicional para evitar que el otro deje de funcionar. Carece de la documentación adecuada y está mal organizado, desprovisto de una estructura lógica y coherente, una situación que a menudo se denomina “código espagueti”.

El código incorrecto a menudo es producto no (solo) de habilidades de programación deficientes, sino de incentivos y estructura organizacional deficientes: priorizar de forma excesiva los lanzamientos de características a expensas de la calidad del código generalmente produce un tiempo de comercialización más rápido, pero mayores complicaciones futuras y deuda técnica.

Es importante recordar que el código incorrecto a menudo funciona, al menos temporalmente. La deuda técnica no se acumularía si no fuera así, porque indudablemente habría que solucionar un código roto. El libro fundamental de Martin Fowler y Kent Beck , Refactoring: Improving the Design of Existing Code, publicado por primera vez en 1999 (y actualizado muchas veces desde entonces), empleó el término code smells para describir el código defectuoso. Por lo general, no son errores y no impiden inherentemente que un programa funcione, pero indican debilidades de diseño y problemas de calidad del código que podrían ralentizar el desarrollo o causar errores en el futuro.

La lista de Fowler y Beck de code smells a tener en cuenta incluye ejemplos como:

  • Función larga (método largo): un método que contiene demasiadas líneas de código.

  • Clase grande: una clase que intenta hacer demasiado y contiene demasiadas variables, sin cohesión.

  • Obsesión por los tipos primitivos: utilizar tipos de datos primitivos en lugar de pequeños objetos especializados.

  • Nombres enigmáticos: funciones o variables con nombres poco claros que ocultan su verdadera finalidad.

  • Agrupaciones de datos: grupos de variables que suelen aparecer juntas en todas partes.

  • Elementos perezosos: clases o funciones que hacen muy poco para existir.

  • Lista larga de parámetros: funciones que requieren demasiados argumentos para funcionar correctamente.

  • Cirugía de escopeta: un cambio requiere modificar muchos módulos dispersos simultáneamente (que es lo opuesto a la clase grande).

  • Código duplicado: estructuras de código idénticas o muy similares en varios lugares.

Aquí se puede encontrar una lista completa de code smells, con explicaciones, ejemplos y citas. Su presencia suele ser una señal de que se necesita refactorización. Una comprensión profunda de estas cuestiones y de las complicaciones que se derivan de ellas, por parte de toda la organización, resulta útil para establecer una visión común de los estándares de calidad entre los equipos de desarrollo.

AI Academy

El auge de la IA generativa para las empresas

Aprenda sobre el auge histórico de la IA generativa y lo que significa para las empresas.

Medición de la calidad del código

Medir la calidad del código siempre debe implicar una evaluación tanto cualitativa como cuantitativa. Si bien las métricas objetivas, como la complejidad ciclomática, pueden ser útiles, también pueden ser engañosas sin el contexto adecuado.

Por ejemplo, su equipo podría escribir una suite de pruebas automatizada y su código podría lograr una cobertura de código del 100 % en una batería de pruebas unitarias. Pero si la suite carece de algunas de las afirmaciones significativas necesarias para validar genuinamente que su código funciona completamente según sea necesario, la falsa confianza de esa cobertura de prueba podría hacer más daño que bien.

Del mismo modo, una estructura de revisión sólida debería incluir tanto la revisión manual del código como la revisión del código mediante IA. Una herramienta moderna de programación con agentes como IBM Bob puede realizar un extenso análisis de código estático y refactorización en tiempo real, pero se beneficia enormemente de reglas personalizadas y modos personalizados que transmiten las necesidades e intenciones específicas del desarrollador. Los seres humanos no lo saben todo y la IA no es infalible, pero complementar ambos es la forma más segura de garantizar que se han analizado todos los posibles problemas teniendo en cuenta el contexto adecuado.

Recuerde siempre que la calidad del código depende del contexto. Imagine que un programador de su equipo ha escrito un algoritmo o bloque de código elocuente, eficiente y perfectamente articulado que logra perfectamente su función prevista. Si el problema podría haberse resuelto de manera efectiva utilizando una función de biblioteca estándar e integrada con la que todos ya están familiarizados, ese código elocuente es en realidad un problema de calidad porque agrega complejidad innecesaria y sobrecarga mental.

Autor

Dave Bergmann

Senior Staff Writer, AI Models

IBM Think

Soluciones relacionadas
IBM Bob

Acelere la entrega de software con Bob, su socio de IA para un desarrollo seguro y consciente de la intención.

Explore IBM Bob
Soluciones de programación de IA

Optimice el desarrollo de software con herramientas confiables impulsadas por IA que minimizan el tiempo dedicado a escribir código, depurar, refactorizar código o completar código, y deje más espacio para la innovación.

Explore soluciones de programación de IA
Consultoría y servicios de IA

Reinvente los flujos de trabajo y las operaciones críticos añadiendo IA para maximizar las experiencias, la toma de decisiones en tiempo real y el valor empresarial.

Explore los servicios de consultoría de IA
Dé el siguiente paso

Aproveche la IA generativa y la automatización avanzada para crear código empresarial listo de forma más rápida. Bob crea modelos para aumentar el conjunto de habilidades de los desarrolladores, simplificando y automatizando sus esfuerzos de desarrollo y modernización.

  1. Descubra IBM Bob
  2. Explore soluciones de programación de IA
Notas de pie de página

1. “Code red: the business impact of code quality – a quantitative study of 39 proprietary production codebases,” Proceedings of the International Conference on Technical Debt (consultado a través de la Association for Computing Machinery Digital Libtary). 16 de agosto de 2022

2. “Fostering Better Coding Practices for Data Scientists,” Harvard Data Science Review. 27 de julio de 2023