Les ORM sont-ils encore un anti-pattern ?
(github.com/getlago)- Les ORM sont souvent critiqués comme des « jouets pour startups », mais le véritable enjeu tient davantage à une mauvaise manière de les utiliser qu’aux ORM eux-mêmes
- Les graphes d’objets et les tables relationnelles sont deux modèles différents, ce qui crée un décalage de paradigme, mais cela ne suffit pas à faire des ORM un anti-pattern
- Le débat sur la violation de la SRP et de la SOC est pertinent, mais comme un ORM est à l’origine une abstraction qui relie deux modèles de données, il est difficile de le juger uniquement à l’aune d’une violation de principes
- Les problèmes de performance viennent plus souvent des schémas qui assemblent les données dans la logique du langage hôte que de l’ORM, et peuvent être réduits grâce aux fonctionnalités proches de SQL de l’ORM
- La raison principale pour laquelle Lago a remplacé des requêtes Active Record par du SQL brut relevait moins de la vitesse que de la visibilité et du débogage, et pour de grosses requêtes, passer au SQL brut peut être plus avantageux en pratique
Position de base face aux critiques des ORM
- Les ORM sont souvent attaqués comme un « anti-pattern », mais conclure que les ORM sont mauvais en soi relève de l’exagération
- Comme toute autre abstraction, un ORM n’est pas parfait et peut entraîner une certaine perte de visibilité ainsi qu’un coût de performance
- Lago a rencontré des problèmes alors qu’il dépendait de Active Record, l’ORM de Ruby on Rails, ce qui l’a amené à reconsidérer sa manière de s’appuyer sur un ORM
- La conclusion n’est pas qu’il faut abandonner les ORM, mais plutôt qu’il faut les traiter comme une abstraction avec des avantages et des inconvénients bien marqués
Différences entre modèle objet et base de données relationnelle
- Les objets manipulés par un ORM se rapprochent d’un graphe orienté pointant vers d’autres nœuds
- Les tables d’une base de données relationnelle se rapprochent d’un graphe non orienté, où les données sont reliées dans les deux sens via des clés partagées
- Un ORM peut tenter d’imiter un graphe non orienté, mais sa configuration et son fonctionnement ne sont pas toujours simples
- il peut manquer un tableau
Postsdans l’objetUser - les entités du tableau
Postspeuvent ne pas contenir de référence de retour vers le même objetUser - même si une référence de retour existe, elle peut pointer vers une copie de l’objet et non vers le même objet
- il peut manquer un tableau
- Par exemple, un ORM peut renvoyer les publications d’un utilisateur sous forme de tableau, sans inclure dans chaque publication de référence inverse vers l’utilisateur en tant qu’auteur
- Ce décalage constitue une bonne critique académique des ORM, mais dans l’exploitation réelle, les problèmes les plus importants apparaissent surtout dans des modes d’utilisation concrets
Débat autour de la SRP et de la SOC
-
Principe de responsabilité unique (SRP)
- Les ORM sont critiqués pour violer le principe de responsabilité unique (SRP)
- parce qu’ils peuvent amener une même classe ou couche à remplir plusieurs rôles à la fois
- exécution de la base de données et des transactions
- représentation des enregistrements
- définition des relations
- génération et exécution des migrations
- Mais comme le but même d’un ORM est de relier deux paradigmes de données différents, il est difficile de rejeter les ORM sur la seule base de certaines violations de principes
-
Séparation des préoccupations (SOC)
- Un ORM peut aussi brouiller le principe de séparation des préoccupations (SOC)
- La SOC est le principe selon lequel un composant d’infrastructure ne devrait porter qu’une seule préoccupation
- Comme un ORM déplace la gestion de la base de données du côté backend, on peut y voir une forme de violation de la SOC
- Cela dit, les composants d’infrastructure et les patterns de code actuels combinent parfois plusieurs rôles pour des raisons de performance, de latence et d’organisation du code
- agrégateurs CPU dans des bases de données OLAP
- backend-frontend edge
- monorepo
Les problèmes de performance viennent souvent davantage de l’usage que des ORM
- La critique selon laquelle les ORM seraient toujours inefficaces est dans l’ensemble fausse
- Beaucoup d’ORM peuvent fonctionner bien plus efficacement que ne l’imaginent les développeurs
- Le problème est que les ORM facilitent l’assemblage des données avec la logique du langage hôte comme JavaScript ou Ruby
- Dans l’exemple TypeORM, il est présenté comme un mauvais pattern de récupérer d’abord les auteurs d’une entreprise donnée, puis de relancer une requête pour les publications de chaque auteur, avant d’enregistrer chaque publication séparément
- Une meilleure approche consiste à construire une requête de mise à jour unique avec
createQueryBuilder()de TypeORM - Dans le refactoring SQL de facturation chez Lago, il n’y avait aucune différence de performance entre la version Active Record et la version SQL brut
- les fonctionnalités d’assemblage de données d’Active Record étaient déjà fortement utilisées, si bien que la requête initiale était déjà optimisée
- la réécriture en SQL brut visait davantage à améliorer la visibilité qu’à gagner en performance
Cas où un ORM peut réellement devenir lent
- Un ORM n’est pas toujours aussi efficace que du SQL brut, et dans certaines situations il peut être nettement inefficace
- Premier problème : l’ORM peut créer un important surcoût de calcul lorsqu’il transforme les résultats de requête en objets
- TypeORM est cité comme exemple de ce problème
- Deuxième problème : lorsqu’on parcourt des relations un-à-plusieurs ou plusieurs-à-plusieurs, on peut provoquer de nombreux allers-retours vers la base de données
- Ce pattern est appelé problème N+1
- à la requête initiale s’ajoutent N sous-requêtes
- dans l’exemple Prisma, une récupération imbriquée des utilisateurs, publications et commentaires peut déclencher une nouvelle requête vers la base pour chaque commentaire
- Le N+1 apparaît souvent avec les ORM, mais un data loader permet de ramener N+1 requêtes à 2 requêtes
- Une grande partie des problèmes courants des ORM peut être évitée si l’on exploite suffisamment les fonctionnalités de l’ORM
Le vrai problème : la visibilité et le débogage
- La plus grande faiblesse des ORM est la visibilité
- Un ORM est en pratique un générateur de requêtes, il n’est donc pas le transmetteur final des erreurs, sauf dans des cas évidents comme une erreur de type brut
- Lorsqu’une erreur SQL est renvoyée, l’ORM doit l’interpréter puis la retransmettre à l’utilisateur
- Active Record rencontrait des difficultés à ce niveau, et c’est aussi pour cette raison que Lago a refactoré ses requêtes de souscription de facturation
- Quand les résultats différaient des attentes, il fallait répéter le processus suivant
- vérifier la requête SQL rendue
- réexécuter cette requête SQL
- reporter l’erreur SQL dans les modifications Active Record
- Ces allers-retours affaiblissent l’objectif initial d’Active Record, qui était justement d’éviter d’interagir directement avec une base de données SQL
Jugement pratique
- Correctement utilisé, un ORM peut atteindre une efficacité proche de celle du SQL brut
- Beaucoup de problèmes surviennent lorsqu’on n’utilise pas les fonctionnalités proches de SQL de l’ORM et qu’on dépend trop de la structure logique du langage hôte
- Si de grosses requêtes compliquent le travail des développeurs et nuisent au débogage, passer à des requêtes SQL brutes peut être un bon investissement
- La plupart des ORM fournissent une fonctionnalité permettant d’exécuter des requêtes SQL depuis l’intérieur même de l’ORM
1 commentaires
Avis sur Hacker News
J’utilise des ORM depuis les débuts de Hibernate en Java, et j’ai toujours trouvé ça médiocre
L’avantage supposé de « pouvoir changer de base de données » ressemble aujourd’hui à une absurdité, et en pratique personne ne s’en sert ainsi
Dire qu’« on n’a pas besoin de connaître SQL » est faux aussi, et toute application non triviale qui dure finit par exiger des retouches sur des requêtes individuelles au niveau de la chaîne de caractères
La bonne approche pour la couche de données consiste à construire et interpoler les requêtes une par une en SQL sous forme de chaînes, et selon moi, plus on est proche de raw JDBC, mieux c’est
L’idée que les ORM soutiennent un « modèle de domaine » est aussi un mauvais argument, parce que ce modèle de domaine devient toujours un modèle de domaine anémique dont la logique est vide
Quand je pense au temps gâché avec les ORM, XML, les annotations, le débogage du SQL généré, etc., j’ai envie de pleurer
Les parties faciles sont déjà faciles, donc elles m’intéressent peu, et à l’inverse il m’est souvent arrivé que le travail devienne un million de fois plus dur parce qu’il fallait se battre contre l’ORM précisément au pire moment, quand les requêtes s’effondrent sous l’effet de l’échelle
Un query builder n’est pas exactement la même chose qu’un ORM, mais j’aime cet article, https://gajus.medium.com/stop-using-knex-js-and-earn-30-bf41..., et je suis devenu fan des technologies du type Slonik
Elles fournissent 90 % de ce que je veux — liaison automatique des résultats à des objets, vérification de types forte, etc. — tout en me laissant écrire du SQL tout à fait normal
Je ne comprends pas non plus l’idée selon laquelle SQL serait un langage mystérieusement difficile. Il est ancien et imparfait, mais il vaut mieux apprendre SQL que le langage de requête maison produit par les outils ORM
À l’époque, quand on formulait ce genre de critique, les autres développeurs vous regardaient de haut
Aujourd’hui encore, il y a beaucoup d’antipatterns parmi les outils et techniques qu’on est forcé d’utiliser comme développeur, et la triste réalité du secteur, c’est qu’une bonne partie des outils largement adoptés sont médiocres et encouragent les antipatterns
Dans l’industrie tech, il existe une petite minorité de développeurs et d’anciens développeurs très bien connectés qui détiennent le pouvoir de décision, et j’ai l’impression qu’ils sont médiocres
Il y a aussi des ORM dont le rapport avantages/inconvénients est correct, en particulier côté Python
L’ORM de Django est rustique et pas très performant, mais il est bien intégré, pratique, productif et agréable à utiliser
Peewee fournit un ORM dans un petit package, ce qui permet d’écrire avec plaisir de petits programmes quand on n’a pas besoin de fonctions extraordinaires et qu’on veut éviter les complications
SQLAlchemy demande davantage d’investissement, mais il est très flexible, génère un SQL propre et se comporte correctement
Il expose aussi un query builder de plus bas niveau pour les cas où l’on ne veut pas du paradigme orienté objet et où l’on souhaite exprimer en Python une abstraction de comportements SQL idiomatiques
Au final, cela devient une décision d’ingénierie classique basée sur le retour sur investissement
Je fais ça depuis plus de dix ans, et je n’ai jamais rencontré une requête que je n’aurais pas pu mieux gérer en lisant cinq minutes la documentation de Hibernate et en faisant ce qu’elle recommande dans ce cas
On dirait surtout que les fanboys de SQL, qui pensent que tous les développeurs doivent mémoriser les tables de logique à trois valeurs et des noms de fonctions à la COBOL, refusent de faire l’effort de lire la documentation de Hibernate
Les ORM sont faits pour les charges de travail OLTP, pas pour l’OLAP, et l’un des créateurs de Hibernate l’a déjà dit
Leur utilité principale, c’est simplement d’éviter d’écrire à la main de longues requêtes INSERT/UPDATE sujettes aux erreurs, et de mapper automatiquement les lignes SQL vers des objets
Si l’on passe à une approche raw, on finit par en réimplémenter une bonne partie, donc là encore ce n’est pas un jeu à somme nulle
Dans une application suffisamment complexe, on finit un jour par voir apparaître quelque chose comme un query builder, qui permet à plusieurs parties de l’application de composer ensemble des requêtes de façon différée
La structure évolue alors vers une composition par requêtes, au lieu d’assembler, filtrer et trier les données en mémoire
Un ORM est un outil qui facilite cela, mais il peut aussi vous tirer une balle dans le pied en rendant très facile la création involontaire de requêtes N+1
Comme pour tout outil, il faut évaluer les compromis à partir des cas d’usage réels, et manipuler directement des chaînes SQL n’est recommandé dans aucun cas
Pourtant, il y a toujours des gens qui ignorent ces différences et affirment de manière absolue que les ORM sont bons ou mauvais
Mieux vaut passer outre ce genre de posture polémique destinée à attirer l’attention, et se concentrer sur des discussions qui partent de l’idée suivante : « les ORM ont des avantages, mais il faut savoir dans quels cas ils sont valables, et veiller à ce que les problèmes d’usage ne l’emportent pas sur ces avantages »
Quand on a besoin de données, on passe par la couche d’accès aux données, et si elle ne fournit pas ce qu’il faut, on crée un nouveau repository, provider, ou autre élément conforme au pattern choisi
Que ce soit avec un ORM ou avec un composeur de requêtes maison, dès qu’une application devient assez complexe pour donner l’illusion que « c’est nécessaire », elle est déjà devenue trop complexe pour être utilisée de manière fiable
Au final, on finit par évaluer le builder au mauvais niveau d’abstraction, ou par parcourir les résultats sans voir qu’on est en train de créer des requêtes N+1
Un ORM n’est pas nécessaire
LINQ n’est pas exactement un ORM : quand on écrit une expression LINQ fortement typée, elle est transformée en arbre d’expressions, puis un fournisseur de requêtes la convertit en requête
Pendant le développement, je préfère la lisibilité de l’ORM dans les modèles, mais quand c’est nécessaire, je surveille de près N+1 et les autres inefficacités, puis j’optimise
La frontière du « quand c’est nécessaire » n’est pas claire, mais j’essaie de ne pas optimiser trop tôt
Sur un nouveau projet, je pars plutôt de la base de données, et avant de coder, je me fais une idée du modèle de données avec des factories, des seeders et des requêtes raw SQL
Les ORM comme Eloquent de Laravel offrent de bonnes méthodes pour résoudre les N+1 et faire du lazy loading, mais il y a toujours des compromis
Au lieu de permettre une composition différée des requêtes, elles vous laissent écrire directement la requête et génèrent au moment de la compilation le code correspondant
Par exemple, si vous écrivez une requête comme
getUser: SELECT * FROM users WHERE id = ?, elles génèrent une classeGetUserQueryet une méthode du typegetUser(id: String): GetUserQueryResult, et ce modèle me paraît bien meilleurLa principale raison pour laquelle je n’aime pas les ORM, c’est qu’ils tendent à traiter les moteurs SQL modernes comme des stockages de bits stupides de luxe
Les CTE, les jointures LATERAL et les clauses RETURNING peuvent grandement simplifier le traitement ou éliminer les risques d’incohérence des données, mais les ORM se limitent généralement à un simple mapping des tables et vues de base vers des objets prédéfinis
C’est encore pire quand l’ORM crée lui-même les tables
SQL est fondamentalement à la fois un outil d’extraction de données et un langage de transformation, mais les ORM ignorent presque totalement cet aspect, si bien que beaucoup de développeurs ne savent même pas que SQL contient autre chose que INSERT/SELECT/UPDATE/DELETE
Il y a les tables pivot, les requêtes temporelles, CUBE/ROLLUP, les fonctions de fenêtre, les fonctions retournant des ensembles, les vues matérialisées, les tables externes, le traitement JSON, le traitement des dates, les contraintes d’exclusion, des types comme les plages, intervalles et domaines, la sécurité au niveau des lignes, MERGE, etc.
C’est comme avoir un atelier d’outillage complet, mais quelqu’un ne vous tend qu’un marteau, un tournevis et une scie à métaux en essayant de vous convaincre que cela suffit, pendant que vous passez votre carrière sans même savoir qu’à quelques mètres se trouvent une scie sur table, une défonceuse, une ponceuse et un jeu de coins
Les ORM poussent surtout à penser en termes de simples requêtes CRUD, mais c’est probablement mieux ainsi, et les fonctionnalités avancées devraient être utilisées avec parcimonie
Mais même quand j’en utilise une, j’essaie volontairement de ne me servir que d’un très petit sous-ensemble des fonctionnalités de la DB
En effet, je vois le « code » comme une zone que je peux contrôler, tandis que la « base de données » est une zone risquée et difficile d’accès, où les erreurs n’apparaissent souvent que plus tard, dans des choses comme des tests d’intégration lents
La logique qui se passe dans la DB échappe au périmètre des tests de bas niveau, ce qui me met mal à l’aise, et je pense que je n’utiliserais probablement même pas de requêtes
select-from-selectJe laisserais volontiers de côté la plus grande partie de l’atelier
On passe l’essentiel de son temps à inventer des contournements élaborés pour réimplémenter des protections de base de l’intégrité des données
Construire sa propre base de données peut être amusant pour apprendre, mais pas pour une application de production
ActiveRecord m’a toujours semblé agréable
Il y a quelques cas d’exception, mais il vise bien le point d’équilibre 80/20, permet de revenir au SQL si besoin, et ses hooks de cycle de vie sont excellents pour organiser la logique métier tout en restant faciles à comprendre
Les ORM pragmatiques qui ne cachent pas tout derrière des « bundles » et n’introduisent pas leur propre langage de requête sont une bonne chose
Ce sont les ORM qui essaient de « résoudre » complètement le problème des ORM qui deviennent difficiles à utiliser
C’est ainsi qu’un ORM devrait être conçu
En revanche, pour bien l’utiliser, il faut avoir de bonnes bases en SQL
Les problèmes apparaissent quand les gens n’apprennent pas SQL et ne comprennent ni les requêtes générées par AR ni ses limites
Le postulat de départ est faux. Un ORM n’a jamais été en soi une « mauvaise idée »
Il existe des ORM avec lesquels il est affreux de travailler, mais cela ne veut pas dire que tout le genre est une mauvaise idée
J’utilise SQLAlchemy avec plaisir depuis des années précisément parce qu’il n’essaie pas de réinventer le concept même de SQL
À la place, il fournit une couche pratique pour construire et transmettre des requêtes, tout en gérant correctement les petits détails pour éviter de devoir les bricoler soi-même
En apprenant Rust récemment, écrire à la main tout le code boilerplate pour gérer des CRUD simples m’a semblé pénible et comme une perte de temps
L’ORM de SQLAlchemy peut être un peu gênant sur des requêtes plus complexes ou à optimiser, mais dans ces cas-là on peut toujours redescendre directement en SQL
Comme pour tout, il y a des contextes où cela convient et d’autres où non, et une technologie peut facilement être surutilisée ou mal utilisée
Par exemple, un ORM comme Entity Framework en .NET peut être un atout majeur, en particulier quand on travaille en approche database-first
Si l’on a une base avec des centaines de tables et des relations de clés étrangères correctement définies, un ORM aide à naviguer dans un schéma complexe et fournit des vérifications à la compilation lors des changements
Le SQL embarqué est une arme à double tranchant qui peut sembler offrir des avantages de performance, mais il est extrêmement difficile de maintenir du SQL verbeux codé en dur, surtout avec des jointures
Je ne parle pas d’un cas avec 5 à 10 tables, mais de centaines
Je ne cherche à convaincre personne, mais il ne faut pas croire aveuglément tout ce qu’on lit sur Internet à propos des bonnes pratiques
Les gens peuvent parler de choses complètement différentes, et quel que soit l’outil choisi, il y aura toujours des développeurs médiocres
Si l’on n’utilise ni ORM ni autre interface de base de données, on finit par en écrire et en maintenir une soi-même pour des choses comme le CRUD
Et elle aura de fortes chances de contenir des bugs bizarres, des cas limites et des failles de sécurité
Il y a aussi un problème à enseigner à l’université des principes comme SOLID comme s’il s’agissait de principes universels de conception logicielle
Dans le monde académique, cela se tient parce que des contraintes comme le temps, la maintenabilité, l’argent ou l’effort comptent moins, mais quand de jeunes diplômés arrivent en entreprise, le choc peut être très mauvais
Ils ont pris l’habitude de passer leurs journées à tondre le yak et à réinventer la roue à la recherche de la solution « parfaite »
Sans suffisamment de seniors ou de leads compétents pour canaliser cela, on obtient des produits très intéressants, des dépassements de budget, des incendies majeurs, ou une combinaison de tout ça
C’est encore pire quand quelque chose conçu par et pour le monde académique est lâché dans le grand public
Un bon/mauvais exemple typique est OpenStack : il a tellement de poignées, de réglages et de composants modularisés à l’extrême pour prendre en charge l’environnement particulier du CERN et de centaines d’universités, mais c’est tellement byzantin qu’il est presque impossible de démarrer avec
Les ORM ne permettent pas de changer de base de données sans effort, n’éliminent pas le besoin d’apprendre et de comprendre le SQL qu’ils génèrent, et ne rendent pas un schéma propre comme par magie
Malgré cela, on les utilise parce qu’ils constituent de toute façon une abstraction standard qu’il faudrait sinon dupliquer
Ils permettent de mettre en cache l’accès à la base, ce qui devient étonnamment difficile à grande échelle avec du SQL écrit à la main
Ils s’accompagnent d’outils standardisés et de bonnes pratiques qui peuvent rendre des problèmes comme le N+1 négligeables
Les principaux problèmes des ORM sont les mauvaises attentes et les mauvais ORM
Si vous voulez comprendre la valeur d’un ORM, ouvrez un projet écrit sans ORM et essayez d’y modifier n’importe quoi
Voir https://news.ycombinator.com/item?id=36498583
Rien d’utile n’avançait, ou cela prenait 20 à 100 fois plus de temps qu’une approche rapide et sale
Le pire cas a été une équipe de designers HTML expérimentés à qui l’on a imposé d’apprendre la programmation fonctionnelle
L’assistant magique de configuration backend était une merveille d’ingénierie moderne et de conception élégante, mais 10 personnes ont mis un an à le construire
L’argent du capital-risque rend les gens bizarres
Le langage SQL est très complexe, et construire un query builder complet, correct et riche en fonctionnalités est tout sauf trivial
Et cela même si l’on laisse de côté toute la partie mapping relationnel proprement dite
Pour SQL, c’est typiquement un cas où il faut « juste programmer cette fichue chose directement »
Il n’y a pas beaucoup d’intérêt à apprendre SQL et une bibliothèque ORM ; il vaut mieux apprendre et utiliser SQL directement
L’accès à la base de données est probablement une activité fondamentale que l’on fera pendant toute sa carrière, donc le mieux est d’apprendre directement la vraie compétence
C’est similaire avec CSS : mieux vaut apprendre et utiliser CSS que d’apprendre une bibliothèque CSS
En fait, c’est pareil pour presque tous les aspects du développement frontend ; au lieu d’une « bibliothèque de formulaires », on peut manipuler directement l’API de formulaires du navigateur
Personnellement, j’ai trouvé SQL bien plus facile à apprendre que n’importe quel ORM
Il ne faut pas gaspiller du temps à apprendre la mauvaise chose
C’est pareil pour CSS : si on connaît CSS, on est beaucoup plus souple et on comprend bien mieux ce qu’on choisit quand on prend une bibliothèque par commodité
À travers les mainframes, le desktop, le client/serveur, le web et les nombreux langages utilisés sur ces plateformes, SQL a toujours été le fil conducteur
Je suis totalement d’accord sur le fait qu’un développeur qui comprend bien la couche de données et ce qui se passe en dessous est un développeur plus solide
Si l’on compte passer du temps à apprendre les bizarreries d’un ORM, la question classique est : pourquoi ne pas investir ce temps dans l’apprentissage de SQL ?
Le rendement cumulé de l’expérience SQL a de fortes chances d’avoir plus de valeur dans 10 à 15 ans qu’un ORM lié à une plateforme ou à un langage particulier
Il y a des raisons d’apprendre et d’utiliser un ORM, mais il ne faut pas pencher vers l’ORM uniquement parce qu’on ne veut pas apprendre SQL
Comme ça, on sait ce qu’on paie en contrepartie de cette abstraction. Bien sûr, c’est différent s’il s’agit d’une « abstraction sans coût »
Mais aujourd’hui, j’utilise
cruddeazer, qu’on peut classer comme un ORM, à cause du marshalling/unmarshalling avec les types GoLa bibliothèque standard Go
sqlest trop basique, donc il faut pratiquement écrire soi-même le marshalling/unmarshalling des objets, et c’est vraiment fastidieuxSi j’utilisais un ORM aujourd’hui, ce serait uniquement pour ça
J’aime les micro-ORM « intermédiaires » comme Dapper ou Diesel
On écrit les requêtes en SQL, tout en bénéficiant d’un typage fort et du mapping automatique du jeu de résultats vers des objets
On gagne à la fois en productivité et on conserve un « vrai » langage de requête complet
J’en suis aussi venu à apprécier l’usage des object mappers uniquement pour les requêtes en lecture seule
Les mises à jour sont faites via le command pattern, c’est-à-dire avec des procédures stockées, que l’on peut mapper pour qu’elles ressemblent à des méthodes natives
Les développeurs doivent arrêter de faire comme si SQL n’existait pas et simplement l’accepter
Eloquent abstrait suffisamment ce travail pénible pour qu’on puisse se concentrer sur la logique
Je suis en train de réécrire une « vieille » application PHP composée uniquement de tableaux et de requêtes vers une structure utilisant des modèles et Eloquent, et j’ai l’impression que ça change complètement la donne
À l’époque où j’utilisais SQLite sur .NET, j’avais aussi créé une bibliothèque wrapper dans cette veine : https://github.com/zmj/sqlite-fast
Ce fil montre bien la domination de l’ORM dans les esprits
Dans presque tous les commentaires, l’alternative implicite à l’ORM, c’est du SQL brut sous forme de littéraux de chaîne dans le code de l’application
Pourtant, il existait déjà il y a 6 ans des outils permettant d’utiliser SQL comme un langage à part entière et de générer des wrappers exposant les requêtes comme des méthodes dans l’application
Des outils comme queryfirst, pgtyped, pugsql ou sqlc
C’était un changement de paradigme, ou du moins cela aurait pu l’être, et il apparaît clairement que c’est une manière de travailler supérieure, mais l’ORM et cette discussion immuable monopolisent toute l’attention et maintiennent cela à la marge
SQL est un langage, et même un langage de très haut niveau
Essayer de bricoler du SQL depuis un langage de niveau plus bas, c’est un cas d’école du « quand on a un marteau, tout ressemble à un clou »
Par exemple, si l’on code en assembleur, donc dans un langage de bas niveau, tout en interagissant avec un gros système dont la documentation dit que les entrées ne peuvent être exprimées qu’en JavaScript, on a le choix
Soit on prend une bibliothèque ésotérique qui permet de bricoler quelque chose en pur assembleur sans avoir à committer de fichier
xxx.jsdans le dépôt, soit on utilise simplement la puissance de ce langage de haut niveau et on l’exprime dans un fichier.jsOn obtient une source unique de vérité pour les requêtes SQL utilisées, et comme ce qu’on écrit et maintient réellement, ce sont les requêtes elles-mêmes, il devient aussi plus facile de faire des optimisations comme créer un nouvel index
Mettre une abstraction au-dessus de chaînes SQL brutes est très utile, mais faire semblant que les relations sont des objets est une manière inutilement embrouillée de faire les choses
TopLink aussi, probablement
C’est ainsi qu’ils géraient le mapping entre procédures stockées et entités locales