Le Design Pattern Registre (Registry) en PHP

Le Registre est un design pattern décrit dans l’excellent livre de Martin Fowler, Patterns of Enterprise Application Architecturecommunément désigné sous le terme PoEAA (Pas de traduction française).

La définition du registre est simple : c’est un objet « bien connu » qui permet aux autres de récupérer d’autres objets ou services.

Nous allons voir ici deux implémentations courantes du Registre en PHP.

Un objet « bien connu » de tous

Avouons le de suite, le Registre a des airs de variable globale. L’utilité du Registre est de permettre à des composants de récupérer d’autres composants (des dépendances) sans avoir à les passer dans toute la chaîne d’appel.

Pour le moment, nous allons nous intéresser uniquement à l’implémentation de ce Registre sans nous attarder sur sa pertinence.

Le modèle Singleton
Le Registre est réalisé sous la forme d’un Singleton et est disponible partout dans l’application.

class Registry 
{
   private static $_registry = false;
   public static function getInstance() 
   {
      if (self::$_registry === false){
         self::$_registry = new Registry();
      }
      return self::$_registry;
   }
   //...
   //je passe ici les autres méthodes du singleton
   private $_connection;
   public function getConnection()
   {
      return $this->_connection;
   }

   public function setConnection(Connection $pConnection)
   {
      $this->_connection = $pConnection;
      return $this;
   }
}

//le code client l'utilise classiquement
Registry::getInstance()->getConnection()
                       ->doStuff();

Le modèle statique
Le Registre est réalisé sous la forme d’une classe composée uniquement de méthodes statiques.

Ici le Registre est composé uniquement de classes statiques
class Registry
{
   private static $_connection;

   public static function getConnection()
   {
      return self::$_connection;
   }

   public static function setConnection(Connection $pConnection)
   {
      self::$_connection = $pConnection;
   }
}

//Le code client l'utilise encore une fois classiquement
Registry::getConnection()->doStuff();

Mais ?? C’est une variable globale !

Le Registre n’est ni plus ni moins une variable globale déguisée…. conteneur d’autres variables globales.
C’est dans sa forme la plus simple (voir plus loin) ou ses dangers nous sautent aux yeux, et à ce titre, il doit être mis en oeuvre avec précaution.

On le retrouve toutefois souvent à l’oeuvre dans les applications pour accomplir les tâches de configuration et de paramétrage, la ou devoir envoyer à l’intégralité de nos objets les paramètres nécessaires à leur création / appel est fastidieux.

En PHP, a-t-on vraiment besoin d’un registre ?

En PHP, contrairement à Java, nous avons quelques outils qui nous permettent de simplifier encore plus l’approche du Registre : $GLOBALS, alors pourquoi ne pas en profiter ?

//Dans un include.php en début de script
$GLOBALS['Registry'] = new Registry();

//et plus tard dans le code client
$GLOBALS['Registry']->getConnection()->doStuff();

Bien sûr, on peut encore aller plus loin et se dire qu’après tout, le Registre n’apporte pas grand chose si ce ne sont des getter/setter vides de sens, et donc nous pouvons placer dans le registre un simple tableau associatif clef / valeur et non un objet.

//Dans notre include.php
$GLOBALS['Registry'] = array();
$GLOBALS['Registry']['connection'] = new Connection();

//Dans le code client, on utilise directement la variable globale sans passer par une 
//quelconque abstraction
$GLOBALS['Registry']['connection']->doStuff();

N’est-ce pas pousser le bouchon un peu loin ?

Si, bien sûr, tout ceci pousse volontairement un peu loin la plaisanterie. Un objet présentera toujours quelques avantages comme celui de pouvoir être décoré, adapté, et j’en passe.

De plus, notre tableau associatif permet moins de choses qu’un objet Registre accompagné de getter/setter, comme par exemple le contrôle du type, la levée d’exception sur une lecture incorrecte ou simplement une interface clarifiée sur ses possibilités.

Pour le jeu, si l’on tient vraiment à manipuler notre Registre comme un tableau dans $GLOBALS['Registry'], PHP nous donne tous les outils nécessaires : L’interface ArrayAccess par exemple, qui permet de manipuler un objet comme un tableau :

class Registry implements ArrayAccess
{
   private static $_registry = false;
   public static function getInstance() 
   {
      if (self::$_registry === false){
         self::$_registry = new Registry();
      }
      return self::$_registry;
   }

   private $_vars = array();
   public function offsetGet($pVarName)
   {
      //ajouter contrôles éventuels
      return $this->_vars[$pVarName];
   }

   public function offsetSet($pVarName, $pValue)
   {
      //ajouter contrôles éventuels
      $this->_vars[$pVarName] = $pVarName;
   }

   public function offsetExists ($pVarName)
   {
      return array_key_exists($pVarName, $this->_vars);
   }
   public function offsetUnset ($pVarName)
   {
      //ajouter contrôles éventuels
      unset($this->_vars[$pVarName]);
   }
}

//Dans notre code client maintenant
$GLOBALS['Registry'] = new Registry();

//plus loin
$GLOBALS['Registry']['Connection'] = new Connection();

Doit on vraiment utiliser le Registre ? Dans quels cas ?

Dans ses dernières formes, le crédo « les variables globales sont le mal » est tellement ancré dans les moeurs que n’importe quel développeur saute au plafond (au moins en première réaction) à la lecture d’un $GLOBALS, ce qui donne au Registre une longueur de retard dans sa simplification.

Le Registre peut être considéré comme une syntaxe plus élégante, déguisée, de la variable globale, mais cela ne le crédite que de très peu.

J’avoue que pour ma part, je décourage l’utilisation du Registre au premier abord car il tend à détériorer la conception globale de l’application en

  • couplant tous les utilisateurs du Registre à des contextes pas vraiment maîtrisés
  • permettant de prendre des raccourcis sur les interfaces des objets en ne se souciant plus des « vraies » dépendances

Toutefois, comme je conclue souvent, à chaque problème sa solution. Si vous choisissez d’utiliser ce pattern en toute connaissance de cause dans un contexte bien particulier ou ce pattern réponds vraiment à la problématique, libre à vous !

Des exemples de registre

  1. I am impressed, I have to say. Really rarely do I see a blog thats both informative and entertaining, and let me tell you, you have hit the nail on the head. Your idea is outstanding; the matter is something that not many people are talking intelligently a

Laisser un commentaire


NOTE - Vous pouvez utiliser les éléments et attributs HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackbacks and Pingbacks: