PHP Método de encadenamiento en PHP


Ejemplo

El método de encadenamiento es una técnica que se explica en el libro de Martin Fowler Lenguajes específicos del dominio . Método de encadenamiento se resume como

Los métodos modificadores de Makes devuelven el objeto host, de modo que se pueden invocar varios modificadores en una sola expresión .

Considere este código no encadenado / regular (portado a PHP desde el libro mencionado anteriormente)

$hardDrive = new HardDrive;
$hardDrive->setCapacity(150);
$hardDrive->external();
$hardDrive->setSpeed(7200);

El método de encadenamiento le permitiría escribir las declaraciones anteriores de una manera más compacta:

$hardDrive = (new HardDrive)
    ->setCapacity(150)
    ->external()
    ->setSpeed(7200);

Todo lo que necesita hacer para que esto funcione es return $this en los métodos que desea encadenar:

class HardDrive {
    protected $isExternal = false;
    protected $capacity = 0;
    protected $speed = 0;

    public function external($isExternal = true) {
        $this->isExternal = $isExternal;        
        return $this; // returns the current class instance to allow method chaining
    }

    public function setCapacity($capacity) {
        $this->capacity = $capacity;        
        return $this; // returns the current class instance to allow method chaining
    }

    public function setSpeed($speed) {
        $this->speed = $speed;        
        return $this; // returns the current class instance to allow method chaining
    }
}

Cuando usarlo

Los principales casos de uso para utilizar el método de encadenamiento son cuando se crean lenguajes internos específicos de dominio. El método de encadenamiento es un bloque de construcción en Expression Builders e Fluent Interfaces . Sin embargo, no es sinónimo de ellos . Método de encadenamiento simplemente habilita aquellos. Citando a Fowler:

También he notado un error común: muchas personas parecen equiparar las interfaces fluidas con el Encadenamiento de métodos. Ciertamente, el encadenamiento es una técnica común para usar con interfaces fluidas, pero la verdadera fluidez es mucho más que eso.

Dicho esto, el uso de Method Chaining solo para evitar escribir el objeto host es considerado por muchos como un olor de código . Hace que las API no sean evidentes, especialmente cuando se mezclan con API sin encadenamiento.


Notas adicionales

Separación de consulta de comando

Command Separación de separación es un principio de diseño presentado por Bertrand Meyer . Establece que los métodos que mutan el estado ( comandos ) no deben devolver nada, mientras que los métodos que devuelven algo ( consultas ) no deben mutar el estado. Esto hace que sea más fácil razonar sobre el sistema. El método de encadenamiento viola este principio porque estamos mutando el estado y devolviendo algo.

Getters

Al utilizar clases que implementan el encadenamiento de métodos, preste especial atención al llamar a métodos getter (es decir, métodos que devuelven algo diferente a $this ). Como los captadores deben devolver un valor diferente a $this , el encadenamiento de un método adicional a un captador hace que la llamada opere en el valor obtenido , no en el objeto original. Si bien hay algunos casos de uso para captadores encadenados, pueden hacer que el código sea menos legible.

Ley de Demeter e impacto en las pruebas.

El método de encadenamiento como se presentó anteriormente no viola la Ley de Demeter . Tampoco tiene impacto en las pruebas. Esto se debe a que estamos devolviendo la instancia de host y no algún colaborador. Es un error común que surge de personas que confunden el mero encadenamiento de métodos con interfaces fluidas y constructores de expresiones . Solo cuando el Encadenamiento de métodos devuelve otros objetos que no son el objeto host , violas la Ley de Demeter y terminas con festines de prueba en tus pruebas.