Comment suggérer l'utilisation d'un ORM au lieu de procédures stockées?

31

Je travaille dans une entreprise qui n'utilise que des procédures stockées pour tous les accès aux données, ce qui rend très ennuyeux de garder nos bases de données locales synchronisées, car à chaque validation, nous devons exécuter de nouveaux processus. J'ai utilisé des ORM de base dans le passé et je trouve l'expérience bien meilleure et plus propre. Je voudrais suggérer au responsable du développement et au reste de l'équipe que nous envisagions d'utiliser un ORM quelconque pour un développement futur (le reste de l'équipe ne connaît que les procédures stockées et n'a jamais utilisé autre chose). L'architecture actuelle est .NET 3.5 écrite comme .NET 1.1, avec des "classes divines" qui utilisent une implémentation étrange d'ActiveRecord et retournent des DataSets non typés qui sont bouclés dans des fichiers code-behind - les classes fonctionnent quelque chose comme ceci:

class Foo { 
    public bool LoadFoo() { 
        bool blnResult = false;
        if (this.FooID == 0) { 
            throw new Exception("FooID must be set before calling this method.");
        }

        DataSet ds = // ... call to Sproc
        if (ds.Tables[0].Rows.Count > 0) { 
            foo.FooName = ds.Tables[0].Rows[0]["FooName"].ToString();
            // other properties set
            blnResult = true;
        }
        return blnResult;
    }
}

// Consumer
Foo foo = new Foo();
foo.FooID = 1234;
foo.LoadFoo();
// do stuff with foo...

Il n'y a pratiquement aucune application de modèles de conception. Il n'y a aucun test (personne d'autre ne sait comment écrire des tests unitaires, et les tests sont effectués en chargeant manuellement le site Web et en fouillant). En parcourant notre base de données, nous avons: 199 tables, 13 vues, 926 procédures stockées et 93 fonctions. Une trentaine de tables sont utilisées pour des travaux par lots ou des objets externes, les autres sont utilisés dans notre application principale.

Vaut-il même la peine de poursuivre une approche différente dans ce scénario? Je parle d'avancer uniquement car nous ne sommes pas autorisés à refactoriser le code existant car "cela fonctionne" donc nous ne pouvons pas changer les classes existantes pour utiliser un ORM, mais je ne sais pas à quelle fréquence nous ajoutons de nouveaux modules à la place d'ajouter / de réparer les modules actuels, donc je ne sais pas si un ORM est la bonne approche (trop investi dans les procédures stockées et les DataSets). Si c'est le bon choix, comment dois-je présenter le cas pour en utiliser un? Sur le haut de ma tête, les seuls avantages auxquels je peux penser sont d'avoir un code plus propre (bien que ce ne soit peut-être pas, car l'architecture actuelle n'est pas t construit avec des ORM à l'esprit, donc nous serions fondamentalement en train de truquer des ORM sur des modules futurs mais les anciens utiliseraient toujours les DataSets) et moins de tracas pour se rappeler quels scripts de procédure ont été exécutés et lesquels doivent être exécutés, etc. mais c'est tout, et je ne sais pas à quel point ce serait un argument convaincant. La maintenabilité est une autre préoccupation, mais personne, sauf moi, ne semble s'inquiéter.

Wayne Molina
la source
8
On dirait que vous avez plus de problèmes que de simplement convaincre l'équipe d'utiliser des ORM. Il me semble que votre équipe n'est pas au courant de certaines bonnes pratiques de développement (par exemple, les modèles de conception, les tests unitaires). Ce sont des problèmes plus importants que vous devez résoudre.
Bernard
6
Ironiquement, je pense qu'en environ 5 ans de développement, je n'ai rencontré peut-être qu'une poignée de personnes / équipes qui étaient au courant de choses comme les modèles de conception et les tests unitaires; en général, je suis le seul gars de l'entreprise à connaître ces choses.
Wayne Molina
3
@Wayne M: Je trouve cela un peu dérangeant, mais je ne suis pas non plus surpris par cela.
Bernard
2
Je l'ai trouvé très ... décourageant. C'est étrange quand vous suggérez quelque chose et que vous obtenez un look "cerf dans les phares" qui indique que l'autre personne n'a pas la moindre idée de ce dont vous parlez ou pourquoi quelqu'un envisagerait de le faire. Je l'ai déjà fait plusieurs fois dans le passé.
Wayne Molina
2
Je suis un grand fan de la procédure stockée, donc mon commentaire est biaisé, mais je suis complètement en désaccord avec la prémisse dans son ensemble. Vous aimez ORM et vous voulez l'utiliser très bien. Cependant, le reste de l'équipe va bien avec les procs stockés. Pourquoi les forcer à ce que vous aimez?
Darknight

Réponses:

47

Les procédures stockées sont mauvaises, elles sont souvent lentes et approximativement aussi efficaces que le code côté client ordinaire.

[L'accélération est généralement due à la façon dont l'interface client et la procédure stockée sont conçues et à la façon dont les transactions sont écrites sous forme de courtes rafales focalisées de SQL.]

Les procédures stockées sont l'un des pires endroits pour mettre du code. Il décompose votre application en deux langues et plates-formes selon des règles souvent aléatoires.

[Cette question sera sous-estimée pour avoir un score d'environ -30 parce que beaucoup, beaucoup de gens pensent que les procédures stockées ont des pouvoirs magiques et doivent être utilisées malgré les problèmes qu'elles causent.]

Déplacer tout le code de procédure stockée vers le client rendra les choses beaucoup plus faciles pour tout le monde.

Vous devrez toujours mettre à jour le schéma et le modèle ORM de temps en temps. Cependant, les modifications de schéma sont isolées des modifications ORM, ce qui permet une certaine indépendance entre les applications et le schéma de base de données.

Vous pourrez tester, corriger, maintenir, comprendre et adapter toutes ces procédures stockées à mesure que vous les réécrivez. Votre application fonctionnera à peu près de la même manière et deviendra beaucoup moins fragile, car vous ne vous séparez plus de deux technologies différentes.

Les ORM ne sont pas magiques, et de bonnes compétences en conception de bases de données sont absolument essentielles pour le faire fonctionner.

En outre, les programmes contenant beaucoup de SQL client peuvent devenir lents en raison d'une mauvaise réflexion sur les limites des transactions. L'une des raisons pour lesquelles les procédures stockées semblent rapides est que les procédures stockées forcent une conception très, très prudente des transactions.

Les ORM n'imposent pas comme par magie une conception prudente des transactions. La conception des transactions doit encore être effectuée avec autant de soin que lors de l'écriture de procédures stockées.

S.Lott
la source
19
+1 parce que les procédures stockées sont une douleur totale à travailler
Gary Rowe
3
: "(Je n'ai aucun problème avec les procédures stockées. C'est juste une autre couche d'abstraction pour moi.
Mike Weller
3
Si nous créons SP, le moteur de base de données le stocke sous forme compilée et crée un chemin d'exécution afin qu'il s'exécute le plus rapidement possible. Mais ORM envoie à chaque fois du SQL qui doit être compilé et exécuté par le moteur de base de données. Je pense qu'il sera plus lent d'utiliser un ORM au lieu de la procédure stockée.
DeveloperArnab
4
Drôle. Nous sommes revenus d'un ORM à des procédures stockées juste à cause de .. SPEED. Pas le temps dont nous avons besoin pour la programmation, mais le temps dont un ORM a besoin pour des choses comme matérialiser des objets, rechercher un objet, mettre à jour sur différents clients. SP où beaucoup plus vite. Un exemple: lire 30 000 objets de DB avec un nouvel ORM moderne a besoin ... eh bien. timeout après 2 minutes. Appel de la procédure stockée et obtention du résultat - 2 secondes. Oui - il existe de nombreuses astuces comme la pagination pour réduire le callign à une base de données - mais grande différence si elles sont juste qu'un ORM peut être utilisé ou
Offler
2
@DeveloperArnab: Cela était peut-être vrai il y a 20 ans, mais les moteurs de base de données modernes sont assez sophistiqués et peuvent reconnaître les requêtes précédemment exécutées et réutiliser les plans d'exécution, la différence de vitesse de nos jours est si faible qu'elle ne justifie guère les tracas supplémentaires des SP.
whatsisname
20

Les procédures stockées sont bonnes, elles sont rapides et très efficaces et sont l'endroit idéal pour mettre votre code lié aux données. Déplacer tout ce code vers le client vous facilitera les choses en tant que développeur client (légèrement, car vous devrez toujours mettre à jour le schéma et le modèle ORM lorsque la validation les modifiera), mais vous perdrez tout ce code existant et votre application est plus lente et probablement plus fragile compte tenu de la perte de toutes ces compétences SQL.

Je me demande si les administrateurs de base de données sont assis là à dire "oh, à chaque validation, je dois à nouveau abaisser le client, nous devrions plutôt déplacer tout le code dans des formulaires DB".

Dans votre cas, vous devriez être en mesure de remplacer l'ORM personnalisé existant (c'est-à-dire vos classes amusantes) par quelqu'un d'autre sans aucune perte, sauf les modifications apportées à la façon dont votre code code est écrit. Vous pouvez également conserver les SP, car la plupart (tous?) Des ORM seront heureux de les appeler. Donc, je recommanderais de remplacer ces classes "Foo" par un ORM et de partir de là. Je ne recommanderais pas de remplacer vos SP.

PS Il semble que vous ayez beaucoup de code commun dans les classes code-behind, ce qui en fait un modèle de conception en soi. que pensez-vous qu'un modèle de conception est en premier lieu! (ok, ce n'est peut-être pas le meilleur, ni même un bon, mais c'est quand même un DP)

Edit: et maintenant avec Dapper , aucune raison d'éviter les sprocs sur un ORM lourd n'est partie.

gbjbaanb
la source
3
+1, la première étape évidente consiste à passer à un ORM et à l'utiliser pour mapper les résultats des procédures stockées existantes aux objets. Débarrassez-vous de toutes ces ds.Tables[0].Rows[0]["FooName"].ToString()conneries. Le gestionnaire aime les procédures stockées? Il arrive à les garder. Mais il serait physiquement impossible de soutenir que déplacer tout ce code répétitif dans un élément généré par, disons, LINQ to SQL, était une mauvaise chose.
Carson63000
11
Eh bien, je ne peux pas croire à quel point "faux" il y a dans votre message. Votre comparaison avec un DBA pleurant d'avoir à tirer le code est inappropriée et complètement insensée. Tout d'abord, la base de données est un SERVICE destiné à stocker et récupérer des données, fin de l'histoire. LOGIC, comme son nom l'indique, va dans la couche de logique métier, qui fait partie du code API. Application plus fragile s'éloignant des sprocs? Êtes-vous sérieux ou simplement à la traîne? TDD une application avec logique dans les sprocs et dites-moi à quel point c'est amusant. Les ORM ne doivent pas non plus être commutés. Les bases de données le sont, car elles ne sont qu'un SERVICE.
Matteo Mosca
5
Je ne peux pas vraiment comprendre pourquoi certaines personnes pensent que la base de données est une sorte de terre sainte où tout est sacré. Penses-y. Lorsqu'une entreprise tierce vous expose un service, vous donne-t-elle un accès direct à sa base de données ou la masque-t-elle derrière une API? Pour utiliser un exemple populaire, prenez n'importe quel service Google. Vous, développeur, vous connectez à leur API publique, vous ne savez même pas quelle base de données est en dessous, ou s'il y a une base de données. C'est ainsi que vous concevez un logiciel solide et découplé. Les bases de données ne sont pas censées être accessibles directement par les applications. Les niveaux intermédiaires sont là pour ça.
Matteo Mosca
5
@Matteo Mosca: bien sûr, mais comment le middleware accède-t-il à la base de données ... c'est un client de la base de données. "client" ne signifie pas "GUI" ou "application de bureau". Il y a beaucoup de zones grises dans les niveaux d'application - mettez-vous la validation dans l'interface graphique ou dans la logique serveur / métier? Il devrait aller dans le serveur pour être une conception propre, mais ce sera vraiment médiocre pour les performances et la réactivité de l'utilisateur. De même, vous mettez souvent un peu de logique dans la base de données lorsqu'elle améliore les performances et (dans ce cas) l'exactitude des données.
gbjbaanb
4
Je suis désolé mais je ne suis toujours pas d'accord. Le jour où vous devez déployer votre application dans un environnement différent, où vous n'avez pas la même technologie de base de données que vous avez utilisée, vous vous retrouvez dans une situation où votre application ne peut pas s'exécuter parce que vous n'avez pas tous ces sprocs sur la nouvelle base de données .. et même si vous les recréez (ce qui est une douleur totale), ils pourraient être différents, en raison des différences de dialectes SQL, etc. Une API centralisée avec logique et validation, exposée à travers un standard (comme SOAP ou REST) ​​résout ce problème problème, et ajoute la testabilité, la gestion des versions et la cohérence.
Matteo Mosca
13

Vous semblez essayer de mener votre équipe d'un extrême (procédures stockées et jeux de données) à un autre (un ORM à part entière). Je pense qu'il existe d'autres changements plus incrémentiels que vous pouvez définir pour implémenter afin d'améliorer la qualité du code de votre couche d'accès aux données, que votre équipe pourrait être plus disposée à accepter.

Le code d'implémentation d'enregistrement actif à moitié cuit que vous avez publié n'est pas particulièrement élégant - je vous recommande de rechercher le modèle de référentiel qui est facile à comprendre et à implémenter, et est très populaire auprès des développeurs .NET. Ce modèle est souvent associé aux ORM, mais il est tout aussi facile de créer des référentiels à l'aide d'ADO.NET simple.

Quant aux DataSet - beurk! Vos bibliothèques de classes seront beaucoup plus faciles à utiliser si vous retournez des objets typés statiquement (ou même dynamiques). Je crois que cette illustration explique mieux que moi mon opinion sur DataSet.

En outre, vous pouvez abandonner les proc stockés sans passer à un ORM - il n'y a rien de mal à utiliser du SQL paramétré. En fait, je préférerais sans aucun doute l'utilisation de proc stockés à moins que vous n'ayez des procédures complexes qui permettent d'économiser sur plusieurs allers-retours vers le serveur. Je déteste moi aussi quand j'ouvre une base de données héritée et que je vois une liste interminable de procédures CRUD.

Je ne décourage pas l'utilisation des ORM - je les utilise généralement sur la plupart des projets sur lesquels je travaille. Cependant, je peux voir pourquoi il pourrait y avoir beaucoup de frictions en essayant d'en introduire un dans ce projet et votre équipe pour le dire gentiment, comme s'ils avaient arrêté d'apprendre de nouvelles choses il y a environ 8 ans. Cela dit, je voudrais certainement jeter un coup d'œil à la nouvelle race de «Micro ORM» tels que Dapper (utilisé pour alimenter ce site non moins) et Massive , qui sont tous deux incroyablement faciles à utiliser et vous maintiennent plus proche du SQL qu'un ORM typique le fait, et que votre équipe pourrait être plus disposée à accepter.

richeym
la source
2
Je pense que le problème vient du moment où l'application a été écrite, il n'y avait pas de véritables ORM à noter pour .NET, donc cela a été fait dans l'autre sens (la façon ASP.NET 1.1), et personne n'a jamais pensé à le faire (ou autre chose) différemment jusqu'à ce que je rejoigne il y a quelques mois.
Wayne Molina
1
+1 pour Dapper. Je viens de commencer à l'utiliser sur un projet et il est extrêmement facile à mettre en œuvre et à utiliser. Je suis déjà un grand fan.
SLoret
4

Je suis dans une situation similaire, en fait notre matériel, notre puissance et notre politique s'appuient sur la base de données, donc tout passe par une procédure stockée. Malheureusement, ils sont pénibles pour un codeur, surtout en ce qui concerne les métadonnées et la génération de code, car il n'y a pas de métadonnées aussi riches dans les procédures stockées que les tableaux.

Quoi qu'il en soit, vous pouvez toujours écrire du code élégant et propre à l'aide de procs stockés. J'implémente moi-même le modèle de référentiel avec toutes les procédures stockées. Je suggère de consulter FluentAdo.net pour son idée brillante lors du mappage du datareader vers vos objets métier. J'ai pris un morceau de cette idée et l'ai réutilisé pour ma solution locale.

Justin
la source
3

JFTR - Je suis un développeur PHP modeste, mais cela ressemble à un problème principalement politique.

Compte tenu de l'ampleur de la «pourriture» qui soutient l'application, alors - hormis les meilleures pratiques - il y aurait un surcoût important pour l'extirper. Cela ressemble à une frontière avec le territoire de réécriture.

Pouvez-vous garantir que l'alternative que vous proposez produirait des avantages pour justifier le coût pour l'entreprise? Je soupçonne que le retour sur investissement de cette entreprise peut être difficile à vendre à l'entreprise. À moins que l'application ne soit instable ou que vous puissiez prouver le mérite de la refonte en termes financiers - cela pourrait s'avérer difficile.

L'ORM est-il la seule alternative à SPROCS? Il existe quelques modèles de conception entre un ORM complet et un SQL vanille. Vous pourriez peut-être lancer le processus en transférant progressivement ces SPROCS de la DB dans une DBAL. Il y a bien sûr le danger que cela devienne un ORM homebrew au fil du temps - mais vous auriez pu vous rapprocher de l'objectif.

sunwukung
la source
2

Nous sommes passés du SP à l'ORM il y a quelques années.

Dans un cas, nous avons dû mettre à jour 80 tableaux. L'ancien modèle d'estimation aurait estimé 80 heures pour cela avec entlib et SP. Nous l'avons fait en 10 :)

Cela nous a permis de réduire de 80% le temps que nous utilisons pour développer la couche d'accès aux données.

Shiraz Bhaiji
la source
1
Et vous ne pouviez pas écrire la mise à jour de la table pourquoi?
Darknight
Cela prenait un objet complexe en mémoire et le sauvegardait dans une base de données relationnelle pour le rapport. Nous avons écrit un programme qui a fait une réflexion sur l'objet pour créer la structure de la table.
Shiraz Bhaiji,
-1

Il me semble plus que le problème sous-jacent est que vos déploiements ne fonctionnent pas correctement et automatiquement.

Il pourrait être plus facile de configurer un moteur de construction continu qui sait comment manipuler les bases de données selon les besoins après chaque validation.


la source