Il PHP 7 diventa severo

Come tutti sappiamo PHP è stato concepito come linguaggio a tipizzazione dinamica: visto da una parte dello scenario come pro, dall’altra come contro.

Nonostante l’esistenza di diversi linguaggi con tale caratteristica quest’ultima è stata per diverso tempo motivo di critica. E’ chiaro che lo sviluppo con certi linguaggi aiuta a scrivere codice più pulito, ma di certo è difficile affermare che la tipizzazione dinamica sfoci in codice spazzatura.

Così come le critiche a PHP spesso sono incomplete o riferite a codice deprecato, così accade per la tipizzazione; per esempio PHP ha e ha avuto per diverso tempo diverse modalità per trattare con i tipi ed è possibile garantire che uno specifico tipo venga utilizzato in uno specifico punto del codice.

Anche il type hinting è stato utilizzato per molto tempo, anche se in modo incompleto.

Con PHP7 sarà possibile far sì che le funzioni e i metodi accettino parametri di determinati tipi.

Andiamo più nello specifico: i principali RFC del nuovo PHP7 sono fondamentalmente tre:

  1. Type hinting scalare;
  2. Dichiarazione di tipi di ritorno;
  3. Gestione delle eccezioni.

Type Hinting Scalare

Una nuova caratteristica quindi di PHP7 sarà quindi il type hinting scalare, vale a dire int, float, string e bool; questo ci permetterà meglio di definire più precisamente nei metodi/funzioni i parametri e i dati da restituire in modo da avere un maggiore controllo sul flusso del nostro codice.

Per esempio, ammettiamo di avere una classe ElePHPant che rappresenti un elefante. Per gli esempi di questo articolo prenderemo a riferimento quelli presenti nel sito del PHP. Utilizziamo gli scalar type hint nel costruttore:

class ElePHPant {
    public $name, $age, $cuteness, $evil;
    public function __construct(string $name, int $age, float $cuteness, bool $evil) {
        $this->name = $name;
        $this->age = $age;
        $this->cuteness = $cuteness;
        $this->evil = $evil;
    }
}

In un file separato ora istanziamo un oggetto di tipo ElePHPant:

require "ElePHPant.php";

$sara = new ElePHPant("Sara", 7, 0.99, FALSE);
var_dump($sara); /*
object(ElePHPant)#1 (4) {
  ["name"]=>
  string(4) "Sara"
  ["age"]=>
  int(7)
  ["cuteness"]=>
  float(0.99)
  ["evil"]=>
  bool(false)
} */

L’istanza avviene correttamente perché i tipi degli argomenti passati matchano correttamente.

Di default vengono utilizzati i type hint deboli che permettono una conversione, in modo che possiamo passare argomenti non dello stesso tipo ma che possono essere convertiti e così sarà fatto, così come con le estensioni e le funzioni built-in di PHP:

require "ElePHPant.php";

$nelly = new ElePHPant(12345, "7 years", "0.9", "1");
var_dump($nelly); /*
object(ElePHPant)#2 (4) {
  ["name"]=>
  string(5) "12345"
  ["age"]=>
  int(7)
  ["cuteness"]=>
  float(0.9)
  ["evil"]=>
  bool(true)
}
Notice: A non well formed numeric value encountered
*/

Modalità di Type Checking

Sarà però possibile attivare un controllo più severo dei tipi per file attraverso una direttiva opzionale con la quale PHP controllerà le variabili in strict-mode o in weak-mode.

Nell’esempio sottostante la stessa chiamata di prima fallirà in un fatal error:

require "ElePHPant.php";

declare(strict_types=1);

$nelly = new ElePHPant(12345, "7 years", "0.9", "1");
// Catchable fatal error: Argument 1 passed to ElePHPant::__construct() must be of the type string, integer given

Questo verrà applicato non solo alle funzioni e metodi definite dall’utente ma anche alle funzioni native.

declare(strict_types=1);

$foo = sin(1);
// Catchable fatal error: sin() expects parameter 1 to be float, integer given

Inoltre è da tenere a mente che la direttiva riguarda tutte le chiamate alla funzione/metodo (o blocco declare() se specificato) indipendentemente dal fatto che le funzioni o metodi chiamati sono stati dichiarati in file in cui è stato attivato lo strict-mode.

Quindi:

require "ElePHPant.php";

// implicitly weakly type-checked code (default)
function makeEllie() {
    return new ElePHPant(42, "19", "0.7", 1); // will succeed, no matter where makeEllie() is called from
}

makeEllie(); // no error

declare(strict_types=1) {
    // explicitly strictly type-checked code

    makeEllie(); // no error

    function makeEllie_strict() {
        return new ElePHPant(42, "19", "0.7", 1); // will fail, no matter where makeEllie_strict() is called from
    }

    makeEllie_strict(); // error
}

// implicitly weakly type-checked code, again

makeEllie_strict(); // error

Dichiarazioni del tipo di ritorno

Gli scalar type hint funzionano anche per le variabili da restituire, come possiamo vedere:

function foobar(): int {
    return 1.0;
}

var_dump(foobar()); // int(1)

declare(strict_types=1) {
    function foobar2(): int {
        return 1.0;
    }
}

var_dump(foobar2());
// Catchable fatal error: Return value of foobar() must be of the type integer, float returned

Tuttavia è da far notare che c’è una differenza fondamentale tra i type hint per gli argomenti e i type hint per i valori di ritorno:

  • la modalità di controllo per gli argomenti di una funzione/metodo corrisponde a quella utilizzata dal file contenente la chiamata a tale funzione/metodo;
  • la modalità di controllo per i valori di ritorno è quello utilizzato dal file che definisce la funzione.

Facciamo un esempio:

declare(strict_types=1) {
    function foobar3(): int {
        return 1.0; // error, regardless of where it is called from
    }

    foobar3(); // error
}

foobar3(); // also error

Exceptions in the engine

Come accennato viene introdotto un Engine Exception: ora un’incoerenza tra i tipi dichiarati e quelli passati in ingresso come argomenti o restituiti si traduce in un catchable fatal error; se questa RFC verrà accettata l’incoerenza si tradurrà invece in un Engine Exception, permettendoci così di controllare maggiormente il comportamento del nostro codice e individuare più facilmente i nostri errori legati alla tipizzazione o semplicemente presentare una risposta più appropriata.

La direzione che sta prendendo PHP può spaventare soprattutto generando il timore che stia diventando un linguaggio strettamente tipizzato o a tipizzazione statica, ma per fortuna non è così perché PHP sarà sempre tipizzato dinamicamente.
Il grosso vantaggio infatti è che la severità sta nella scelta dello sviluppatore.

Lo scalar type hinting sarà una caratteristica fondamentale per PHP7 e PHP7 sarà un passo fondamentale per PHP, che lo manterrà emozionante e giovane, capace di crescere ancora a lungo.

Buon divertimento!

Loading Facebook Comments ...
0 commenti

Lascia un Commento

Vuoi partecipare alla discussione?
Fornisci il tuo contributo!

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *