Los olores a código son un clásico. Huele porque es probable que haya muchos casos en los que podría editarse o mejorarse. La mayoría de estos olores son solo indicios de algo que podría estar mal. No se requieren fijos per se... (Sin embargo, deberías investigarlo). Olores de código anteriores Parte I Parte II Parte III Parte IV Parte V Parte VI Parte VII Parte VIII Parte IX Parte X Parte XI Parte XII Parte XIII Parte XIV Parte XV Parte XVI Parte XVII Parte XVIII Parte XIX Parte XX Parte XXI Continuemos... Código Olor 106 - Código dependiente de la producción No agregue IF para verificar el entorno de producción. TL; DR: evite agregar condicionales relacionados con la producción Problemas Violación del principio de fallo rápido Falta de capacidad de prueba Soluciones Si es completamente necesario, modele entornos y pruébelos . TODOS Contexto A veces, necesitamos crear diferentes comportamientos en el desarrollo y la producción. Por ejemplo, la fortaleza de las contraseñas. En este caso, necesitamos configurar el entorno con la estrategia de fuerza y probar la estrategia y no el entorno en sí. Código de muestra Equivocado def send_welcome_email(email_address, environment): if ENVIRONMENT_NAME == "production": print(f"Sending welcome email to {email_address} from Bob Builder <bob@builder.com>") else: print("Emails are sent only on production") send_welcome_email("john@doe.com", "development") # Emails are sent only on production send_welcome_email("john@doe.com", "production") # Sending welcome email to john@doe.com from Bob Builder <bob@builder.com> Derecha class ProductionEnvironment: FROM_EMAIL = "Bob Builder <bob@builder.com>" class DevelopmentEnvironment: FROM_EMAIL = "Bob Builder Development <bob@builder.com>" # We can unit test environments # and even implement different sending mechanisms def send_welcome_email(email_address, environment): print(f"Sending welcome email to {email_address} from {environment.FROM_EMAIL}") # We can delegate into a fake sender (and possible logger) # and unit test it send_welcome_email("john@doe.com", DevelopmentEnvironment()) # Sending welcome email to john@doe.com from Bob Builder Development <bob@builder.com> send_welcome_email("john@doe.com", ProductionEnvironment()) # Sending welcome email to john@doe.com from Bob Builder <bob@builder.com> Detección manuales [x] Este es un olor de diseño. Necesitamos crear configuraciones de desarrollo/producción vacías y delegarlas con objetos polimórficos personalizables. Etiquetas Acoplamiento Conclusión Evite agregar condicionales no comprobables. Crear configuraciones delegando reglas de negocio. Utilice abstracciones, protocolos e interfaces, evite jerarquías estrictas. Relaciones Code Smell 56 - Preprocesadores Más información Cómo evitar los molestos ifs Créditos Foto de en Birmingham Museums Trust Unsplash Este tuit fue inspirado por @Jan Giacomelli Gorjeo La complejidad es un signo de inmadurez técnica. La simplicidad de uso es el verdadero signo de un producto bien diseñado, ya sea un cajero automático o un misil Patriot. daniel t ling Grandes citas de ingeniería de software Code Smell 107 - Reutilización de variables La reutilización de variables hace que los alcances y los límites sean más difíciles de seguir TL; DR: no lea y escriba la misma variable para diferentes propósitos Problemas Legibilidad Problemas ocultos Soluciones No reutilices variables para aislar ámbitos Método de extracción Contexto Al programar un script, es común reutilizar variables. Esto genera confusión y dificulta la depuración. Debemos reducir el alcance tanto como sea posible. Código de muestra Equivocado // print line total double total = item.getPrice() * item.getQuantity(); System.out.println("Line total: " + total ); // print amount total total = order.getTotal() - order.getDiscount(); System.out.println( "Amount due: " + total ); // variable is reused Derecha function printLineTotal() { double total = item.getPrice() * item.getQuantity(); System.out.println("Line total: " + total ); } function printAmountTotal() { double total = order.getTotal() - order.getDiscount(); System.out.println( "Amount due: " + total ); } Detección Automático [ ] Linters puede usar el árbol de análisis para encontrar definiciones y usos de variables. Etiquetas Legibilidad Conclusión Evite reutilizar nombres de variables. Use nombres más específicos y diferentes. Relaciones Code Smell 03 - Las funciones son demasiado largas Más información Refactorización 002 - Método de extracción Créditos Foto de en Sigmund Unsplash Simplicidad antes que generalidad, uso antes que reutilización. kevlin henney Grandes citas de ingeniería de software Code Smell 108 - Afirmaciones flotantes Afirmar que dos números flotantes son iguales es un problema muy difícil TL;DR: No compares flotadores Problemas Resultados de prueba incorrectos Pruebas frágiles Violación del principio de fallo rápido Soluciones Evite los flotadores a menos que tenga preocupaciones REALES sobre el rendimiento Usar números de precisión arbitraria Si necesita comparar flotadores, compare con la tolerancia. Contexto Comparar números flotantes es un viejo problema de informática. La solución habitual es utilizar comparaciones de umbral. Recomendamos evitar los flotantes y tratar de usar números de precisión infinitos. Código de muestra Equivocado Assert.assertEquals(0.0012f, 0.0012f); // Deprecated Assert.assertTrue(0.0012f == 0.0012f); // Not JUnit - Smell Derecha Assert.assertEquals(0.0012f, 0.0014f, 0.0002); // true Assert.assertEquals(0.0012f, 0.0014f, 0.0001); // false // last parameter is the delta threshold Assert.assertEquals(12 / 10000, 12 / 10000); // true Assert.assertEquals(12 / 10000, 14 / 10000); // false Detección Automático [ ] Podemos agregar una verificación con en nuestros marcos de prueba para evitar la verificación de flotadores. assertEquals() Etiquetas Prueba de olores Conclusión Siempre debemos evitar comparar flotadores. Relaciones Code Smell 71 - Flotadores mágicos disfrazados de decimales Más información Fallar rapido Créditos Foto de en Mika Baumeister Unsplash Dios hizo los números naturales; todo lo demás es obra del hombre. Leopoldo Kronecker Grandes citas de ingeniería de software Olfato de código 109 - Propiedades automáticas ¿Qué pasa si combinas 4 olores de código? TL;DR: Evitar Getters, Evitar Setters, Evitar Metaprogramación. Piensa en el Comportamiento. Problemas Violación de ocultación de información Mutabilidad Violación del principio Fail Fast Código duplicado al establecer propiedades Soluciones Eliminar setters y getters automáticos Contexto Setters y getters son una mala práctica de la industria. Muchos IDE favorecen este olor a código. Algunos lenguajes brindan soporte explícito para construir modelos anémicos y DTO. Código de muestra Equivocado class Person { public string name { get; set; } } Derecha class Person { private string name public Person(string personName) { name = personName; //imutable //no getters, no setters } //... more protocol, probably accessing private variable name } Detección Automático [ ] Esta es una característica del lenguaje. Debemos evitar lenguajes inmaduros o prohibir sus peores prácticas. Etiquetas Encapsulación Conclusión Necesitamos pensar cuidadosamente antes de exponer nuestras propiedades. El primer paso es dejar de pensar en propiedades y centrarse únicamente en el comportamiento. Relaciones Code Smell 28 - Setters Code Smell 68 - Captadores Code Smell 70 - Generadores de modelos anémicos Código Olfato 40 - DTO Code Smell 01 - Modelos anémicos Más información escuelas W3 Pereza I - Metaprogramación Pereza II - Asistentes de código Refactorización 001 - Eliminar setters El poder maligno de los mutantes Fallar rapido Créditos Foto de en Kony Unsplash No hay nada más difícil que trabajar con un plazo ajustado y aun así tomarse el tiempo para limpiar sobre la marcha. Kent Beck Grandes citas de ingeniería de software Code Smell 110 - Interruptores con valores predeterminados Predeterminado significa 'todo lo que aún no sabemos'. No podemos prever el futuro. TL; DR: no agregue una cláusula predeterminada a sus casos. Cámbialo por una excepción. Sea explícito. Problemas Acoplamiento Violación del principio Fail Fast Violación del principio abierto cerrado Soluciones Reemplazar si y casos con polimorfismo Cambiar el código predeterminado a una excepción Contexto Cuando usamos casos, generalmente agregamos un caso predeterminado para que no falle. Fallar siempre es mejor que tomar decisiones sin pruebas. Dado que la también son un olor, podemos evitarlos. caja y los interruptores Código de muestra Equivocado switch (value) { case value1: // if value1 matches the following will be executed.. doSomething(); break; case value2: // if value2 matches the following will be executed.. doSomethingElse(); break; default: // if value does not presently match the above values // or future values // the following will be executed doSomethingSpecial(); break; } Derecha switch (value) { case value1: // if value1 matches the following will be executed.. doSomething(); break; case value2: // if value2 matches the following will be executed.. doSomethingElse(); break; case value3: case value4: // We currently know these options exist doSomethingSpecial(); break; default: // if value does not match the above values we need to take a decision throw new Exception('Unexpected case ' + value + ' we need to consider it'); break; } Detección Semiautomático [x] Podemos decirle a nuestros linters que nos adviertan sobre los usos predeterminados a menos que haya una excepción. Etiquetas Fallar rapido Conclusión Escribir código robusto no significa que debamos tomar decisiones sin evidencia. Relaciones Code Smell 36 - Declaraciones Switch/case/elseif/else/if Más información Fallar rapido Créditos Foto de en Joshua Woroniecki Unsplash El costo de agregar una función no es solo el tiempo que toma codificarla. El costo también incluye la adición de un obstáculo para la futura expansión. El truco consiste en elegir las características que no luchan entre sí. Juan Carmack Grandes citas de ingeniería de software Y eso es todo por ahora… ¡El próximo artículo explicará 5 olores de código más!