No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Code Smells

6/14
Recursos

Aportes 16

Preguntas 4

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

Code smell

Sensaci贸n de que algo va mal con el c贸digo al percibir algunos indicadores de posibles errores. A veces estos errores pueden ser indicaciones de mala calidad del c贸digo, pero, esto que a simple vista se ve como 鈥渕al, feo, o raro鈥, en muchas ocasiones puede ser causante de problemas m谩s profundos de funcionamiento en el c贸digo del programa o aplicaci贸n, lo que conllevar铆a una refactorizaci贸n o incluso una reescritura del c贸digo para lograr un c贸digo limpio y su mejor funcionamiento.

Algunos ejemplos de code smell:

  • Variables, m茅todos o clases con nombres poco descriptivos.
  • M茅todos y clases de much铆simas l铆neas que se vuelven dif铆ciles o tediosos de entender. Esto es un indicativo de que las funcionalidades que contienen se pueden separar en peque帽as partes y as铆 poder dividir las responsabilidades en clases y metodos mas peque帽os y entendibles.
  • M茅todos o funciones que reciben demasiados par谩metros, lo que indica que hay mucha l贸gica dentro de esa funci贸n.
  • Utilizaci贸n de 鈥淣煤meros m谩gicos鈥 o 鈥渜uemados鈥, esto se refiere a n煤meros fijos que utilizamos dentro de la l贸gica de nuestro c贸digo y que puede causar que a primera vista no se entienda cu谩l es su funci贸n dentro del mismo y se requiera de m谩s tiempo para comprender lo que hacen.

Tipos de code smell:

Para considerar los diferentes code smells, hay que distinguir entre los niveles de abstracci贸n del c贸digo:

  1. Code smells de forma general
  2. Code smells a nivel de funci贸n
  3. Code smells a nivel de clase
  4. Code smells a nivel de la aplicaci贸n

Para complementar la informaci贸n sobre los tipos de code smell les recomiendo la lectura de este art铆culo: Code smell explicado de forma sencilla

Code Smell, "Demasiados parametros"
Creo que se puede resolver pasando una clase o dos como parametro algo como esto:

var numerosSumados = new ValoresNumericos
{
  primerValor = 20, 
  segundoValor = 20
}

var opcionesCalculoSuma = new opcionesDeFormato
{
   cantidadDecimales  = 2, 
   tituloSalidaTerminal = "Total de suma 2 parametros",
   tipoDeOperacion = OperacionAritmetica.Suma

}


public double Calculation( VarloresNumericos numerosCalculo, opcionesDeFormato opcionesFormatoCalculo)
.
.
.

creo que hay otras formas mas elegantes de escribir ese codigo, lo importante es que me parece que las funciones con menos de 4 parametros son mas faciles de leer.

驴Que opinan?

Lo hice de esta forma, ya que usar if en un programa grande es mas optimo usar switch y ademas si la comparacion es de solo igual a, lo mejor es usar switch
<code>

TaskList = new List<string>();
            int menuselected = 0;
            do
            {
                menuselected = ShowMainMenu();
               switch (menuselected)
               {
                case 1:
                ShowMenuAdd();
                break;

                case 2:
                ShowMenuRemoveTask();
                break;

                case 3:
                ShowMenuTaskList();
                break;

               }
            } while (menuselected != 4);

Para evaluar code smells, us茅 mucho Sonarqube, como herramienta de an谩lisis est谩tico. Las reglas para detectar code smells (incluso otras reglas que veremos mas adelante) me ayudaron a entender y mejorar mucho la programaci贸n, vale la pena revisarlas e ir entendi茅ndolas.
https://rules.sonarsource.com/csharp/type/Code Smell

***Code smell*** es un t茅rmino utilizado en el desarrollo de software para describir signos o indicios de que puede haber problemas en el c贸digo fuente. Estos indicios no son necesariamente errores de programaci贸n o bugs, pero sugieren que el c贸digo podr铆a beneficiarse de mejoras, refactoring o una revisi贸n m谩s detallada. 1. **Nombres de variables errados:** Nombres poco claros o gen茅ricos pueden hacer que el c贸digo sea dif铆cil de entender. 2. **Clases o m茅todos largos:** Clases o m茅todos que son excesivamente largos y realizan m煤ltiples tareas pueden ser dif铆ciles de entender y mantener. 3. **Demasiados par谩metros:** Clases o m贸dulos con una gran cantidad de atributos y m茅todos pueden indicar una falta de cohesi贸n y responsabilidades excesivas. 4. **N煤meros m谩gicos:** Se refiere a valores literales o constantes que se utilizan directamente en el c贸digo en lugar de ser asignados a variables con nombres descriptivos. Algunos otros son: 1. **C贸digo duplicado:** Repetici贸n innecesaria de fragmentos de c贸digo que podr铆an ser reutilizados o abstra铆dos en funciones o clases. 2. **Anidaci贸n excesiva de bucles o condicionales:** Demasiados niveles de anidaci贸n pueden complicar el flujo del programa. 3. **Dependencias circulares:** Cuando las clases tienen dependencias circulares, puede ser un signo de un acoplamiento excesivo y una mala arquitectura. 4. **Comentarios excesivos o in煤tiles:** La necesidad de comentarios excesivos a menudo indica que el c贸digo no es lo suficientemente claro por s铆 mismo. 5. **C贸digo muerto:** C贸digo que no se utiliza y est谩 presente en el repositorio, lo que puede confundir a los desarrolladores.

En la parte donde nosotros vemos el menu, encontr茅 otra forma de poner enums dentro de la selecci贸n del menuSelected sin que se genere error alguno, aqu铆 dejo el link de stackoverflow para el que quiera verlo ;D saludos!
.
https://es.stackoverflow.com/questions/87221/el-operador-no-se-puede-aplicar-a-operandos-del-tipo-int

 do
            {
                menuSelected = ShowMainMenu();
                if (menuSelected == (int)Menu.Add)
                {
                    ShowMenuAdd();
                }
                else if (menuSelected == (int)Menu.Remove)
                {
                    ShowMenuRemove();
                }
                else if (menuSelected == (int)Menu.List)
                {
                    ShowMenuTaskList();
                }
            } while (menuSelected != (int)Menu.Exit);
        }

Recomiendo esta extension. SonarLint
Detects and helps fix issues in your C# code locally in your IDE

Esta clase me hizo recordar a cuando en mi trabajo pasado hab铆a un archivo con m谩s de 20k lineas de c贸digo

Los "code smells" (o "malos olores del c贸digo") en C# se refieren a ciertos patrones o estructuras en el c贸digo que indican posibles problemas de dise帽o o implementaci贸n. Estos "smells" a menudo se帽alan 谩reas donde el c贸digo podr铆a mejorarse para tener una mejor legibilidad, mantenibilidad y eficiencia. Aqu铆 tienes algunos "code smells" comunes en C#: 1\. \*\*M茅todos largos\*\*: Los m茅todos excesivamente largos pueden ser dif铆ciles de entender, probar y mantener. Div铆delos en m茅todos m谩s peque帽os y enfocados. 2\. \*\*Clases grandes\*\*: Similar a los m茅todos largos, las clases que son demasiado grandes a menudo indican que est谩n haciendo demasiado. Considera dividirlas en clases m谩s peque帽as y cohesivas. 3\. \*\*Obsesi贸n por lo primitivo\*\*: El uso excesivo de tipos primitivos (como cadenas o enteros) en lugar de crear tipos espec铆ficos del dominio puede conducir a un c贸digo menos expresivo y menos mantenible. Crea tipos personalizados para representar conceptos del dominio. 4\. \*\*C贸digo repetido\*\*: El c贸digo duplicado debe evitarse ya que conlleva sobrecarga de mantenimiento y posibles errores. Refactoriza el c贸digo duplicado en m茅todos o clases reutilizables. 5\. \*\*Listas de par谩metros largas\*\*: Los m茅todos con un gran n煤mero de par谩metros pueden ser dif铆ciles de usar y entender. Considera usar objetos de par谩metros o dividir el m茅todo en otros m谩s peque帽os y enfocados. 6\. \*\*Intimidad inapropiada\*\*: Las clases que est谩n demasiado acopladas violan el principio de encapsulaci贸n y pueden ser dif铆ciles de mantener y probar. Reduce las dependencias entre clases usando interfaces, inyecci贸n de dependencias u otros patrones de dise帽o. 7\. \*\*Nomenclatura inconsistente\*\*: Las convenciones de nomenclatura inconsistentes hacen que el c贸digo sea m谩s dif铆cil de entender. Usa una nomenclatura clara y consistente en todo tu c贸digo. 8\. \*\*Envidia de caracter铆sticas\*\*: Cuando un m茅todo accede a los datos de otra clase m谩s que a los suyos propios, puede indicar que el m茅todo pertenece a la otra clase. Considera mover el m茅todo a la clase que posee los datos. 9\. \*\*Grandes instrucciones SWITCH o IF-ELSE\*\*: Las instrucciones switch y las cadenas if-else largas pueden ser dif铆ciles de mantener y extender. Considera usar polimorfismo, el patr贸n de estrategia o tablas de b煤squeda para manejar estos casos de manera m谩s elegante. 10\. \*\*Grupos de datos\*\*: Cuando grupos de campos de datos se pasan frecuentemente juntos, puede indicar que deber铆an estar juntos en su propia clase. Crea una nueva clase para encapsular campos de datos relacionados. 11\. \*\*Clases Dios\*\*: Clases que saben o hacen demasiado, violando el Principio de Responsabilidad 脷nica. Refactoriza estas clases en otras m谩s peque帽as y enfocadas. 12\. \*\*Complejidad ciclom谩tica\*\*: Alta complejidad ciclom谩tica en los m茅todos puede indicar una l贸gica demasiado compleja que es dif铆cil de entender y probar. Refactoriza estos m茅todos en piezas m谩s peque帽as y manejables. Al identificar y abordar estos "code smells", puedes mejorar la calidad, legibilidad y mantenibilidad de tu base de c贸digo en C#.
Code Smells en C#: ------------------ **驴Qu茅 son?** Los Code Smells son indicadores de posibles problemas en tu c贸digo que pueden afectar su mantenimiento, legibilidad y probabilidad de errores. **Ejemplos comunes en C#:** * **Clases grandes:** Dificultad de comprensi贸n y mantenimiento. * **M茅todos largos:** Complejidad y dificultad para refactorizar. * **Duplicaci贸n de c贸digo:** Mantenimiento ineficiente y errores repetitivos. * **Nombres inconsistentes:** Dificultad para comprender el prop贸sito del c贸digo. * **Comentarios excesivos:** Posible indicador de c贸digo complejo o mal escrito. * **Falta de pruebas:** Dificultad para detectar y corregir errores. **驴Por qu茅 son importantes?** Detectar y corregir los Code Smells a tiempo puede ayudarte a: * **Mejorar la legibilidad y mantenibilidad del c贸digo.** * **Reducir la probabilidad de errores.** * **Facilitar la refactorizaci贸n y el mantenimiento del c贸digo.** **驴C贸mo prevenirlos?** * **Seguir buenas pr谩cticas de codificaci贸n.** * **Utilizar herramientas de an谩lisis de c贸digo.** * **Realizar revisiones de c贸digo con regularidad.**
Hay unos libros recomendados para aprender estas buenas pr谩cticas "The clean code" y de "Clean Coder" escritos por Bob Martin, conocido tambi茅n Como Uncle Bob, y tienen acumulados muchos a帽os de desarrollo y buenos pr谩cticas

Vivi toda mi vida enganado pensando que utilizar los numero magicos estaba bien

De la clase anterior (Y)

using System;
using System.Collections.Generic;

namespace ToDo
{
    internal class Program
    {
        private static List<string> taskList;

        //public static List<string> TL { get; set; } --> Malas practicas
        public static List<string> GetTaskList()
        {
            return taskList;
        }

        //public static List<string> TL { get; set; } --> Malas practicas
        public static void SetTaskList(List<string> value)
        {
            taskList = value;
        }

        static void Main(string[] args)
        {
            SetTaskList(new List<string>());
            int menuSelected = 0;
            do
            {
                menuSelected = ShowMainMenu();
                if (menuSelected == 1)
                {
                    ShowMenuAdd();
                }
                else if (menuSelected == 2)
                {
                    ShowMenuRemove();
                    //Mala practica ShowMenuDos: debe decir siempre la funci贸n que cumple!
                }
                else if (menuSelected == 3)
                {
                    ShowMenuTaskList();
                    //Mala practica ShowMenuTres: debe decir siempre la funci贸n que cumple!

                }
            } while (menuSelected != 4);
        }
        /// <summary>
        /// Show the main menu 
        /// </summary>
        /// <returns>Returns option indicated by user</returns>
        public static int ShowMainMenu()
        {
            Console.WriteLine("----------------------------------------");
            Console.WriteLine("Ingrese la opci贸n a realizar: ");
            Console.WriteLine("1. Nueva tarea");
            Console.WriteLine("2. Remover tarea");
            Console.WriteLine("3. Tareas pendientes");
            Console.WriteLine("4. Salir");

            // Read line
            string taskIndex = Console.ReadLine();
            return Convert.ToInt32(taskIndex);
        }

        public static void ShowMenuRemove()
        {
            try
            {
                Console.WriteLine("Ingrese el n煤mero de la tarea a remover: ");
                // Show current taks
                for (int i = 0; i < GetTaskList().Count; i++)
                {
                    Console.WriteLine((i + 1) + ". " + GetTaskList()[i]);
                }
                Console.WriteLine("----------------------------------------");

                string taskIndex = Console.ReadLine();
                // Remove one position
                int indexToRemove = Convert.ToInt32(taskIndex) - 1;
                if (indexToRemove > -1)
                {
                    if (GetTaskList().Count > 0)
                    {
                        string taskToRemove = GetTaskList()[indexToRemove];
                        GetTaskList().RemoveAt(indexToRemove);
                        Console.WriteLine("Tarea " + taskToRemove + " eliminada");
                    }
                }
            }
            catch (Exception)
            {
            }
        }

        public static void ShowMenuAdd()
        {
            try
            {
                Console.WriteLine("Ingrese el nombre de la tarea: ");
                string task = Console.ReadLine();
                GetTaskList().Add(task);
                Console.WriteLine("Tarea registrada");
            }
            catch (Exception)
            {
            }
        }

        public static void ShowMenuTaskList()
        {
            if (GetTaskList() == null || GetTaskList().Count == 0)
            {
                Console.WriteLine("No hay tareas por realizar");
            }
            else
            {
                Console.WriteLine("----------------------------------------");
                for (int i = 0; i < GetTaskList().Count; i++)
                {
                    Console.WriteLine((i + 1) + ". " + GetTaskList()[i]);
                }
                Console.WriteLine("----------------------------------------");
            }
        }
    }
}

C贸digo actualizado:

using System;
using System.Collections.Generic;

namespace ToDo
{
    internal class Program
    {
        public static List<string> TaskList { get; set; }

        static void Main(string[] args)
        {
            TaskList = new List<string>();
            int menuOption = 0;
            do
            {
                menuOption = ShowMainMenu();
                if ((Menu)menuOption == Menu.Add)
                {
                    AddTask();
                }
                else if ((Menu)menuOption == Menu.Remove)
                {
                    RemoveTask();
                }
                else if ((Menu)menuOption == Menu.List)
                {
                    ShowTaskList();
                }
            } while ((Menu)menuOption != Menu.Exit);
        }
        /// <summary>
        /// Show the main menu 
        /// </summary>
        /// <returns>Returns menuOption indicated by user</returns>
        public static int ShowMainMenu()
        {
            Console.WriteLine("----------------------------------------");
            Console.WriteLine("Ingrese la opci贸n a realizar: ");
            Console.WriteLine("1. Nueva tarea");
            Console.WriteLine("2. Remover tarea");
            Console.WriteLine("3. Tareas pendientes");
            Console.WriteLine("4. Salir");

            // Read taskIndex
            string taskIndex = Console.ReadLine();
            return Convert.ToInt32(taskIndex);
        }

        public static void RemoveTask()
        {
            try
            {
                Console.WriteLine("Ingrese el n煤mero de la tarea a remover: ");
                // Show current taks
                for (int i = 0; i < TaskList.Count; i++)
                {
                    Console.WriteLine((i + 1) + ". " + TaskList[i]);
                }
                Console.WriteLine("----------------------------------------");

                string taskIndex = Console.ReadLine();
                // Remove one position
                int indexToRemove = Convert.ToInt32(taskIndex) - 1;
                if (indexToRemove > -1)
                {
                    if (TaskList.Count > 0)
                    {
                        string taskToRemove = TaskList[indexToRemove];
                        TaskList.RemoveAt(indexToRemove);
                        Console.WriteLine("Tarea " + taskToRemove + " eliminada");
                    }
                }
            }
            catch (Exception)
            {
            }
        }

        public static void AddTask()
        {
            try
            {
                Console.WriteLine("Ingrese el nombre de la tarea: ");
                string taskToAdd = Console.ReadLine();
                TaskList.Add(taskToAdd);
                Console.WriteLine("Tarea registrada");
            }
            catch (Exception)
            {
            }
        }

        public static void ShowTaskList()
        {
            if (TaskList == null || TaskList.Count == 0)
            {
                Console.WriteLine("No hay tareas por realizar");
            } 
            else
            {
                Console.WriteLine("----------------------------------------");
                for (int i = 0; i < TaskList.Count; i++)
                {
                    Console.WriteLine((i + 1) + ". " + TaskList[i]);
                }
                Console.WriteLine("----------------------------------------");
            }
        }
    }

    public enum Menu
    {
        Add = 1,
        Remove = 2,
        List = 3,
        Exit = 4
    }
}