PHP

Mon compte-rendu de la soirée Afup « Accès aux données et ORM »

Flattr this!

Il y a plus de deux semaines se déroulait la soirée Afup à La Cantine à propos des bases de données et des ORM avec PHP. Mais je ne fais mon "compte-rendu" que maintenant, désolé, pas eu le temps avant... D'ailleurs c'est plutôt une mise à plat de mes notes, ce qui risque de vous sembler parfois chaotique.

Les intervenants étaient Mickael Perraud, François Zaninotto et Antoine Hérault.

Pour rappel, ORM, signifie Object Relational Mapping et permet de manipuler des objets plutôt que des enregistrements en base. Un SGBD est un Système de Gestion de Base de Données.

PHP 4

Mickael Perraud a commencé par un historique de l'accès aux données avec PHP. Rappelant nos débuts à nombreux d'entre nous sous PHP 4 avec les méthodes mysql_*. Oui, ces méthodes où vous prépariez des chaînes de requêtes SQL, que vous concaténiez et priez pour que ça ne se crashe pas, ou il fallait se méfier de tout et surtout où un développement n'était pas portable d'un SGBD à un autre.

L'arrivée des PDO

Puis il a abordé l'arrivée des PDO. Ces drivers qui ont permis de rendre un peu plus portable nos codes. Avec le défaut qu'ils ne réécrivait pas les requêtes SQL, laissant à la charge du développeur la gestion des risques tels que les injections SQL. Et même si ils ont bien amélioré la portabilité des applications, ils n'émulent pas les différences entre les SGBD restant de fait un poil limité. Typiquement, la notion de LIMIT ou encore tous les types de jointure ne sont pas présents dans tous les SGBD, les PDO n'y remédient pas. Ce qui impliquent du coup encore un minimum de développement pour passer d'un SGBD à un autre.

Zend_DB

Il a ensuite lancé le sujet du composant Zend_DB qui est une sorte de surcharge des PDO et aussi un composant du Zend Framework.

Zend_DB_Adapter

Composant du Zend Framework lié à Zend_DB, Adapter est une surcharge de PDO et n'est pas un ORM.

Zend_Db_Adapter permet l'exécution de requêtes préparées, fournit une abstraction suffisante pour être considérée comme un DML (Data Manipulation Language) permettant ainsi notamment les opérations classiques du "CRUD" (Create - Read - Update - Delete).

Il propose également certains pans de la gestion des schemas, on y retrouve notamment la possibilité de lister les tables. Adapter gère les transactions et propose la clause LIMIT, qui n'est pas proposé par tous les SGBD.

Doctrine DBAL

Cette partie du framework Doctrine (je reviens plus tard dessus) est destinée à l'abstraction des bases de données. Pour info, DBAL signifie DataBase Abstraction Layer. Elle est constituée de plusieurs éléments :

  • doctrine\DBAL\Driver : surcouche de PDO et autres pilotes
  • doctrine\DBAL\Platform : abstraction de génération de requêtes
  • doctrine\DBAL\Schema : abstraction des schemas
  • doctrine\DBAL\Type : abstraction des types de données

Il gère notamment les transactions imbriquées ce qui peut se révéler particulièrement pratique et grâce aux sous-composants Schema et Type permet donc de gérer complètement vos schemas à un niveau non atteint par Zend_Db.

Zend_DB 2.0

A été évoqué cette seconde version du composant pendant la conférence. Pas de date de sortie (j'avoue être complètement à la masse sur l'avancement de Zend Framework, même si je l'utilise quotidiennement).

Il contiendra plusieurs composants :

  • Adapter : permettra l'utilisation de plugins et supprimera le SQL pur
  • Query : proposera toujours l'abstraction des requêtes DML, DDL et DCL
  • ResultSet : modélisation des résultats
  • MetaData : gestion des schemas

L'essentiel des nouveautés seront donc sur les requêtes DDL et DCL ainsi que la gestion des schemas.

En savoir plus

Pour ceux pour qui les notions de DML, DDL ou DCL restent flous, je vous propose de jeter un oeil ici : http://www.orafaq.com/faq/what_are_the_difference_between_ddl_dml_and_dcl_commands

Propel

François Zaninotto a ensuite pris le relais pour nous parler de Propel qui est un ORM et fonctionne sur le principe d'ActiveRecord.

ActiveRecord est un design pattern défini par Martin Fowler qui marche sur un principe simple : Chaque description de table correspond à une définition de classe, ainsi chaque tuple (un enregistrement en base) est un objet dans le code.

En savoir plus

Pour ceux qui s'intéressent aux travaux de Martin Fowler, il a écrit un livre chaudement recommandé par François : Patterns of Enterprise Application Architecture.

BookQuery

Ce composant qui est hérité de BaseBookQuery propose une méthode "filter" qui remplace la clause WHERE du SQL afin de mieux gérer les types.

Benchmarking

François a ensuite parlé un peu performances. Suggérant que certes PDO est plus rapide que Propel mais la différence est négligeable par rapport aux 2 versions de Doctrine comparées. Il a par ailleurs mis en place un test qu'il vous propose ici : http://code.google.com/p/php-orm-benchmark/

Doctrine

Antoine Hérault a pris le relais pour nous présenter Doctrine. Dans sa première version, celui-ci, comme Propel était une implémentation du pattern ActiveRecord. En décembre 2010, avec sa version 2, Doctrine reprend le principe du DataMapper, un autre pattern proposé par Martin Fowler (voir Patterns of Enterprise Application Architecture).

Je trouve que ça se rapproche beaucoup d'ailleurs de Hibernate (depuis la mise en place de JPA) avec ses annotations pour mapper les classes avec les tables du schema. Méthode dont je ne suis pas fan, trop compliquée à maintenir par rapport à ActiveQuery, mais ça n'est que mon avis.

Il est basé sur deux concepts fondamentaux :

  • Entity : l'objet métier, il n'a pas conscience de sa persistance
  • EntityManager, c'est le point d'accès aux fonctions de l'ORM

On y sépare donc clairement le fonctionnement de la persistance et les données à persister.

Doctrine Query Language

Comme son homologue pour Java (HQL pour Hibernate), Doctrine propose un langage de requêtage. Un point de plus qui pour moi est une erreur. Le principe d'abstraire les bases, c'est de se passer de l'écriture de requêtes SQL. Alors là ok, on écrit plus de requêtes SQL mais des sortes de requêtes objet, ce qui n'est pour moi qu'avoir déplacé le problème.

Cache

Doctrine propose différents niveaux de cache, ce qui n'est pas le cas de Propel. Sur des requêtes uniques, le benchmark de François montre bien que Doctrine est à la bourre, mais sur des requêtes répétées... Peut-être qu'un niveau de cache ne serait pas de trop, on connait tous un miimum l'utilité du cache (et aussi leurs inconvénients).

Bon voilà, j'ai fini ce billet, j'espère que ce n'est pas trop le bazar dans vos têtes après lecture. Je rappelle que ce n'est qu'un portage de mes notes pris à la va-vite pendant la conférence. Parfois, j'ai même dû piller par dessus l'épaule de l'ami m0hda.

Flattr this!

A propos de Mathieu

Ingénieur développeur web dans la vente par correspondance B2B, adepte de nouvelles technologies et d'innovation. Vous pouvez aussi me retrouver sur Twitter @mathrobin
Cette entrée a été publiée dans PHP, avec comme mot(s)-clef(s) , , , , , , , , , , , , , , , , , , , , . Vous pouvez la mettre en favoris avec ce permalien.
  • http://blog.mageekbox.net mageekguy

    J’avoue être plus que septique par rapport à cette volonté de s’abstraire du SGBD sous-jacent.
    En effet, ça revient à demander à un pilote de course automobile Ferrari de conduire sa voiture comme une 2 CV en espérant que ça sera plus simple pour lui de piloter une Lamborghini si d’aventure il change de crémerie.
    En effet, les outils comme doctrine ou propel ne permettent pas, par définition, d’exploiter la totalité de la puissance du SGBD sous-jacent, car bien souvent, cette puissance réside dans les spécificités du SGBD.
    Le développeurs va donc être confronté à des problèmes de performances, et des choses qui devraient être pour lui relativement simples vont devenir compliquées, car il ne pourra pas exploiter les outils ad hoc du SGBD pour faire le travail.
    Pour reprendre l’analogie du pilote de course, ça revient à demander à ce dernier de gagner des courses avec sa Ferrari en la conduisant à 70 km/h sans assistance électronique et avec du gasoil dans le réservoir.
    Un peu ambitieux, d’autant que ces contraintes sont imposées parce qu’un jour, peut être, éventuellement, il est probable, voir possible, mais c’est pas certain, qu’on utilise Oracle à la place de Mysql…
    Ok.
    Et le jour ou on passe à Oracle, il apportera quoi de plus que Mysql ?
    Ma question peut sembler stupide, mais si on réfléchit deux secondes, l’ORM imposera forcément son nivellement par le bas (en terme fonctionnel) à Oracle, puisque le but est de pouvoir migrer d’un SGBD à l’autre sans modifier le code (ce qui est je pense une pure chimère, mais c’est un autre débat).
    Et si Mysql est déjà « bridé » par l’ORM, le bridage sera encore pire dans le cas d’Oracle, puisque ce dernier est censé être bien plus puissant et riche fonctionnement.
    Franchement, migré de Mysql à Oracle juste pour bénéficier uniquement d’un moteur de requêtes SQL potentiellement plus performant et d’une architecture des données hypothétiquement plus efficace, ça vaut vraiment le coup ?
    Il est déjà légitime de se demander si ne pas utiliser les triggers, les procédures sotckées, etc, de Mysql juste pour pouvoir passer hypothétiquement d’un SGBD à l’autre n’est pas une erreur, je pense donc qu’il est encore plus intelligent de se demander si investir dans Oracle pour juste l’utiliser à 10% (en étant gentil) n’est pas également la dernière des conneries à faire.
    Parce qu’en règle générale, une migration de ce genre est envisagée/effectuée à cause d’un problème de performance.
    Mais… ne serait-ce pas l’ORM, le problème, dans ce cas, qui bride le SGBD, et non le SGBD ?
    La question mérite d’être posée et d’avoir une réponse claire et précise.
    Pour conclure, je ne nie pas l’intérêt d’Active Record.
    Je l’ai implémenté et utilisé avec bonheur il y a10 ans alors que le concept n’avait pas encore de nom.
    Ça permet de manipuler vite, bien et de manière confortable et sécurisé un enregistrement dans une table.
    Mais je pense que les ORM vont bien trop loin en voulant s’abstraire totalement du SGBD et que le prix à payer pour leur mise en œuvre est bien trop élevé, surtout pour essayer de parer à une situation (la migration vers un autre SGBD) qui n’arrivera probablement jamais.

  • http://www.mathieurobin.com/ Mathieu

    C’est vrai que l’argument premier pour un ORM est la portabilité et je te rejoins pour dire qu’effectivement, en 6 ans de dev, je n’ai jamais eu l’occasion de faire migrer de SGBD mes applications. Ton point de vue/avis découle de la pure logique, comme d’habitude, je lis dans tes propos un avis éclairé et réfléchi (et vu le commentaire de @m0hda sur Twitter, je ne suis pas le seul).
    Mais comme tu l’as aussi suggéré, l’usage d’ActiveRecord permet de manipuler de façon très confortable les données et de façon sécurisée. J’apprécie aussi dedans le fait de pouvoir débugger plus facilement mes requêtes que via une requête SQL de base.
    Etant utilisateur d’une version « personnalisée » de Zend_DB, je n’ai pas du tout envie de changer pour autre chose ou revenir à la méthode plus classique même si du coup effectivement, j’y perds bien des avantages de mon SGBD.
    Tu me mets un gros doute sur ma façon de voir les choses ceci dit du coup.
    Très bon l’exemple du pilote automobile, très représentatif de la situation.

  • m0hda

    Je suis totalement d’accord sur le fait que le changement de SGBD n’est pas une raison pour mettre en place un ORM puisque dans l’absolu il y a peu de chance que le changement de SGBD soit pertinent parce qu’en passant par l’ORM on bride les nouvelles fonctionnalités apportés par le SGBD remplaçant (comme mageekguy le dit si bien)

    Par contre,je pense que l’utilité de l’ORM est dans le déploiement de code « générique » qui pour être déployer dans un maximum de cas sans tenir compte du SGBD. Donc en sacrifiant de la performance,on s’affranchit des contraintes matérielles, après je pense que tout dépend des priorités du client.
    Un site d’enchère ultra réactif en terme de rafraîchissement sera toujours plus apprécié « techniquement » qu’un concurrent sous Symfony/Doctrine mais un site vitrine par exemple n’as pas besoin d’une grande vitesse de rafraîchissement (même si on reste tout de même dans la limite du raisonnable en utilisant un ORM)

  • Syndrael

    Je rejoins un peu l’avis de mageekguy.. Hélas on a rarement changé de SGDB, et bien que cela puisse arriver, on pense à une série de tests, et pourquoi pas de refonte de base ou de requete..
    Donc le changement de SGBD n’est à mon sens que très marginal.
    l’ORM n’est-il pas une lubbie de développeur qui veut se débarrasser de la sacro-sainte requete en string ?
    Quelqu’un connait il finalement un « ORM light » qui conserve les avantages de MySQL ? ActiveRecord que je n’ai pas eu l’occasion de regarder ??
    S.

  • http://www.mathieurobin.com/ Mathieu

    Attention, Active Record n’est pas un ORM, c’est un design pattern qui a inspiré des ORM tels que Propel ou Doctrine 1. En fait l’ORM n’aurait un intérêt un intérêt réel que si dédié spécifiquement à un SGBD et du coup pouvant en exploiter à fond les capacités. On y perd certes la portabilité (négligeable, et encore plus négligeable si l’application est correctement architecturée) mais on y gagnerait en performances.
    Tu exprimes bien l’une des raisons de pourquoi j’utilise un ORM, la construction de la requête sous forme de string plutôt que via un objet comme avec Zend_Db_Select

  • http://www.geek-directeur-technique.com Amaury

    J’étais à cette soirée, et j’ai passé pas mal de temps (jusqu’à minuit !) à discuter avec le monde présent, dont François Zaninotto et Antoine Hérault. Comme Frédéric, j’ai une aversion assez profonde envers les ORM. L’abstraction qu’ils apportent se justifie − à mon avis − dans le cas des SSII ou des web agency qui doivent produire rapidement des sites sans réelles contraintes de performance. Un peu comme l’utilisation d’un framework très dirigiste, cela permet de gagner du temps de développement, tant que l’on reste sur des besoins basiques. Et dans cette vision, les ActiveQuery de Propel sont plutôt bien pensées.

    Mais tout cela a forcément un coût. En fonctionnalités, pour commencer : Les requêtes très complexes, à base d’UNION, de GROUP BY… HAVING, sont parfois possibles mais pas simples à manipuler. Certains requêtes sont mêmes impossibles il me semble, comme les insertions avec ON DUPLICATE KEY.
    Ensuite, en terme de performances, il ne faut pas s’attendre à quelque chose de satisfaisant quand on commence à avoir de grosses volumétries. Il est d’ailleurs amusant de voir que les ORM se mesurent majoritairement les uns par rapport aux autres, plutôt que de se mesurer à l’utilisation de requêtes optimisées sans ORM.

    Un lien intéressant à ce sujet : http://highscalability.com/blog/2011/5/2/stack-overflow-makes-slow-pages-100x-faster-by-simple-sql-tu.html
    Eh oui, dans la vraie vie, quand un site rencontre du succès, une des premières choses à faire, c’est de virer l’ORM.

    Je pense détailler bientôt mes idées à ce sujet sur mon blog, j’y réfléchis depuis longtemps.

  • https://plus.google.com/116975024782869852103/about Félix Bellanger

    Qu’on se le dise une fois pour toute: « ORMs are slow », cela est d’autant plus vrai en PHP sans vouloir cracher sur le langage. Deuxièmement j’ai vu dans les commentaires qu’Active Record était un design pattern ce qui est vrai mais il existe un ORM qui s’appelle ActiveRecord et qui est l’ORM par défaut sous RoR.

    Maintenant concernant les ORMs cités dans l’article je ne retiendrais que Propel et Doctrine (et ce qui en découle). Pourquoi? Tout simplement à cause du marché PHP actuel. En effet, on ne va pas se mentir, étant lead developer dans une start-up et côtoyant pas mal de développeurs, la plupart des développeurs PHP que je connais et qui doivent travailler sur un projet tendent à s’orienter sur Symfony (okay, pas tout le monde il y en a qui prototype sur du Kohana ou du CodeIgniter mais bon) qui, par défaut (du moins en version 1.4) embarque les 2 ORMs que j’ai retenus et qui en font potentiellement les leaders actuels. Le problème est donc lequel choisir. Si on se réfère à la documentation il est claire que cette dernière prône l’utilisation de Doctrine, puis après en regardant de plus près il y a la communauté qui joue, du fait de la documentation je suppose. Nous sommes donc actuellement, selon moi (et j’ai peut-être tord), dans une situation ou Symfony 1.4/Doctrine 1.2 dominent, même si cela risque de fortement changer dans les 6 à 12 mois avec l’arrivée récente de Symfony 2. Ceci dit, je parle je parle et je m’écarte du sujet…

    La vraie question qui se pose et qui semble être débattue ici est: « Est-ce que je dois utiliser un ORM pour accéder à mes données et si oui lequel…? ». Concernant la première partie j’ai envie de vous dire ça dépend, si vous avez besoin de gagner beaucoup temps et que vous n’êtes pas très regardant en terme de vitesse ou si vous avez un stack de type MVC cela semble assez justifié, il faut cela dit rester prudent et éventuellement faire du benchmark et le support en cas de problème sur l’ORM. Pour reprendre Propel et Doctrine on voit clairement que la communauté Doctrine semble être beaucoup plus active que celle de Propel ceci dit Doctrine 2 est souvent critiqué pour sa lenteur et Propel 1.6 nouvellement sorti pour sa rapidité mais aucun benchmarks comparatif pour justifier ces propos au moment ou j’écris ce commentaire. Concernant la seconde partie et le choix de l’ORM, il y a l’idée du changement hypothétique du système de SGBD, ce qui bien sur n’arrive jamais (ou rarement) cela dit ce qui est beaucoup plus fréquent c’est d’avoir une architecture qui met en jeu plusieurs SGBD, ce qui se fait de plus en plus à l’heure actuelle pour la simple raison que tel ou tel SGBD est plus apte a faire certaines taches que d’autres. C’est là que Doctrine fait assez bien les choses en proposant aujourd’hui 2 choses un ORM pour manipuler des SGBD de type SQL et un ODM pour manipuler du NoSQL (MongoDB seulement a l’heure actuelle) et ce avec des APIs relativement similaires. En passant outre les performances cela reste un atout relativement riche par rapport à Propel qui ne propose que la manipulation de SGBD de type SQL, ce qui est suffisant bien sur pour la plupart des applications mais si l’on commence à s’écarter un peu des standards on peut vite se retrouver avec 2 ORMs ce qui n’est pas forcément très pertinent, surtout en PHP. Ce qui m’amène un peu à sortir du droit chemin et regarder les alternatives sur les autres langages.

    Prenons Ruby qui est très en vogue depuis 6 mois avec l’arrivée de Rails 3. Par défaut, on a comme je le disais ActiveRecord pour tout ce qui est SQL, cela dit vu les critiques la plupart du temps celui-ci est souvent remplacé par une alternative comme Sequel ou DataMapper qui sont beaucoup plus lite et performants selon moi. Cependant, avec l’explosion du NoSQL on voit de plus en plus de stack RoR qui se fait avec MongoMapper ou MongoID. Concernant les performances on remarque vite que sous Ruby les ORMs/ODMs sont déjà bien plus rapide qu’en PHP et sont souvent (mais pas tout le temps) nécessaires car peu de monde s’amuse a faire du requêtes SQL pures sauf cas avancés (UNION, …) comme le citait Amaury dans le cas du PHP.

    Orientons nous maintenant sur du bleeding-edge avec Node.JS, stack récent, premier commits il y a environ un an. On a donc peu de choix, ce qui n’est pas le cas sur les stacks anciens. En effet, la plupart du temps on se retrouve a faire des requêtes à la main via les modules natifs en fonction du SGBD car pas d’ORM disponibles, cela dit ce n’est pas forcément gênant puisque ça sort du JSON par défaut qui est de plus en plus un standard et donc ça facilite les manipulations. On peut toutefois citer Sequelize pour MySQL qui est un WIP et qui après mes demandes supporte enfin les clés primaires naturelles et permet de faire du mapping efficacement et Mongoose pour MongoDB qui lui est assez flexible. Concernant les perfs, j’vais pas dire grand chose parce que Node.js c’est complètement à part par rapport à du PHP ou du Ruby.

    On peut donc dire qu’il existe 10000 moyens différent d’accéder à des données avec un ORM ou non et dans différents langages. Selon moi quand l’architecture dépasse une certaine taille, il est toujours plus simple d’utiliser Active Record comme design pattern et surtout de ne pas réinventer la roue donc utiliser un ORM déjà existant. J’espère avoir donné un apercu global concernant le choix d’un ORM en fonction du stack même si en définitive cela reste un choix personnel ou du moins un choix du chef de projet. Si vous avez des retours, remarques ou si vous constatez que j’aurais peut-être dit une bêtise, n’hésitez pas à réagir.

  • http://www.mathieurobin.com/ Mathieu

    Intéressant ton point de vue, d’autant qu’il est plutôt complet. Même si pour moi, il manque un gros acteur des accès aux bases de données dans tes considérations : Zend_DB.
    Alors certes, Zend_DB n’est pas tout à fait un ORM puisqu’il ne fait pas de persistance, cependant, j’ose croire qu’il occupe suffisamment le marché pour ne pas être négligé.
    Au delà de cette considération, je suis d’accord avec toi (et avec les autres participants à la discussion visiblement) que les ORM sont souvent critiquables sur les questions de performance et sur l’argument fallacieux du changement de SGBD.
    Cependant, et ça reste mon point de vue, je n’aime pas trop la méthode de mapping comme le font Doctrine et autre ORM basé sur le pattern DataMapping. A mon sens ça pollue le code, notamment avec des annotations qui n’en sont pas vraiment. Peut-être que c’est mieux présenter sous Doctrine 2, mais mon expérience passée sur Hibernate (près d’un an en usage professionnel encadré par un architecte expérimenté) m’a clairement refroidi sur ce pattern.

Articles liés