Los bad code smells, code smells o simplemente smells es código que huele a problemas. El hecho de haber code smells no quiere decir que el programa no funcione o cumpla con los requisitos funcionales y tampoco señala la presencia de errores en el sistema, pero sí que hay debilidades en el diseño del software y puede dar problemas de escalabilidad o para su mantenimiento.
¿Qué es el code smell?
Un code smell es una forma de programar que permite a los programadores experimentados intuir que el código no está limpio.
Por lo tanto, un code smell indica un problema sistémico. Puede que el código lo escribiese un programador sin los conocimientos suficientes o que diferentes programadores hayan ido turnándose. En este último caso, las diferencias en el nivel de competencia, el conocimiento de la base de código y la familiaridad con las directrices y las normas de cada profesional conducen a una mala calidad del código. Es decir, el código puede empezar a “oler mal”.
La soolución: Refactorizarlo o Reescribirlo.
¿Cuáles son los diferentes tipos de code smells?
El código es un medio que existe a diferentes niveles de abstracción. Por ejemplo, en las aplicaciones el código define una multitud de piezas individuales: variables, funciones, clases y módulos. Para considerar los diferentes code smells, hay que distinguir entre los niveles de abstracción:
Code smells de forma general
La mayoría de las veces no son errores graves, sino patrones que tienen un impacto negativo. Sobre todo en el caso de los programadores principiantes, el código ofrece el resultado deseado, pero no es incomprensible.
Mala nomenclatura en la estructura del código
Utilizar la nomenclatura correcta de las construcciones de código, como las variables y las funciones, es todo un arte. Los nombres deben tener sentido y ser coherente en toda la aplicación, utilizar variables de una sola letra: x, i, n, etc. es un code smell.
Los nombres deben ser naturales como el lenguaje.
Falta de uniformidad en el estilo del código
Un código limpio parece haber sido escrito por una sola persona, es coherente y simillar en todos lados. Si falta dicha uniformidad, se trata de un code smell.
La falta de homogeneidad en la forma de nombrar variables sugiere que varias personas escribieron partes del código sin ponerse de acuerdo.
Variables sin definir
Algunos lenguajes permiten declarar variables sin darles un valor inicial. La variable existe desde su creación, pero no está definida, lo que puede dar lugar a pequeños errores.
Valores codificados en el código
Este error lo suelen cometer los programadores inexpertos: para comparar una variable con un valor concreto, introducen el valor directamente (se denomina “valores codificados”). Los valores codificados son problemáticos si aparecen en varios lugares del mismo programa, pues las copias individuales del valor tienden a mutar de forma independiente con el tiempo.
Es mejor definir una constante para el valor. Esto crea una Single Source of Truth (SSOT): todo el código que necesita el valor accede a la misma constante definida en un único lugar.
Números mágicos en código
Un número mágico es un caso especial de valores codificados. Imagina que el código funciona con valores limitados a 24 bits. 24 bits corresponden a 16 777 216 valores posibles o a los números de 0 a 16 777 215.
Desgraciadamente, falta añadir un comentario, por lo que no está claro, a posteriori, cómo se ha llegado a ese valor. Resultado: ha surgido un número mágico. El desconocimiento del origen del valor aumenta el riesgo de que se modifique por error.
Estos errores pueden evitarse al incluir la definición del valor como una expresión al asignar la constante.
Sentencias de control profundamente anidadas
En la mayoría de los lenguajes, es posible cambiar las construcciones de código a cualquier profundidad. Por desgracia, esto también aumenta su complejidad, lo que hace más difícil entenderlo cuando se lee. Un code smell especialmente común es el de las sentencias de control profundamente anidadas, como los bucles y las ramas.
Hay varias maneras de resolver una anidación como, por ejemplo, utilizando el operador booleano AND para colocar ambas condiciones dentro de una misma sentencia if
El code smell a nivel funcional
En la mayoría de los lenguajes, las funciones son la unidad básica de ejecución del código. Hay piezas de código más pequeñas, como las variables y las expresiones, pero estas son independientes. Escribir funciones sencillas y claras requiere cierta experiencia. Mostramos algunos de los code smells más comunes a nivel de función.
Falta de atención a las excepciones
Las funciones reciben argumentos a modo de valores de entrada. En muchos casos, solo son válidos ciertos valores o rangos de valores. Es responsabilidad de los programadores comprobar la autenticidad de los valores introducidos y gestionar las excepciones en consecuencia.
Acceso a la variable desde un nivel superior de la función
Las áreas de validez son una característica fundamental de la mayoría de los lenguajes de programación. Determinan qué nombres se definen en qué lugares del código. Los ámbitos subordinados heredan de los superiores. Si se accede a una variable definida externamente dentro de una función, se convierte en un code smell. Esto se debe a que el valor puede haber cambiado entre que se definió la variable y cuando se llama a la función.
Lo ideal es que solo se acceda a los valores que aparecen como sentencias dentro de las funciones. Se utilizan parámetros por defecto para evitar tener que pasar el mismo valor repetidas veces:
Nota
El acceso a una variable desde fuera del ámbito de una función que la encierra crea un “Closure”. No se trata de code smell. Los cierres son un concepto importante en la programación de JavaScript.
Code smells a nivel de clase
La programación orientada a objetos (POO) puede ayudar a aumentar la reutilización del código y reducir su complejidad. Desgraciadamente, hay muchas ocasiones en las que se pueden cometer errores en el diseño de las clases que luego desencadenan en un code smell.
Uno de los code smells más comunes a nivel de clase es el “God Object” o su correspondiente “Clase Dios”. Un god object combina todo tipo de funcionalidades que normalmente no van juntas y, por tanto, violan el principio de “separación de intereses”.
Los code smells se encuentran a menudo en relación con la jerarquía de la herencia. A veces el código se distribuye innecesariamente a través de múltiples niveles de herencia. A menudo se comete el error de utilizar la herencia en lugar de la composición como enfoque principal para componer objetos.
El uso involuntario de “Data Classes” también se considera un code smell. Son clases que no implementan su propio funcionamiento. Si no se definen métodos aparte de los getters y setters genéricos, se debe considerar el uso de una estructura de datos más simple como un Dict o un Struct.
Code smells a nivel de aplicación
Es la pesadilla de todo programador: que te designen a trabajar en una aplicación existente y con un primer vistazo al código veas que toda la aplicación se encuentra en un único archivo enorme, donde no queda claro cómo se relacionan los componentes individuales del código. Como un plato de fideos, todo se desmadra en el “Spaghetti Code”.
Faltan todas las abstracciones, no hay subdivisión entre las clases y, en el mejor de los casos, solo hay unas pocas funciones. En cambio, hay todo tipo de duplicaciones de código que dan lugar a pequeños bugs. Además, se utilizan mucho las variables globales.
El uso de variables globales es un code smell especialmente invasivo, pues estas pueden ser potencialmente modificadas desde cualquier parte del código, lo que abre la puerta a errores difíciles de corregir. Para limpiar el código, te ves en la obligación de buscar errores por todas sus secciones.
¿Cómo se puede evitar un code smell?
Si utilizas las buenas prácticas que da el Clean Code vas a evitar los code smells. Es preferible mantener el código limpio en todo momento.
Evita el «si funciona no lo toques», a la larga, el código empieza a no oler bien y la deuda técnica se acumula.
Si un código fuente que ya existe contiene code smells, no es posible empezar desde cero. Por lo que es necesario limpiar el código. Lo mejor es proceder de forma gradual y delimitar primero las áreas del código fuente que pueden limpiarse con relativa facilidad. Separa los componentes que funcionan o que son mejorables de los “rincones oscuros” que es mejor no tocar.
Separar las áreas de código “menos apestosas” de las “más apestosas” reduce la complejidad del código. Esto facilita la comprobación del código y la adopción de medidas de debugging. También pueden ser de gran ayuda las herramientas automatizadas de code Review que detectan los code smells y ofrecen sugerencias o ayuda para limpiarlos.
Los enfoques de refactorización son eficaces para eliminar los code smells. La funcionalidad se encapsula en funciones o se dividen las funciones existentes. Eliminar las secciones de código que no se utilizan y mejorar la nomenclatura del código hace que el código fuente sea más sencillo. Las reglas de oro “Don’t Repeat Yourself” (DRY) y “You ain’t gonna need it” (YAGNI) sirven de guía.
Deja una respuesta