Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 01-01-2013 23:10:27

Kunai
Nouveau membre
Lieu: Var
Date d'inscription: 17-02-2012
Messages: 6

[conception] Dependency Injection, Data Mapper et liste d'objets

Bonjour,

Avec les nouveautés introduites avec le ZF2, je cherche à anticiper la migration de mes développements dédiés au ZF1 pour y généraliser l'inversion de contrôle et permettre de passer plus facilement au conteneur d'injection de dépendance (DiC). Pour autant, je n'arrive pas à concevoir l'injection de dépendance dès lors qu'une classe contient une méthode censée créer une liste d'objets. Je vais prendre en exemple mon propre problème : un data mapper dont une méthode permet de retrouver un ensemble d'entrées en base de données pour créer un ensemble d'objets associés. L'idée est de se passer de conteneur d'injection de dépendance pour se focaliser sur l'injection en elle-même or, sans conteneur, je ne vois pas comment appliquer l'injection de dépendance au cas exposé précédemment. Je ne vois que 3 solutions qui ne me paraissent pas satisfaisantes :

1. Se passer d'injection de dépendance en considérant qu'il y a nécessairement un couplage fort entre un data mapper et la classe qui définie les objets associés. Ce n'est du coup pas une solution au problème mais peut-être est-ce la seule solution logique pour concevoir un data mapper.

2. Passer une instance de l'objet mappé au constructeur ou à une méthode du data mapper et cloner l'objet ou utiliser l'API reflection. Cette solution semble tirée par les cheveux (illogique d'instancier un objet pour rien) et n'est probablement pas optimale niveau performances.

3. Passer une chaîne de caractères correspondant au nom de la classe mappée au constructeur ou à une méthode et l'utiliser pour créer les instances via call_user_func. Ça semble être la solution la plus en adéquation avec l'utilisation future du DiC du ZF2 puisque ce dernier utilise des chaînes pour déclarer / récupérer les objets stockés. Toutefois, elle semble être totalement contraire au principe même d'injection de dépendance puisqu'au final, la création des instances se fait toujours au sein du data mapper.

4. Passer au data mapper une instance d'un objet représentant une liste de l'objet mappé... qui ne ferait que reproduire le même problème au sein de l'objet liste... Donc solution non satisfaisante également.

Du coup, à part la solution 1 qui n'en est pas une, je ne vois pas de solution évidente (ni même recherchée) pour résoudre ma problématique. Si quelqu'un a une idée, elle est bienvenue.

Hors ligne

 

#2 27-01-2013 16:40:16

Alcide_
Membre
Lieu: Brest
Date d'inscription: 20-03-2010
Messages: 31
Site web

Re: [conception] Dependency Injection, Data Mapper et liste d'objets

La problématique est intéressante...
La question est "que doit renvoyer ta méthode de type fetchAll dans ton data mapper ?"

1 - Une référence de type Liste  respectant un interface (ex: RowsetInterface)?
2 - un tableau (array) contenant des références respectant une interface (ex: RowInterface) ?
3 - une référence de type Liste contenant des références ?

Sans accès au conteneur, les solutions sont assez réduites, car il te faudra donc injecter directement les objets dont le data mapper a besoin soit à l'instanciation (constructeur), soit à l'initialisation (accesseurs)... Hors, dans le cas d'une liste, tu ne peux pas savoir le nombre de résultats que tu auras au moment de l'instanciation du data mapper.

Si on prend l'exemple du quickstart de ZF 1.12 :

Code:

[lang=php]public function fetchAll()
    {
        $resultSet = $this->getDbTable()->fetchAll();
        $entries   = array();
        foreach ($resultSet as $row) {
            $entry = new Application_Model_Guestbook();
            $entry->setId($row->id)
                  ->setEmail($row->email)
                  ->setComment($row->comment)
                  ->setCreated($row->created);
            $entries[] = $entry;
        }
        return $entries;
    }

Ici le but serait d'utiliser l'injection pour l'instanciation de "Application_Model_Guestbook".
Chose à mon avis impossible sans conteneur.
Je vois deux solutions :
1 - comme tu l'as dis, injecter le nom de la classe sous forme de String. Même si c'est le data mapper qui réalise l'instanciation, tant que tu respecte une interface je ne voit pas trop de problème.
2 - injecter une fabrique qui se chargerait de l'instanciation mais ça peut devenir un peu lourd...

Voilà, le déroulé est un peu long pour pas grand chose mais c'est souvent le cas que je réfléchi en même temps que j'écris ;-)
Conclusion : injection de String ou injection de Fabrique...

Dernière modification par Alcide_ (27-01-2013 17:01:00)

Hors ligne

 

#3 29-05-2013 23:36:07

Kunai
Nouveau membre
Lieu: Var
Date d'inscription: 17-02-2012
Messages: 6

Re: [conception] Dependency Injection, Data Mapper et liste d'objets

Bonsoir,

Je remonte ce sujet afin de soumettre une proposition pour résoudre la problématique exposée aux critiques éventuelles. Je me dis que finalement, peut-être que l'utilisation de closures serait la solution idéale. Ainsi, l'injection de dépendance serait réalisée de manière assez classique :

Code:

[lang=php]

$callback = function() {
    // Injection de la dépendance du mapper

    // Peut être un objet de test unitaire
    // return new MockObject();

    // Est compatible avec un DiC
    // return new Zend\Di\Di()->get('ModelA');

    return new ModelA();
};

// Passage de la dépendance via le constructeur
$mapper = new ModelAMapper($callback);

// ou via un setter
$mapper->setCreateFunction($callback);

Je pense que cette solution permet le découplage attendu par le concept d'injection de dépendance au sacrifice peut-être d'une légère complexification du mapper, surtout si ce dernier doit créer des instances de plusieurs classes différentes.

Hors ligne

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages