Pourquoi l'architecture backend gagne à dépasser le modèle traditionnel des ORM
L'usage systématique des ORM dans les applications web pose des questions croissantes de performance et d'abstraction surdimensionnée. En revenant à du SQL brut encapsulé dans des magasins de données dédiés, les équipes d'ingénierie réduisent l'empreinte mémoire et tirent pleinement parti des capacités natives des bases relationnelles.
Fil « Réflexion sur les alternatives aux ORM pour la gestion de bases de données »
Les limites fondamentales du mapping objet-relationnel
L'utilisation d'un ORM (Object-Relational Mapping, technique de correspondance entre objets logiciels et tables relationnelles) est devenue le choix par défaut dans de nombreux frameworks. Cependant, cette couche d'abstraction impose un coût de performance élevé en matière d'allocation mémoire et de temps processeur pour transformer chaque ligne de la base de données en objet complet. De plus, elle masque souvent des fonctionnalités SQL avancées comme les fonctions de fenêtrage (window functions, calculs d'agrégation sur un sous-ensemble de lignes) ou les requêtes CTE (Common Table Expressions, expressions de table communes pour structurer des requêtes complexes).
Exploiter la puissance SQL native avec la clause RETURNING
Les ORM incitent fréquemment à multiplier les aller-retours avec la base de données. Par exemple, pour supprimer des enregistrements tout en récupérant leur contenu, une approche ORM classique exécute d'abord une requête SELECT puis une série de requêtes DELETE. Des bases relationnelles comme PostgreSQL ou SQLite permettent d'exécuter cette opération en un seul aller-retour grâce à la clause RETURNING.
DELETE FROM beads
WHERE material = 'wood'
RETURNING *;
Repenser le composant Modèle dans l'architecture MVC
Dans l'architecture MVC (Modèle-Vue-Contrôleur, patron d'architecture séparant les données, l'affichage et la logique métier), le modèle est traditionnellement assimilé à une entité ORM dotée d'une API (Application Programming Interface, interface de programmation) très vaste. Une approche alternative consiste à encapsuler les requêtes dans des classes dédiées (Store ou Repository) qui renvoient directement des structures de données brutes (des dictionnaires ou cartes clé-valeur) plutôt que des instances d'objets lourdes.
class PostsStore
def initialize(db)
@db = db
end
def create(title:, body:)
@db.query_single_row(<<~SQL, title, body)
INSERT INTO posts (title, body)
VALUES (?, ?)
RETURNING id;
SQL
end
end
Réduire la complexité inutile du code
Une application web n'exécute en pratique qu'un nombre fini et relativement restreint de requêtes par table. L'utilisation d'un DSL (Domain-Specific Language, langage dédié servant ici à construire dynamiquement des requêtes) complexe s'avère souvent surdimensionnée. Définir des requêtes SQL explicites dans une couche d'accès aux données simplifie la maintenance, élimine la magie implicite des ORM et garantit une maîtrise totale des performances de la base de données.