La meilleure façon d'organiser les requêtes SQL stockées dans votre code? (ou devriez-vous?) [fermé]

13

Je suis sûr que je ne suis pas le seul à être frustré lorsqu'ils voient une page de code jonchée de requêtes SQL. ActiveRecord et d'autres modèles ORM permettent d'atténuer une bonne quantité de SQL utilisé dans un projet, mais dans de nombreux cas de requêtes complexes, l'utilisation de SQL est apparemment inévitable.

Je recherche des opinions sur la façon dont les requêtes SQL doivent être organisées avec le reste du code (ou en externe) pour l'empêcher d'être dispersé partout? Une idée évidente est l'utilisation de vues, mais souvent les vues peuvent être une source de problèmes de performances lors du traitement de plusieurs grandes tables indexées, etc.

EDIT 1 - Je suppose que vous l'avez déjà séparé dans la couche modèle

méduse
la source
3
Cette question est tout à fait appropriée ici - organisation du code: «inspire [s] des réponses qui expliquent« pourquoi »et« comment ». et est des sujets 'Design patterns' et 'Architecture' (from the Faq )
Michael K
1
J'étais sur le point de poser cette même question. Je souhaite qu'il y ait plus de réponses ici.
Michael Kristofik

Réponses:

10

Pour moi, SQL est une partie fondamentale (dans de nombreux cas, la majorité) du code de logique métier. Si vous essayez de le séparer du code qui opère sur les données retournées, vous êtes plus enclin à déséquilibrer la compréhensibilité et la maintenabilité du code.

À mon avis, lire des données, traiter des données, écrire des données, rechercher des données ... ce sont toutes des opérations similaires, et il vaut mieux les garder au même endroit.

Si vous commencez à sentir une duplication des efforts avec les requêtes, vous avez peut-être besoin d'une vue de base de données ou d'un objet qui peut encapsuler cet aspect de l'accès à la base de données.

Une autre astuce consiste à avoir une bonne méthode de requête de base de données. Dans les logiciels que j'écris (PostgreSQL, MySQL, SQL Server), j'ai veillé à ce que la majeure partie de mes opérations de requête puisse avoir lieu comme une seule déclaration de code.

GetValue(SQL, [transaction], [array_of_params])
GetRow(SQL, [transaction], [array_of_params])
GetRowList(SQL, [transaction], [array_of_params])
GetValueList(SQL, [transaction], [array_of_params])
Execute(SQL, [transaction], [array_of_params])

Ce sont (grosso modo) les principaux appels de fonction dont je m'assure qu'ils font partie de mon "objet de connexion". Cela dépend de la langue, de ce que vous implémentez réellement, mais mon but est de le garder vraiment, vraiment simple et indolore.

En résumé, traitez SQL comme une partie native de la programmation et n'abstenez pas pour l'abstraction.

gahooa
la source
1
une excellente réponse. peut-être ai-je juste besoin de prendre du recul et de commencer à regarder le SQL en tant que partie du code, pas seulement dispersé parmi lui.
jellyfishtree
1
"ne faites pas d'abstrait pour l'abstraction" - Bon point. Résumé pour un code plus compréhensible.
Jason Baker
"Une autre astuce consiste à avoir une bonne méthode de requête de base de données": je suis définitivement d'accord. Cela aide beaucoup lorsqu'il n'y a qu'un seul endroit pour modifier le code lorsque la logique métier change.
Michael K
1
Où mettez-vous le SQL? Est-il compilé dans l'application et envoyé en utilisant les méthodes ci-dessus?
johnny
Sur la base du commentaire d'OP sur la réponse de Jason Baker, "regarder le baril d'une requête SQL géante ...", comment cela résout-il le problème de la lecture de gros blocs de texte SQL?
JeffO
0

Généralement, avoir une couche de modèle distincte est la meilleure approche. Il existe un certain nombre de modèles de conception d'entreprise qui permettent de concevoir cela.

Jason Baker
la source
désolé, j'aurais dû être plus précis ... Je suppose déjà que vous les avez séparés en une couche modèle. Mais une couche de modèle peut encore être assez dispersée avec du code SQL. C'est peut-être inévitable. L'autre chose qui me fait flipper dans le code du modèle est un code qui "construit une requête SQL" basé sur une logique ... peut-être que cela devrait être séparé dans sa propre usine ou quelque chose ...
jellyfishtree
2
@jellyfishtree - J'ai bien peur de ne pas comprendre le problème. Je veux dire, vous avez peur que votre couche de modèle se retrouve avec trop de code de modèle?
Jason Baker
une réfutation valide. Je suis préoccupé par la lisibilité. Un bon code de modèle est généralement assez facile à comprendre, mais regarder le baril d'une requête SQL géante n'a pas exactement sa signification. Évidemment, la première chose à faire est de commenter correctement ces requêtes, mais ce n'est pas la même chose qu'un bon code auto-documenté et ce type de sections est dispersé à travers le modèle. Je l'accepte, mais je me demandais s'il y avait une meilleure façon d'isoler ou d'organiser des instructions SQL folles dans le modèle ...
jellyfishtree
0

Il pourrait être judicieux de séparer votre couche de modèle en 3 sous-couches - "entités", "référentiels" et "services". Cela vous permettra de séparer les préoccupations et de rassembler SQL en un seul endroit, hors de votre logique métier.

Dans ce scénario, tout le code de récupération de données, y compris SQL complexe, sera situé dans des référentiels. Le but du référentiel est donc de cacher des instructions SQL complexes derrière des méthodes explicites comme getUsersWithActiveSubscription().

L'entité résume les vrais noms de champ de table DB avec des getters et setters, peut fournir une certaine conversion de données entre les types de champs DB et les types disponibles dans votre langage d'application / de programmation. Si votre ORM le prend en charge, les entités peuvent gérer les associations.

La couche de service est le lieu de la logique métier. Le service récupère les entités à l'aide de référentiels, agit sur elles et les stocke.

GerKirill
la source