Profile Image

Carlos Vigueras

Senior Backend Developer

Object Calisthenics – Un nivel de indentación por método

Dicen que lo prometido es deuda… y ya que prometí que iría desarrollando cada una de las 9 reglas de Object Calisthenics, no podía dejar de hacerlo.

En este post me voy a centrar en la primera regla Un nivel de indentación por método.

Como todo hijo de vecino, siendo programadores, alguna vez en la vida nos hemos encontrado que tenemos que desarrollar un evolutivo, o una nueva Feature sobre un proyecto ya existente, y quien dice alguna vez en la vida, dice casi siempre, pues pocas veces nos enfrentamos a proyectos desde cero, ya nos gustaría ya… empezar un nuevo proyecto, acabarlo y comenzar otro, pero la realidad es muy diferente. Sin irme por las ramas, como comento, cuando hemos de realizar un desarrollo, o añadir una nueva Feature en un proyecto podemos encontrarnos con clases muy grandes y métodos larguísimos que hacen muchas cosas, lo que diríamos que son métodos que carecen de cohesión. Bien, pues cuando nos enfrentamos a una situación de esta índole, tenemos dos opciones:

  • Acordarnos del programador que en su momento desarrolló “esa cosa que está ahí”.

  • Refactorizar el método que tenemos delante para poder hacernos la vida un poco mas fácil

Sin lugar a dudas, deberíamos siempre elegir la segunda opción, aunque en principio elijamos la primera para desahogarnos un poco.

Y aquí es donde debemos tener en cuenta, que en la medida de lo posible, hemos de refactorizar el método ante el que nos enfrentamos, y para ello lo que Jeff Bay propone en esta primera regla es lo siguiente:

  • Usar métodos de no mas de 5 líneas.

  • Que un método haga una sola cosa, o sea, que cada método tenga una única responsabilidad, un conjunto de instrucciones por método o una estructura de control.

Y como se suele decir… “Una imagen vale mas que mil palabras”


public enum TipoOperacion
{
    Default,
    Suma,
    Resta,
    Multiplicacion,
    Division
}
public class Operacion
{
    public int Operar(int number1, int number2, TipoOperacion tipoOperacion)
    {
        if (tipoOperacion == TipoOperacion.Suma)
        {
            return number1 + number2;
        }
        else if (tipoOperacion == TipoOperacion.Resta)
        {
            return number1 - number2;
        }
        else if (tipoOperacion == TipoOperacion.Multiplicacion)
        {
            return number1 * number2;
        }
        else if (tipoOperacion == TipoOperacion.Division)
        {
            return number1 / number2;
        }
        return 0;
    }
}

var operacion = new Operacion();
var resultadoSuma = operacion.Operar(1, 1, TipoOperacion.Suma);
var resultadoResta = operacion.Operar(1, 1, TipoOperacion.Resta);
var resultadoMultiplicacion = operacion.Operar(2, 2, TipoOperacion.Multiplicacion);
var resultadoDivision = operacion.Operar(10, 5, TipoOperacion.Division);
Lenguaje del código: PHP (php)

Si os fijáis en el código, el método Operar(), no solo está haciendo mas de una cosa, si no que tiene varias estructuras de control anidadas, por lo que trabajas con niveles de abstracción diferentes y esto no es del todo correcto.

¿ Podríamos decir que el método es funcional y que cumple su objetivo?

Si, realmente es funcional y cumple su objetivo, pero no es para nada reutilizable en cuanto a nivel de abstracción, me explico, el método Operar() hace 4 cosas diferentes, suma, resta, multiplica y divide, y cada vez que queramos hacer cualquiera de estas operaciones, vamos a tener que llamar al método Operar(), y pasándole el enumerado TipoOperación hará una operación u otra. No podemos llamar directamente a un método Resta(), por ejemplo, hemos de pasar primero por todas las estructuras de control, hacer todas las comprobaciones necesarias y ejecutar la operación resultante para obtener el valor solicitado.

Así que vamos a refactorizar el código y vemos el resultado

public class Operacion
{
    public int Sumar(int number1, int number2)
    {
       return number1 + number2;   
    }

    public int Restar(int number1, int number2)
    {
       return number1 - number2;   
    }
    
    public int Multiplicar(int number1, int number2)
    {
       return number1 * number2;   
    }

    public int Dividir(int number1, int number2)
    {
       return number1 / number2;   
    }
}

var operacion = new Operacion();
var resultadoSuma = operacion.Sumar(1, 1);
var resultadoResta = operacion.Restar(1, 1);
var resultadoMultiplicacion = operacion.Multiplicar(2, 2);
var resultadoDivision = operacion.Dividir(10, 5);Lenguaje del código: PHP (php)

Si ahora nos fijamos, tenemos 4 métodos, que cada uno hace una cosas diferente, por lo que nuestro nivel de abstracción ha aumentado.

¿ Y que quiere decir esto ?

Pues que en el momento en el que tengas los métodos separados, y cada uno de ellos con una única responsabilidad, mas reutilizable será tu código, además mas entendible, y mas fácil de refactorizar en un futuro.

De otro modo, si nos fijamos, hemos refactorizado un método de casi 20 líneas, por 5 métodos de una línea cada uno.

Cada método tiene un nombre indicativo de la única responsabilidad que se le ha otorgado, y si en algún momento necesitamos realizar cualquiera de las 4 operaciones disponibles, solo hemos de llamar a ese método, por lo que el código se entiende mejor si llamamos a Sumar(), que si llamamos a Operación con un enumerado Tipo Operación, además ya podemos prescindir de dicha enumeración que realmente no nos proporcionaba valor alguno a nuestra aplicación.

2 thoughts on “Object Calisthenics – Un nivel de indentación por método

  1. ¡Hola amigo!
    Escribes las cosas correctas….
    Pero mi jefe me dice que el negocio necesita una solución más rápida…
    ¡Será mejor que escribas cómo explicarle al cliente que primero debes pensar con la cabeza y luego hacerlo con las manos!

    1. Buenos días LG, bueno es como todo en la vida. Muchas veces dedicando sólo al principio un poco mas de tiempo al desarrollo, vas a ahorrar mucho en un futuro. No se trata de hacerlo todo de golpe, si no de aplicar “La regla del Boy Scout”. Y poco a poco todo va a su cauce y dedicando menos tiempo que antes. Gracias por leerme.

Deja una respuesta

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