PHP Metodo di concatenamento in PHP


Esempio

Il metodo Chaining è una tecnica spiegata nel libro Domain Specific Languages ​​di Martin Fowler . Il concatenamento del metodo è riassunto come

Fa in modo che i metodi di modifica restituiscano l'oggetto host, in modo che più modificatori possano essere richiamati in una singola espressione .

Considera questa parte di codice non concatenante / regolare (trasferita su PHP dal libro sopra menzionato)

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

Il metodo Chaining consente di scrivere le dichiarazioni di cui sopra in modo più compatto:

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

Tutto quello che devi fare per far funzionare tutto questo è return $this nei metodi da cui vuoi concatenare:

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
    }
}

Quando usarlo

I casi d'uso primari per l'utilizzo di Method Chaining si hanno quando si creano lingue specifiche di dominio interne. Il concatenamento di metodi è un elemento fondamentale in Expression Builders e Fluent Interfaces . Non è sinonimo di quelli, però . Il metodo Chaining consente semplicemente a quelli. Citando Fowler:

Ho anche notato un malinteso comune: molte persone sembrano equiparare interfacce fluide con il metodo Chaining. Certamente il concatenamento è una tecnica comune da utilizzare con interfacce fluenti, ma la vera fluidità è molto più di questo.

Detto questo, l'uso del metodo di concatenamento solo per evitare di scrivere l'oggetto host è considerato un odore di codice da molti. Rende API non ovvi, soprattutto quando si mischiano con API non concatenate.


Note aggiuntive

Comando Separazione delle query

Command Query Separation è un principio di design portato avanti da Bertrand Meyer . Dichiara che i metodi che mutano lo stato ( comandi ) non dovrebbero restituire nulla, mentre i metodi che restituiscono qualcosa ( query ) non dovrebbero mutare lo stato. Questo rende più facile ragionare sul sistema. Il metodo Chaining viola questo principio perché stiamo mutando lo stato e restituendo qualcosa.

Getters

Quando si utilizzano le classi che implementano il concatenamento dei metodi, prestare particolare attenzione quando si chiamano i metodi getter (cioè i metodi che restituiscono qualcosa di diverso da $this ). Poiché i getter devono restituire un valore diverso da $this , concatenare un metodo addizionale a un getter rende la chiamata operativa sul valore ottenuto , non sull'oggetto originale. Mentre ci sono alcuni casi d'uso per i getter concatenati, possono rendere il codice meno leggibile.

Legge di Demetra e impatto sui test

Il concatenamento di metodi come presentato sopra non viola la legge di Demeter . Né ha impatto sui test. Questo perché stiamo restituendo l'istanza dell'host e non qualche collaboratore. È un comune malinteso derivante da persone che confondono il semplice metodo di concatenazione con Fluent Interfaces e Expression Builders . È solo quando Method Chaining restituisce altri oggetti rispetto all'oggetto host che violi Law of Demeter e finisci con i Mock Fests nei tuoi test.