Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

PHP 8.4: cosa sono e come funzionano i Lazy Objects

PHP: analizziamo il funzionamento dei Lazy Objects per scoprirne i vantaggi a favore delle prestazioni di un'applicazione
PHP: analizziamo il funzionamento dei Lazy Objects per scoprirne i vantaggi a favore delle prestazioni di un'applicazione
Link copiato negli appunti

PHP 8.4 è una delle major release più interessanti degli ultimi anni. Questo grazie al gran numero di funzionalità che sono state incluse nell'ultimo aggiornamento del linguaggio (escludendo naturalmente le minor release successive).

In esso troviamo ad esempio la nuova funzione array_find() con cui abbiamo finalmente un costrutto dedicato all'individuazione di elementi in grado di corrispondere a condizioni specifiche. Ma meritano una segnalazione anche i Property Hooks, la possibilità di specificare separatamente i permessi di lettura e scrittura delle proprietà, l'introduzione dell'attributo #[\Deprecated] e, sicuramente, anche le nuove modalità di arrotondamento fornite tramite la funzione round().

Se però dovessero chiedermi quale feature ritengo più interessante di questa versione risponderei senza dubbio il supporto per i Lazy Objects. Forse è solo un parere personale da sviluppatore di vecchia data. Vale però la pena di analizzare il loro funzionamento per scoprire quali vantaggi potrebbero offrire durante il coding. Iniziamo quindi dandone una semplice definizione.

Cosa sono i Lazy Objects di PHP 8.4

I Lazy Objects sono una funzionalità che permette di rinviare l'inizializzazione di un oggetto fino al momento in cui si accede ad esso. In questo caso non parliamo quindi di un nuovo costrutto di PHP ma di un nuovo approccio alla scrittura del codice.

Esistono infatti oggetti la cui logica di inizializzazione è particolarmente pesante dal punto di vista del consumo di risorse. Poterla rimandare si traduce così in un impatto positivo sulle prestazioni. Soprattutto quando l'inizializzazione di un oggetto è utile soltanto in fase di esecuzione. Maggiore sarà la complessità della nostra applicazione più dovremmo osservarne i benefici.

Ma come funzionano i Lazy Objects in PHP? In pratica essi utilizzano un oggetto proxy, che viene generato dinamicamente, per posticipare l'esecuzione del costruttore di un oggetto target. Questo proxy imita la classe originale e consente all'oggetto reale di rimanere non inizializzato fino a quando non viene effettivamente impiegato. Alla base di tutto vi è la reflection con cui possiamo ispezionare e manipolare classi, metodi, proprietà e funzioni durante l'esecuzione di un'applicazione.

Grazie ad essa, infatti, abbiamo la possibilità di accedere ai dettagli sulla struttura del codice e di interagire con gli elementi in modo dinamico. Anche quando questi ultimi non sono stati definiti esplicitamente in anticipo.

Un esempio pratico di Lazy Objects nel codice PHP

Per proporre un esempio pratico riguardante l'uso dei Lazy Objects all'interno di un progetto è possibile fare riferimento al codice seguente:

<?php
// Definizione di una classe chiamata SimpsonClass
class SimpsonClass
{
    // Dichiarazione del costruttore della classe con una proprietà privata $homer
    public function __construct(private int $homer)
    {
        // Messaggio visualizzato quando un oggetto della classe viene inizializzato
        echo 'Homer sta inizializzando qualcosa...'.PHP_EOL;
    }
    // Metodo pubblico per accedere al valore della proprietà privata $homer
    public function getHomer(): int
    {
        return $this->homer; // Restituisce il valore di $homer
    }
}
// Creazione di un'istanza della classe SimpsonClass e assegnazione a $bart
$bart = new SimpsonClass(1); // Il valore 1 viene passato al costruttore e assegnato a $homer
// Messaggio che indica che l'oggetto è stato creato
echo 'Bart è stato creato come un Lazy Object.'.PHP_EOL;
// Chiamata del metodo getHomer() per ottenere il valore di $homer
// e visualizzazione del messaggio con il valore restituito
echo 'Bart sta chiamando Homer: '. $bart->getHomer() . PHP_EOL;

Se tutto dovesse andare come previsto gli output in fase di esecuzione saranno i seguenti e in quest'ordine:

Homer sta inizializzando qualcosa...
Bart è stato creato come un Lazy Object.
Bart sta chiamando Homer: 1

La classe SimpsonClass rappresenta un'entità con una proprietà privata $homer che è un numero intero. Essa viene inizializzata attraverso il costruttore che accetta un parametro (int $homer) e lo assegna ad $homer. Il metodo pubblico getHomer() permette poi di accedere al valore di $homer che altrimenti non sarebbe accessibile direttamente a causa del suo livello di visibilità. Viene inoltre creato un nuovo oggetto $bart con valore 1 passato al costruttore. Questo assegna 1 ad $homer e dopo che getHomer() viene chiamato sull'oggetto $bart il valore di $homer viene mostrato in output.

I vantaggi e gli svantaggi dei Lazy Objects

Abbiamo ormai capito che i Lazy Objects di PHP sono appunto degli oggetti "pigri" perché consentono di posticipare tramite un oggetto proxy l'esecuzione del costruttore di un oggetto target, l'inizializzazione di quest'ultimo risulterà così posticipata. Tipicamente un Lazy Object viene creato da un metodo, mentre una funzione di inizializzazione inizializza l'oggetto unicamente in corrispondenza della chiamata del metodo. Quali sono i vantaggi che derivano dall'uso di questa funzionalità?

In primo luogo si avrà un miglioramento delle prestazioni. Il fatto di ritardare la fase di inizializzazione di un oggetto, e di renderla possibile solo quando diventa effettivamente necessaria, permette infatti di occupare una minore quantità di memoria. Tale beneficio dovrebbe risultare ancora più evidente quando si sviluppano progetti che richiedono l'interazione con le API di servizi di terze parti. Nello stesso modo si potrebbe avere un vantaggio in termini di ottimizzazione delle risorse quando si devo operare con degli ORM. O se si lavora con i container e si devono effettuare procedure di injection delle dipendenze.

Un altro aspetto da considerare riguarda direttamente la reflection. Se infatti gli oggetti proxy vengono creati dinamicamente i Lazy Objects possono essere gestiti come qualsiasi altro oggetto senza ulteriori interventi sul codice.

Ma veniamo agli svantaggi che esistono anche in questo caso, non sono però numerosi né particolarmente ostici. Innanzitutto la presenza di livelli addizionali dovuti alla generazione dei proxy potrebbe rendere il debug più macchinoso. In secondo luogo, dato che si opera con degli stati che vengono posticipati si potrebbero incontrare delle difficoltà sia in fase di serializzazione che di deserializzazione.

Conclusioni

Inclusi nel rilascio di PHP 8.4, i Lazy Objects rappresentano una novità che migliora le performance e l'efficienza del codice. Permettono infatti di ritardare l'inizializzazione di un oggetto fino a quando esso non deve essere effettivamente utilizzato. In questo modo si riduce il consumo della memoria, vengono liberate risorse preziose e si velocizzano i tempi di caricamento. Tale funzionalità è quindi particolarmente utile nello sviluppo di applicazioni complesse, come per esempio quelle che prevedono il coinvolgimento di un gran numero di dipendenze o operazioni di inizializzazione molto costose dal punto di vista delle risorse.

Ti consigliamo anche