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).
Continuemos...
Al comparar con booleanos, realizamos lanzamientos mágicos y obtenemos resultados inesperados.
TL; DR: No compares con la verdad. O eres verdadero o falso o no debes comparar
Muchos lenguajes emiten valores a dominios de cruce booleano.
#!/bin/bash if [ false ]; then echo "True" else echo "False" fi # this evaluates to true since # "false" is a non-empty string if [ false ] = true; then echo "True" else echo "False" fi # this also evaluates to true
#!/bin/bash if false ; then echo "True" else echo "False" fi # this evaluates to false
Los linters pueden buscar comparaciones y advertencias explícitas.
Es una práctica común en la industria utilizar muchos valores no booleanos como valores booleanos. Deberíamos ser muy estrictos al usar booleanos.
Code Smell 69 - Big Bang (Castings ridículos de JavaScript)
Foto de Michael Held en Unsplash
Si no funciona, no importa lo rápido que no funciona.
-Mich Ravera
Los IF y Els anidados son muy difíciles de leer y probar
TL; DR: Evite los IF anidados. Aún mejor: evite TODOS los IF
En el código de procedimiento, es muy común ver ifs anidados complejos. Esta solución está más relacionada con las secuencias de comandos que con la programación orientada a objetos.
if (actualIndex < totalItems) { if (product[actualIndex].Name.Contains("arrow")) { do { if (product[actualIndex].price == null) { // handle no price } else { if (!(product[actualIndex].priceIsCurrent())) { // add price } else { if (!hasDiscount) { // handle discount } else { // etc } } } actualIndex++; } while (actualIndex < totalCounf && totalPrice < wallet.money); } else actualIndex++; } return actualIndex; }
foreach (products as currentProduct) addPriceIfDefined(currentProduct) addPriceIfDefined() { //Several extracts }
Dado que muchos linters pueden analizar árboles, podemos verificar el tiempo de compilación para ver los niveles de anidamiento.
Siguiendo el consejo del tío Bob , deberíamos dejar el código más limpio de lo que lo encontramos.
Refactorizar este problema es fácil.
Code Smell 78 - Infierno de devolución de llamada
Code Smell 03 - Las funciones son demasiado largas
Code Smell 36 - Declaraciones Switch/case/elseif/else/if
El propósito de la ingeniería de software es controlar la complejidad, no crearla.
-Pamela Zavé
Llamar a nuestros propios métodos de acceso puede parecer una buena idea de encapsulación. Pero no lo es.
TL; DR: no use setters y getters, incluso para uso privado
El uso de doble encapsulación era un procedimiento estándar en los años 90.
Queríamos ocultar los detalles de implementación incluso para uso privado.
Esto ocultaba otro olor cuando demasiadas funciones se basan en la estructura de datos y la implementación accidental.
Por ejemplo, podemos cambiar la representación interna de un objeto y confiar en su protocolo externo.
El costo/beneficio no vale la pena.
contract MessageContract { string message = "Let's trade"; function getMessage() public constant returns(string) { return message; } function setMessage(string newMessage) public { message = newMessage; } function sendMessage() public constant { this.send(this.getMessage()); // We can access property but make a self call instead } }
contract MessageContract { string message = "Let's trade"; function sendMessage() public constant { this.send(message); } }
Podemos inferir getters y setters y comprobar si se invocan desde el mismo objeto.
La doble encapsulación era una idea de moda para proteger la implementación accidental, pero exponía más que protegía.
Code Smell 37 - Atributos protegidos
Foto de Ray Hennessy en Unsplash
Encapsular el concepto que varía.
-Erich Gamma
Afirmar contra booleanos hace que el seguimiento de errores sea más difícil.
TL; DR: no afirme que es verdadero a menos que esté verificando un valor booleano
Al afirmar un valor booleano, nuestros motores de prueba no pueden ayudarnos mucho.
Simplemente nos dicen que algo falló.
El seguimiento de errores se vuelve más difícil.
<? final class RangeUnitTest extends TestCase { function testValidOffset() { $range = new Range(1, 1); $offset = $range->offset(); $this->assertTrue(10 == $offset); // No functional essential description :( // Accidental description provided by tests is very bad } } // When failing Unit framework will show us // // 1 Test, 1 failed // Failing asserting true matches expected false :( // () <-- no business description :( // // <Click to see difference> - Two booleans // (and a diff comparator will show us two booleans)
<? final class RangeUnitTest extends TestCase { function testValidOffset() { $range = new Range(1, 1); $offset = $range->offset(); $this->assertEquals(10, $offset, 'All pages must have 10 as offset'); // Expected value should always be first argument // We add a functional essential description // to complement accidental description provided by tests } } // When failing Unit framework will show us // // 1 Test, 1 failed // Failing asserting 0 matches expected 10 // All pages must have 10 as offset <-- business description // // <Click to see difference> // (and a diff comparator will help us and it will be a great help // for complex objects like objects or jsons)
Algunos linters nos advierten si estamos verificando contra booleanos después de establecer esta condición.
Necesitamos cambiarlo a un control más específico.
Intenta reescribir tus aserciones booleanas y arreglarás las fallas mucho más rápido.
Code Smell 101 - Comparación con booleanos
Code Smell 07 - Variables booleanas
Foto de Joël de Vriend en Unsplash
Finalmente he aprendido lo que significa 'compatible con versiones superiores'. Significa que podemos mantener todos nuestros viejos errores.
-Dennie van Tassel
Use nombres profesionales y significativos
TL;DR: No seas informal ni ofensivo
Nuestra profesión tiene un lado creativo.
A veces nos aburrimos y tratamos de ser graciosos.
function erradicateAndMurderAllCustomers(); // unprofessional and offensive
function deleteAllCustomers(); // more declarative and professional
Podemos tener una lista de palabras prohibidas.
También podemos comprobarlos en revisiones de código.
Los nombres son contextuales, por lo que sería una tarea difícil para un linter automático.
Las convenciones de nombres deben ser genéricas y no deben incluir jerga cultural.
Sea profesional en la forma en que nombra las cosas en su código.
No intente ser un comediante dándole a una variable un nombre tonto.
Debe escribir el código de producción para que los futuros desarrolladores de software (incluso usted) puedan entenderlo fácilmente.
Code Smell 38 - Nombres abstractos
Foto de Stewart Munro en Unsplash
Esta mentalidad de 'usuarios son idiotas y están confundidos por la funcionalidad' de Gnome es una enfermedad. Si cree que sus usuarios son idiotas, solo los idiotas lo usarán.
-Linus Torvalds
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!