Optionnel

En PHP et donc dans Dotclear et Clearbricks, on utilise tout un tas de fonctions utilitaires qui attendent un ou plusieurs paramètres obligatoires et un ou plusieurs paramètres optionnels, permettant de spécialiser leur comportement.

Au fil des développements, afin de conserver une compatibilité ascendante, on évite de modifier cette « signature », c’est à dire modifier le rôle de chacun des paramètres et on se limite à en ajouter de nouveaux, forcément optionnels, en fin de liste.

C’est pratique, parce qu’ainsi les codes existants n’ont pas à être modifiés et les nouveaux peuvent profiter des nouveautés. Sauf qu’à force, on arrive à en avoir une liste impossible à mémoriser, d’une part, et d’autre part, si vous souhaitez utiliser uniquement une partie seulement de ceux-ci vous devez a minima fournir tout ceux qui précédent !

Exemple (tiré de Clearbricks) :

Soit la fonction form::combo(), qui attend 2 paramètres obligatoires, id, data, et 5 paramètres optionnels, default, class, tabindex, disabled, extra_html :

public static function combo($nid, $data, $default = '', $class = '', $tabindex = '',
        $disabled = false, $extra_html = '') {
…
}

Si vous souhaitez l’utiliser en n’indiquant que la valeur pour disabled, vous devez alors l’appeler de cette façon :

form::combo($nid, $data, '', '', '', true);

Vous voyez ? Obligé de préciser 3 fois '' pour arriver à nos fins. C’est lourd et surtout on fini, à force d’avoir des paramètres à rallonge, par devoir compter les arguments pour vérifier qu’on a bien mis tout ceux qui sont nécessaires et quand on relit plus tard l’appel on ne sait pas à quoi correspond tel ou tel argument.

Bref spa terrible !

Alors pour pallier ça j’ai choisi de proposer une seconde méthode pour appeler cette fonction : la liste des paramètres optionnels pertinents peut être fournie sous la forme d’un tableau associatif (clé → valeur) en indiquant uniquement par leur nom le ou les paramètres utilisés et pas les autres. Si je reprends l’exemple ci-dessus, l’appel devient ceci :

form::combo($nid, $data, array( 'disabled' => true ));

Deux avantages à ça. Premièrement vous n’indiquez que ce qui est pertinent. Deuxièmement vous nommez ce que vous utilisez ce qui rend la lecture future plus simple (on sait ce que vous avez utilisé sans devoir retourner lire le code ou la doc de la fonction appelée).

Il y a tout de même un inconvénient, même deux. Premièrement vous fixez le noms des arguments de la fonction appelée et êtes donc tributaire d’un éventuel changement à ce niveau. Deuxièmement ça fonctionne uniquement si le premier argument optionnel n’est pas déjà un tableau.

En détail, j’utilise ceci en début de fonction appelée (je reprends l’exemple de form::combo) :

public static function combo($nid, $data, $default = '', $class = '', $tabindex = '',
        $disabled = false, $extra_html = '') {
…
    if (func_num_args() > 2 && is_array($default)) {
        // Cope with associative array of optional parameters
        $options = self::getDefaults(__CLASS__, __FUNCTION__);
        extract(array_merge($options, array_intersect_key($default, $options)));
    }
…
}

Qui me permet de récupérer dans le tableau options toutes les valeurs nécessaires, celles passées au moment de l’appel et celles par défaut. Le 2 du test doit indiquer le nombre de paramètres obligatoires de la fonction, et $default correspond au premier paramètre optionnel. C’est donc à ajuster fonction par fonction.

Ensuite ce tableau d’options est utilisé pour valoriser tous les paramètres optionnels de la fonction, ce qui permet de ne pas modifier tout le code qui suit.

Pour info, la fonction qui permet de récupérer la liste des paramètres optionnels est celle-ci :

private static function getDefaults($class, $method)
{
    $options = array();
    $reflect = new ReflectionMethod($class, $method);
    foreach ($reflect->getParameters() as $param) {
        if ($param->isOptional()) {
            $options[$param->getName()] = $param->getDefaultValue();
        }
    }
    return $options;
}

Ça sera en place dans Clearbricks pour la prochaine 2.14 de Dotclear et ça simplifiera, a minima, l’usage des fonctions qui permettent d’insérer des composants de formulaires dans les pages d’administration.

Ajouter un commentaire

Les champs suivis d'un * sont obligatoires

Les commentaires peuvent être formatés en utilisant la syntaxe Markdown Extra.

Ajouter un rétrolien

URL de rétrolien : https://open-time.net/trackback/13664

Haut de page