Rester OO et testable tout en travaillant avec une base de données


16

Quelles sont les stratégies POO pour travailler avec une base de données tout en gardant les éléments testables? Disons que j'ai une classe Utilisateur et que mon environnement de production fonctionne avec MySQL. Je vois quelques approches possibles, présentées ici en utilisant PHP:

  1. Passez une $ data_source avec des interfaces pour load()et save(), pour résumer la source de données backend. Lors des tests, passez un autre magasin de données.

    $ user = nouvel utilisateur ($ mysql_data_source);
    $ user-> load ('bob');
    $ user-> setNickname ('Robby');
    $ user-> save ();
    
  2. Utilisez une fabrique qui accède à la base de données et transmet la ligne de résultat au constructeur de l'utilisateur. Lors des tests, générez manuellement le paramètre $ row ou moquez l'objet dans UserFactory :: $ data_source. (Comment puis-je enregistrer les modifications apportées à l'enregistrement?)

    class UserFactory {
        static $data_source;
    
        public static function fetch( $username ) {
            $row = self::$data_source->get( [params] );
    
            $user = new User( $row );
            return $user;
        }
    }
    

J'ai Design Patterns et Clean Code ici à côté de moi, mais j'ai du mal à trouver des concepts applicables.


Réponses:


11

Donc, ce que vous voulez ramasser, ce sont les modèles d'architecture d'application d'entreprise de Martin Fowlers (il fournit également un catalogue sur son site Web ici ).

Il y décrit plusieurs modèles d'abstraction de l'accès aux données. La première approche que vous décrivez est Active Record . Votre deuxième approche est similaire à Table Data Gateway .

Une approche encore meilleure consiste à utiliser un O / RM pour supprimer la nécessité d'écrire le code d'accès aux données à la main. Je n'ai pas utilisé PHP depuis que nous étions inquiets pour Y2K, mais wikipedia a une liste d'options pour vous . Je ne sais pas si elles sont bonnes. Je peux cependant vous dire certaines choses à rechercher dans un O / RM:

  • Ignorance de la persistance : l'O / RM ne doit pas forcer vos objets métier à dériver d'une interface / classe spécifique afin de participer à la stratégie d'accès aux données.
  • Mappage des relations : vous devez être en mesure de mapper les relations entre vos objets (un client a des commandes, les commandes ont des éléments de campagne, les éléments de campagne ont un produit, etc.)
  • Mappage hiérarchique : vous devriez pouvoir mapper les hiérarchies de classes à la base de données.
  • Prise en charge de la syntaxe / critères de requête : vous devriez pouvoir créer une requête au moment de l'exécution en termes de vos objets et non en termes de base de données, et le O / RM doit traduire et exécuter la requête sur la base de données. Points supplémentaires si la requête est une chaîne fortement typée au lieu d'une chaîne.

Il y a d'autres facteurs à considérer, mais ceux-ci sont parmi les plus importants. J'espère que cela t'aides.


6

À mon humble avis, cela dépend de ce que vous voulez tester, si vous voulez tester votre logique métier, vous devez bloquer / simuler ( Martin Fowler ) votre accès aux données, donc votre première suggestion est un bon début. Cette question de stackoverflow donne un bel exemple C # (j'ai essayé de trouver des exemples PHP mais je n'en ai pas trouvé).

Si vous voulez tester l'accès aux données en soi, il ne s'agit plus de tests unitaires mais de tests d'intégration. Lisez ici pour quelques conseils généraux, cette question de stackoverflow contient également des liens intéressants.

Si vous souhaitez tester la logique des procédures stockées dans votre base de données, consultez xUnit TestPattern

J'espère que cela t'aides


2

Ce n'est pas nécessairement une réponse immédiatement utile, mais si vous êtes vraiment préoccupé par la testabilité de la base de données, vous devriez regarder comment cela se fait dans Ruby on Rails. Pour autant que je sache, personne n'a traité le sujet mieux ou plus intuitivement.


2
Ruby on Rails implémente le modèle d'enregistrement actif par défaut. Pourrait également fournir un lien: en.wikipedia.org/wiki/Active_record_pattern
Spoike

0

Je vous recommande de vérifier la solution Symfony Framework pour ce type de problème. Symfony est un framework php OO avec des tests fonctionnels.

Voici un lien , ils ont utilisé quelque chose comme ce à quoi vous pensez.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.