0

Clean Code #02 (2nd Edition): Firmas Pobres

Hasta ahora vimos nombres pobres y las mejores prácticas para corregirlo. Ahora es el momento firmas pobres en los métodos. Veamos.

Firmas pobres en métodos

Básicamente estamos presencia de una firma pobre cuando tenemos métodos que no son significativos y que no dicen realmente cual es su objetivo, por ejemplo:

Brown GetProduct(int airplane);

Como vemos, este método dice GetProduct, pero recibe como parámetro un airplane y devuelve un objeto Brown, no es un objeto Product…. Realmente, no se entiende el objetivo de este método y es bastante confuso.

Veamos otro método:

void Parse(int command);

Tenemos un método que recibe un tipo de dato int y no nos devuelve nada. ¿Que tiene de malo este método? Típicamente los métodos llamados Parse reciben un string y devuelve un objeto. En este caso, al existir métodos con un significado, nos conviene respetarlo. Lo usaremos  de la siguiente forma:

int Parse(string command);

Veamos más ejemplos:

public class PoorMethodSignatures{
    public void Run(){
        var productService = new ProductService();

        var product = productService.GetProduct("productName", "description", true);
        var anotherProduct = productService.GetProduct("productName", null, false);
    }
}

Vemos que tenemos un método que se llama Run, dentro, se crea un objeto ProductService. Luego, se invoca al método GetProduct que recibe 3 parámetros, “productName”, “description” y un flag true. En la siguiente línea, vemos que se invoca nuevamente el mismo método pero, el segundo parámetro es null y el tercero es false.

Estamos obligados a ver la implementación del método porque no nos dice que hace. Veamos la implementación:

public class ProductService
{
    private ProductDbContext _dbContext = new ProductDbContext();

    public Product GetProduct(string productName, string description, bool onlyByName){

        if(onlyByName){

            var product = _dbContext.Products
                                .SingleOrDefault(p => p.ProductName == productName 
                                    && p.Description == description);
                            
            if(product != null)
                product.UpdateCreated = DateTime.Now;
            
            return product;



        }else{

            var product = _dbContext.Products
                                .SingleOrDefault(p => p.ProductName == productName); 
            return product;

        }
    }
}

base de datos por nombre del producto y la descripción, si lo encuentra, cambiará el valor de la propiedad UpdateCreated y devolverá en objeto producto. 

En caso de que parámetro onlyByName sea false, lo buscara por el parámetro productName y nos devolverá el producto.

Algo que debemos tener en cuenta, casi siempre, parámetros del tipo boolean en las firmas de los métodos son Code Smells. Nos alerta de que el método, seguramente, hace diferentes cosas dependiendo de este parámetro. Si tenemos muchos parámetros boolean en el método, esto hará más complejo nuestro código teniendo diferentes combinaciones de estos parámetro para resolver situaciones.

Veamos un mejor camino. Primero separaremos esta el codigo donde se busca por los 3 parámetros. Crearemos el método GetProductByNameByDescription() para no tener más el parámetro booleano , volverlo mucho más expresivo y que denote una intensión.

public Product GetProductByNameByDescription(string name, string description){

        var product = _dbContext.Products
                                        .SingleOrDefault(p => p.ProductName == name 
                                            && p.Description == description);
                            
        if(product != null)
            product.UpdateCreated = DateTime.Now;
        
        return product;

    }

Todavía nos queda resolver la siguiente línea de código :

var anotherProduct = productService.GetProduct("productname", null, false);

Ahora podemos eliminar los parámetros de descripción y el booleano. Estos no son utilizados para el método que nos queda. Queda de esta manera:

public Product GetProduct(string productName){
        
        var product = _dbContext.Products
                                .SingleOrDefault(p => p.ProductName == productName); 
        return product;
    }

Para concluir, nuestros métodos quedan más limpios, más pequeños y más mantenibles. Cualquier persona que lee nuestro código sabrá qué intenciones tiene y no necesitaran ver la implementación para saber qué hacen.

public class PoorMethodSignatures{
    public void Run(){

        var productService = new ProductService();

        var product = productService.GetProductByNameByDescription("productname", "description");
        var anotherProduct = productService.GetProduct("productname);
    }
}

Conclusión

Siempre debemos tener en cuenta y validarlos más de una vez los siguientes puntos:

  • Chequear que devuelvan un solo tipo.
  • Chequear el nombre del método.
  • Chequear los parámetros.

En próximos post veremos más trucos para mejorar y limpiar nuestro código.

Fernando Sonego

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *