7 points par GN⁺ 2023-06-28 | 1 commentaires | Partager sur WhatsApp
  • 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 Posts dans l’objet User
    • les entités du tableau Posts peuvent ne pas contenir de référence de retour vers le même objet User
    • 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
  • 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

 
GN⁺ 2023-06-28
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

    • Tout à fait d’accord. Je dirais que les ORM « rendent les parties faciles un peu plus faciles, mais rendent les parties difficiles vraiment difficiles »
      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
    • Dès la première fois que j’en ai utilisé il y a longtemps, je détestais les ORM pour les mêmes raisons et je les considérais comme un antipattern
      À 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
    • Tu as simplement commencé avec l’un des pires ORM existants
      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
    • Dire qu’« il faut ajuster au niveau de la chaîne de caractères » est absurde d’après mon expérience
      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
    • Personne d’un tant soit peu réfléchi n’a jamais présenté le fait de « ne pas avoir besoin de connaître SQL » comme un avantage des ORM
      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

    • L’expérience avec les ORM peut varier de façon extrême selon le langage utilisé, le niveau d’intégration et le type de travail
      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 »
    • Je ne considère pas comme allant de soi qu’une application suffisamment complexe ait besoin d’un query builder, et je ne l’accepte pas dans mes applications
      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
    • J’y vois quelque chose de proche de ce que faisait déjà LINQ en 2007
      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
    • En utilisant à la fois ORM et raw SQL, je me reconnais dans les deux approches
      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
    • Il existe aussi des bibliothèques qui renversent le concept d’ORM
      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 classe GetUserQuery et une méthode du type getUser(id: String): GetUserQueryResult, et ce modèle me paraît bien meilleur
  • La 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

    • La plupart des frameworks ORM permettent d’exécuter du raw SQL, donc utiliser un ORM ne veut pas dire qu’on ne peut pas se servir de ces fonctionnalités
      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
    • J’ai l’impression d’avoir de la chance parce que je travaille surtout sur des projets sans base de données
      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-select
      Je laisserais volontiers de côté la plus grande partie de l’atelier
    • Il n’est donc pas surprenant que beaucoup de développeurs ne voient pas bien la différence entre SQL et NoSQL
    • À grande échelle, il est courant de dénormaliser fortement la base de données pour des raisons de performance et de l’utiliser comme un stockage de bits stupide de luxe
    • J’ai participé plusieurs fois à des projets où l’on disait : « on n’a pas besoin de toutes ces fonctionnalités sophistiquées de base de données », et gérer les conséquences a été frustrant
      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

    • ActiveRecord est vraiment agréable à utiliser, et dès qu’on rencontre un edge case, on peut toujours revenir au raw SQL
      C’est ainsi qu’un ORM devrait être conçu
    • Il est difficile d’imaginer refaire une grosse application CRUD sans ActiveRecord : la lisibilité et la maintenabilité en souffriraient
      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
    • J’ai du mal à comprendre les plaintes contre les ORM, mais c’est peut-être parce que le seul ORM que j’ai utilisé est ActiveRecord
  • 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

    • Mon expérience des ORM se limite presque entièrement à SQLAlchemy, avec juste un peu d’apprentissage d’Ecto, donc en lisant ce fil je me demande si tous les autres ORM sont vraiment aussi horribles
      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
    • Cela faisait vraiment longtemps que je n’avais pas vu quelqu’un employer correctement l’expression « begging the question »
    • Je peux recommander SQLAlchemy parce qu’il donne confiance pour écrire du SQL d’une manière où le code correspond bien à la requête
  • 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

    • Dans ce fil, beaucoup se plaignent que les ORM ne tiennent pas les promesses des éditeurs, et c’est vrai
      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
    • Dire qu’« on finit par en écrire un soi-même » n’est vrai que si l’on s’obstine à organiser la logique autour des objets plutôt que des « lignes »
      Voir https://news.ycombinator.com/item?id=36498583
    • Plusieurs départements et plusieurs entreprises ont souffert, ou ont échoué, parce qu’un ou quelques ultra-génies poursuivaient la perfection
      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
    • J’ai tellement entendu de choses négatives sur SQLAlchemy que j’ai décidé de créer moi-même un petit query builder léger, mais huit mois plus tard j’utilisais finalement SQLAlchemy
      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
    • Mieux vaut utiliser un bon ORM, sinon on se retrouve à porter soi-même la moitié d’un ORM médiocre
  • 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

    • Si on apprend d’abord SQL, on saura aussi quand il faut utiliser un ORM, et on pourra mieux l’évaluer
      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é
    • SQL est présenté comme un langage éternel
      À 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
    • L’idée clé est plutôt : « apprends d’abord les bases avant l’abstraction »
      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 »
    • J’écris directement du SQL depuis 1992 avec Pro*Pascal, CS130
      Mais aujourd’hui, j’utilise crud de azer, qu’on peut classer comme un ORM, à cause du marshalling/unmarshalling avec les types Go
      La bibliothèque standard Go sql est trop basique, donc il faut pratiquement écrire soi-même le marshalling/unmarshalling des objets, et c’est vraiment fastidieux
      Si 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

    • Dapper est de loin la solution d’accès aux données la plus agréable que j’aie utilisée
      Les développeurs doivent arrêter de faire comme si SQL n’existait pas et simplement l’accepter
    • J’aime le fait de ne pas avoir à écrire moi-même des fonctions de modèle qui finissent de toute façon par se mapper uniquement à du SQL, ni à produire du boilerplate PHP pour exécuter correctement des requêtes paramétrées
      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
    • Le juste milieu est bien. En TypeScript, il y a par exemple Kysely ou mon projet Zapatos
    • Je pense que c’est le point optimal
      À 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

    • Oui. Il y a aussi sqlc en Go
      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.js dans le dépôt, soit on utilise simplement la puissance de ce langage de haut niveau et on l’exprime dans un fichier .js
    • Depuis que j’ai utilisé sqlc sur un projet, j’ai l’impression de ne plus pouvoir revenir en arrière
      On 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
    • ActiveRecord m’a toujours semblé médiocre, mais j’ai toujours aimé arel, qui compose les requêtes en interne
      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
    • Le Enterprise Objects Framework de NeXT prenait déjà cela en charge il y a plus de 25 ans
      TopLink aussi, probablement
      C’est ainsi qu’ils géraient le mapping entre procédures stockées et entités locales
    • Je me demande de quels outils il s’agit