Quelle logique métier la base de données doit-elle implémenter?


108

J'ai travaillé sur certains projets où la majeure partie de la logique métier était implémentée dans la base de données (principalement via des procédures stockées). De l'autre côté, certains collègues programmeurs m'ont dit que c'était une mauvaise pratique ("Les bases de données sont là pour stocker des données. Les applications sont là pour faire le reste").

Laquelle de ces approches est généralement la meilleure?

Les avantages de la mise en œuvre de la logique métier dans la base de données à laquelle je peux penser sont:

  • Centralisation de la logique métier;
  • Indépendance du type d'application, du langage de programmation, du système d'exploitation, etc.
  • Les bases de données sont moins sujettes à la migration technologique ou aux grands refactorisations (selon les informations dont je dispose)
  • Aucune retouche sur la migration de la technologie d'application (par exemple: .NET vers Java, Perl vers Python, etc.).

Les inconvénients:

  • Le langage SQL est moins productif et plus complexe pour la programmation de logique d’entreprise, en raison du manque de bibliothèques et de constructions de langage, ce qui en fait l’offre de langages la plus orientée application;
  • Plus difficile (si possible) la réutilisation du code dans les bibliothèques;
  • IDE moins productifs.

Remarque: les bases de données dont je parle sont des bases de données relationnelles populaires telles que SQL Server, Oracle, MySql, etc.

Merci!


3
Vous pourriez trouver la réponse utile à cette question .
Blrfl

7
Cet argument a déjà été débattu de manière exhaustive . Que pourrions-nous ajouter de manière significative à la conversation ici?
Robert Harvey

2
@gn: Pas même proche.
Robert Harvey


7
Considérez que la base de données va surpasser ( loin ) votre application. La base de données peut même survivre à la langue que vous écrivez votre application. Les données elles- mêmes en général est l'entreprise, et la base de données devrait être en mesure de protéger l'intégrité des données qu'il contient. En ce sens, chaque contrainte de clé étrangère est, franchement, l’application d’une règle de gestion. Si vous ne supprimez pas toutes les contraintes relationnelles de votre base de données relationnelle, vous ne pouvez vraiment pas extraire totalement la logique métier de la base de données.
Craig le

Réponses:


83

La logique métier ne va pas dans la base de données

Si nous parlons d'applications multi-niveaux, il semble assez clair que la logique métier, le type de renseignement qui gère une entreprise particulière, appartient à la couche de logique applicative, pas à la couche d'accès aux données.

Les bases de données font très bien certaines choses:

  1. Ils stockent et récupèrent des données
  2. Ils établissent et renforcent les relations entre différentes entités de données
  3. Ils fournissent le moyen d'interroger les données pour obtenir des réponses
  4. Ils fournissent des optimisations de performances.
  5. Ils fournissent un contrôle d'accès

Maintenant, bien sûr, vous pouvez codifier toutes sortes d'éléments dans une base de données concernant vos préoccupations commerciales, tels que les taux d'imposition, les remises, les codes d'opération, les catégories, etc. Mais l' action entreprise sur ces données n'est généralement pas codée dans la base de données, pour toutes sortes de raisons déjà mentionnées par d'autres, bien qu'une action puisse être choisie dans la base de données et exécutée ailleurs.

Et bien sûr, certaines choses peuvent être exécutées dans une base de données pour des raisons de performances et pour d'autres raisons:

  1. Clôture d'une période comptable
  2. Le nombre de calculs
  3. Traitements par lots nocturnes
  4. Fail-over

Naturellement, rien n'est gravé dans la pierre. Les procédures stockées conviennent à un large éventail de tâches simplement parce qu'elles résident sur le serveur de base de données et présentent certains avantages et forces.

Procédures stockées partout

Il y a une certaine attirance à coder toutes vos tâches de stockage, de gestion et de récupération de données dans des procédures stockées, et à consommer simplement les services de données résultants. Vous bénéficierez certainement des optimisations maximales possibles en termes de performances et de sécurité que le serveur de base de données pourrait fournir, et ce n'est pas une mince affaire.

Mais que risquez-vous?

  1. Immobilisation du vendeur
  2. Le besoin de développeurs avec des compétences spéciales
  3. Outils de programmation spartiates, globalement
  4. Couplage logiciel extrêmement serré
  5. Pas de séparation des préoccupations

Et bien sûr, si vous avez besoin d’un service Web (et c’est probablement là que tout se passe, de toute façon), vous devrez toujours le construire.

Alors, quelle est la pratique typique?

Je dirais qu'une approche moderne typique consiste à utiliser un mappeur relationnel-objet (tel que Entity Framework) pour créer des classes qui modélisent vos tables. Vous pouvez ensuite parler à votre base de données via un référentiel qui renvoie des collections d'objets, une situation très familière à tout développeur de logiciel compétent. L'ORM génère dynamiquement du code SQL correspondant à votre modèle de données et aux informations demandées, que le serveur de base de données traite ensuite pour renvoyer les résultats de la requête.

Comment ça marche? Très bien et beaucoup plus rapidement que l’écriture de procédures stockées et de vues. Cela couvre généralement environ 80% de vos besoins d’accès aux données, principalement CRUD. Qu'est-ce qui couvre l'autre 20%? Vous l'avez deviné: les procédures stockées, que tous les principaux ORM prennent en charge directement.

Pouvez-vous écrire un générateur de code faisant la même chose qu'un ORM, mais avec des procédures stockées? Sûr que vous pouvez. Mais les ORM sont généralement indépendants des fournisseurs, bien compris de tous et mieux supportés.


3
Merci pour votre excellente réponse, Robert Harvey. Mais je pensais à l'argument du "verrouillage du vendeur": si vous n'utilisez pas une technologie particulière (la pile .NET ou Java, par exemple) pour créer une application, vous devez également vous en tenir au vendeur? Ou y a-t-il des avantages d'un verrouillage du fournisseur de pile orienté application par rapport à un verrouillage de base de données?
Raphael

3
@RobertHarvey, mais la partie de la logique d'application qui se trouve dans .NET est toujours verrouillée sur .NET. Il en va de même pour PHP et Java.
Pacerier

2
@Pacerier: Par vendeur-lockin, je parle du fournisseur de base de données. Dans la pratique, la base de données (et la pile de programmation) sont rarement remplacées.
Robert Harvey

2
@ Kai: Eh bien, vous ne pouvez pas avoir les deux. Soit vous utilisez des moignons et des mocs et vous vivez avec le fait que le test est artificiel, soit vous écrivez un test réaliste, avec un peu de retard. Je doute que votre compromis est de 10 minutes contre 30 secondes.
Robert Harvey

3
Peut-être tard, mais j'estime que les procédures stockées implémentant la logique métier appartiennent à la couche de logique métier et non à la couche de données. Ils sont en quelque sorte des lang séparés sans besoin de ORM.
Paralife

16

Je suis un fervent partisan de la conservation de la base de données autant que possible de la logique commerciale. Cependant, en tant que développeur de performances de mon entreprise, j'apprécie qu'il est parfois nécessaire d'obtenir de bonnes performances. Mais je pense que cela est nécessaire beaucoup moins souvent que ne le prétendent les gens.

Je conteste vos avantages et vos inconvénients.

Vous prétendez que cela centralise votre logique métier. Au contraire, je pense que cela le décentralise. Dans un produit sur lequel je travaille actuellement, nous utilisons des procédures stockées pour une grande partie de notre logique métier. Bon nombre de nos problèmes de performances proviennent de l'appel répété de fonctions. Par exemple

select <whatever>
from group g
where fn_invoker_has_access_to_group(g.group_id)

Le problème avec cette approche est qu’elle (dans certains cas, cela est faux) force la base de données à exécuter votre fonction N fois, une fois par ligne. Parfois, cette fonction est chère. Certaines bases de données prennent en charge les index de fonction. Mais vous ne pouvez pas indexer toutes les fonctions possibles avec toutes les entrées possibles. Ou peut vous?

Une solution courante au problème ci-dessus consiste à extraire la logique de la fonction et à la fusionner dans la requête. Maintenant, vous avez cassé l'encapsulation et la logique dupliquée.

Un autre problème que je vois est l'appel de procédures stockées dans une boucle car il n'existe aucun moyen de joindre ou d'intersecter des ensembles de résultats proc stockés.

declare some_cursor
while some_cursor has rows
    exec some_other_proc
end

Si vous extrayez le code du processus imbriqué, vous décentralisez à nouveau. Par conséquent, vous êtes obligé de choisir entre encapsulation et performance.

En général, je trouve que les bases de données sont mauvaises à:

  1. Calcul
  2. Itération (ils sont optimisés pour les opérations sur les ensembles)
  3. L'équilibrage de charge
  4. L'analyse

Les bases de données sont bonnes à:

  1. Verrouillage et déverrouillage
  2. Maintenir les données et leurs relations
  3. Assurer l'intégrité

En effectuant des opérations coûteuses telles que l'analyse de boucles et de chaînes et en les conservant dans votre niveau d'application, vous pouvez redimensionner votre application horizontalement pour obtenir de meilleures performances. L'ajout de plusieurs serveurs d'applications derrière un équilibreur de charge est généralement beaucoup moins coûteux que la configuration de la réplication de base de données.

Vous avez cependant raison de dire que cela dissocie votre logique métier du langage de programmation de votre application, mais je ne vois pas en quoi cela constitue un avantage. Si vous avez une application Java, alors vous avez une application Java. La conversion d'un tas de code Java en procédures stockées ne change pas le fait que vous avez une application Java.

Ma préférence est de garder le code de base de données concentré sur la persistance. Comment créez-vous un nouveau widget? Vous devez insérer dans 3 tables et elles doivent être dans une transaction. Cela appartient à une procédure stockée.

La définition de ce qui peut être fait sur un widget et les règles de gestion permettant de rechercher des widgets appartiennent à votre application.


8
Dans SQL Server, seuls les sps mal écrits doivent être appelés dans une boucle, vous pouvez lui envoyer des ensembles de données dans un paramètre et effectuer un processus basé sur les ensembles.
HLGEM

2
SQL Server générera un plan de requête sous-optimal chaque fois qu'il y a une UDF dans une clause WHERE.
Jim G.

7
On dirait que votre problème de performance n’est pas la faute de la logique dans la base de données vs app .. c’est juste mal écrit et architecturé. Ce problème vous suivra de la même manière dans le monde ORM. Les ORM peuvent être un vrai casse-tête en dehors des opérations CRUD. Si votre système est lourd en données et en type de rapport, veuillez faire preuve de prudence.
Sam yi

C'est vrai. La plupart de nos problèmes de performances sont simplement dus à un code mal écrit et à une architecture trop complexe. Mais je crois toujours que nous avons mis le mauvais type de travail dans nos bases de données. Le codage le plus possible dans la base de données nous a amené à faire des choses pour lesquelles la base de données n’est pas bonne.
Brandon

1
Cet exemple est même un argument pour placer les parties principales de la logique d'entreprise dans la base de données: pour éviter une approche itérative (boucles de code ou de curseur au lieu d'expressions basées sur des ensembles) comme le fléau. Les programmeurs ont tendance à traiter des ensembles d'objets de manière itérative (boucle, traversée), ce qui peut conduire à des charges inutiles ou au problème SELECT N + 1 de nombreux circuits aller-retour autour d'une seule requête. En utilisant SQL ou des expressions basées sur le langage (par exemple, LINQ), ils seront obligés d'utiliser une approche basée sur les ensembles, dans la mesure du possible.
Erik Hart

10

J'ai travaillé dans 2 entreprises différentes qui avaient une vision différente sur le sujet.

Ma suggestion personnelle serait d'utiliser des procédures stockées lorsque le temps d'exécution est important (performance). Puisque les procédures stockées sont compilées, si vous avez une logique complexe pour interroger les données, il est préférable de la conserver sur la base de données elle-même. En outre, il n'enverra que les données finales à votre programme à la fin.

Sinon, je pense que la logique d'un programme devrait toujours être dans le logiciel lui-même. Pourquoi? Parce qu'un programme doit être testable et je ne pense pas qu'il existe un moyen simple de tester à l'unité la procédure stockée. N'oubliez pas qu'un programme non testé est un mauvais programme.

Utilisez donc la procédure stockée avec prudence, lorsque cela est nécessaire.


3
Les procédures stockées sont testables à l’unité. Voir ici pour quelques techniques.
Robert Harvey

4
autant que je sache, un test unitaire n'utilise jamais de base de données ou de fichier. Donc techniquement, "tester en unité" une procédure stockée n'est pas une analyse en unité et ce sera très lent. Une suite de tests unitaires doit être exécutée en quelques secondes (ou peut-être quelques minutes avec une très grande application) à tout moment du développement.
Jean-François Côté le

1
Le PO parlait de "logique métier" et cette dernière devrait être testée d'unité. En le mettant dans une procédure stockée, vous le mélangez avec une requête de base de données qui ralentit l'ensemble du processus. Comme je l'ai dit, vous pouvez utiliser la procédure stockée (ce n'est pas un crime), mais la ligne de démarcation entre la logique métier et la couche base de données sera floue. Utilisez-le avec précaution :)
Jean-François Côté le

1
Si vous créez la base de données et les objets nécessaires, sp, test, puis supprimez-le par la suite, il s'agit d'un test unitaire. Il teste une unité de travail.
Tony Hopkinson

2
Les gains de performances obtenus avec le mythe des procédures stockées n'ont-ils pas été démystifiés?
JeffO

9

Vous devez trouver un terrain d'entente. J'ai vu des projets effrayants dans lesquels les programmeurs utilisent la base de données comme rien de plus qu'un magasin de clé / valeur hors de prix. J'ai vu d'autres où les programmeurs échouent à utiliser des clés étrangères et des index. À l'autre extrémité du spectre, j'ai vu des projets dans lesquels la plupart, voire la totalité, de la logique métier est implémentée dans le code de base de données.

Comme vous l'avez noté, T-SQL (ou son équivalent dans d'autres SGBDR courants) n'est pas exactement le meilleur endroit pour coder une logique métier complexe.

J'essaie de créer un modèle de données raisonnablement décent, d'utiliser les fonctionnalités de la base de données pour protéger mes hypothèses sur ce modèle (c.-à-d. Les FK et les contraintes) et d'utiliser le code de la base de données avec parcimonie. Le code de la base de données est utile lorsque vous avez besoin de quelque chose (par exemple, une somme) que la base de données sait très bien faire et peut vous éviter de déplacer des zillions d'enregistrements sur le réseau lorsque vous n'en avez pas besoin.


2
L'utilisation de la base de données en tant que magasin clé / valeur "hors de prix" est une technique parfaitement valable, comme l'attesteront les légions de praticiens de NoSQL.
Robert Harvey

1
@ RobertHarvey Vous avez manifestement raison, mais mon instinct continue d'insister sur le fait qu'il doit exister une solution plus simple / moins chère / plus rapide qu'une base de données si vous n'avez besoin que d'un magasin de clés / valeurs. J'ai besoin d'en savoir plus sur NoSQL.
Dan Pichelman

2
Je ne vois pas en utilisant des procédures stockées comme un remède pour une base de données mal conçue.
JeffO

2
@ RobertHarvey, j'ai lu littéralement "magasin de clé / valeur surévalué". Payer une licence Oracle ou SQL Server pour quelque chose comme ça, quand il y a des options comme MongoDB disponibles gratuitement, semble être une perte d'argent.
Raphael

@Raphael Ou vous pouvez utiliser PostgreSQL ™
Demi

9

Si votre logique métier implique des opérations sur les ensembles, elle constitue probablement un emplacement approprié dans la base de données, car les systèmes de base de données sont vraiment efficaces pour effectuer des opérations sur les ensembles.

http://en.wikipedia.org/wiki/Set_operations_(SQL)

Si la logique applicative implique une sorte de calcul, elle appartient probablement en dehors de la procédure de base de données / magasin car les bases de données ne sont pas vraiment conçues pour la boucle et le calcul.

Bien que ce ne soient pas des règles strictes, c'est un bon point de départ.


6

Il n'y a pas une seule bonne réponse à cela. Cela dépend de ce que vous utilisez la base de données. Dans une application d'entreprise, vous avez besoin de la logique de la base de données sous forme de clés étrangères, de contraintes, de déclencheurs, etc., car c'est le seul endroit où toutes les applications possibles partagent le même code. En outre, l'insertion de la logique requise dans le code signifie généralement que la base de données est incohérente et que les données sont de mauvaise qualité. Cela peut sembler trivial à un développeur d’applications qui ne se soucie que de la façon dont fonctionne l’interface graphique, mais je vous assure que les personnes essayant d’utiliser les données dans les rapports de conformité le trouvent très ennuyeux et coûteux lorsqu'elles se voient imposer des amendes d'un milliard de dollars pour avoir Suivez pas les règles correctement.

Dans un environnement non réglementaire où vous vous souciez moins de l'ensemble des enregistrements et que seulement une ou deux applications arrivent dans la base de données, vous pouvez peut-être vous en sortir en gardant tout cela dans l'application.


3

Après quelques années, la question est toujours importante ...

Pour moi, la règle est simple: s'il s'agit d'une contrainte logique ou d'une expression omniprésente (instruction unique), placez-la dans la base de données (oui, les clés étrangères et les contraintes de vérification sont également de la logique métier!). Si c'est procédural, en contenant des boucles et des branches conditionnelles (et ne peut vraiment pas être transformé en une expression), mettez-le en code.

Éviter les bases de données de vidage de corbeille

Les tentatives visant à placer réellement toute la logique métier dans le code d’application vont probablement dégénérer la base de données (relationnelle) en un vidage de la corbeille, où la conception relationnelle est presque complètement omise, où les données peuvent avoir un état incohérent et où la normalisation est absente (souvent principalement XML, , Colonnes de corbeille CSV etc.).

Ce type de logique réservée aux applications est probablement l’une des principales raisons de l’essor de NoSQL - bien sûr, mais l’inconvénient est que l’application doit prendre en charge toute la logique elle-même, qui est intégrée à la base de données relationnelle depuis des décennies. Cependant, les bases de données NoSQL conviennent mieux à ce type de traitement de données. Par exemple, les documents de données conservent une "intégrité relationnelle" implicite en eux-mêmes. Pour les bases de données relationnelles, il s’agit tout simplement d’abus et de problèmes.

Expressions (basées sur les ensembles) au lieu de code procédural

Dans le meilleur des cas, chaque requête ou opération de données doit être codée comme une expression plutôt que comme un code de procédure. Les langages de programmation prennent en charge des expressions telles que LINQ dans le monde .NET (malheureusement, seules les requêtes pour le moment, pas de manipulation). Du côté des bases de données relationnelles, on a appris depuis longtemps à préférer les expressions d'instructions SQL aux boucles procédurales du curseur. Ainsi, la base de données peut être optimisée, effectuer l’opération en parallèle, ou ce qui peut être utile.

Utiliser les mécanismes d'intégrité des données de la base de données

Lorsqu'il s'agit de SGBDR avec une clé étrangère et des contraintes de vérification, des colonnes calculées, éventuellement des déclencheurs et des vues, c'est l'endroit idéal pour stocker la logique métier de base dans la base de données. Une normalisation appropriée aide à maintenir l'intégrité des données, afin de garantir une instance unique et distincte des données. Même si vous devez le dupliquer dans le code et la base de données, ces mécanismes de base de l'intégrité des données ne doivent pas être omis!

Procédures stockées?

Les procédures stockées sont rarement nécessaires de nos jours, car les bases de données conservent les plans d'exécution compilés pour SQL et les réutilisent lorsque la même requête revient, uniquement avec des paramètres différents. Ainsi, l'argument de précompilation pour les SP n'est plus valide. On peut stocker ou générer automatiquement des requêtes SQL dans l'application ou l'ORM, qui trouvera la plupart du temps des plans de requête précompilés. SQL est un langage d'expression, tant que vous n'utilisez pas explicitement des éléments procéduraux. Donc, dans le meilleur des cas, vous utilisez des expressions de code pouvant être traduites en SQL.

Bien que le côté application, y compris SQL généré par ORM, ne soit plus dans la base de données, contrairement aux procédures stockées, je le considère toujours comme du code de base de données. Parce qu'il nécessite toujours des connaissances en SQL et en base de données (à l'exception du CRUD le plus simple), il fonctionne de manière très différente du code de procédure généralement créé avec des langages de programmation tels que C # ou Java.


2

Cela dépend vraiment de l'entreprise, de sa culture et de son héritage. Mis à part les considérations techniques (celles-ci ont été abordées des deux côtés), les réponses fournies indiquent qu’il s’agit de savoir d’où viennent les gens. Dans certaines organisations, les données sont primordiales et le DBA est un personnage puissant. C'est votre environnement centralisé typique, un centre de données auquel sont rattachés de nombreux terminaux. La préférence dans ce type d’environnement est claire. Le poste de travail peut changer radicalement plusieurs fois avant que quoi que ce soit ne change dans le centre de données et il y aura peu de temps entre les deux.

L’autre extrémité du spectre est l’architecture pure à 3 niveaux. Ou peut-être à plusieurs niveaux dans une entreprise orientée Web. Votre volonté entendre probablement une histoire différente ici. L’administrateur de base de données, s’il y en a un, sera juste un sidekick qui effectue certaines tâches administratives.

Un développeur d'applications des temps modernes aura plus d'affinité avec le second modèle. Si vous avez grandi avec un grand système client-serveur, vous seriez probablement dans l'autre camp.

Il y a souvent tellement de facteurs liés à l'environnement non techniques impliqués ici qu'il n'y a pas de réponse générale à cette question.


2

Le terme logique métier est ouvert à interprétation. Lors de la construction de systèmes, nous voulons garantir l’intégrité de la base de données et de son contenu. Dans un premier temps, différentes autorisations d'accès utilisateur doivent être en place. À titre d’exemple très simple, considérons une application ATM.

Pour obtenir le solde du compte, il suffit de sélectionner une vue appropriée. Mais pour transférer des fonds, vous voudriez que la transaction soit encapsulée par une procédure stockée. La logique applicative ne doit pas être autorisée à mettre à jour directement les tables pour les montants en crédits et débits.

Dans cet exemple, la logique applicative pourrait vérifier le solde avant de demander le transfert ou simplement appeler le proc stocké pour le transfert et signaler l'échec. IMHO, la logique métier, dans cet exemple, doit vérifier de manière préventive que des fonds suffisants sont disponibles et que le compte cible existe, puis seulement appeler les fonds de transfert. Si un autre débit se produit entre les étapes initiales et l’invocation de procédure stockée, une erreur ne serait alors renvoyée.


Bel exemple et explication.
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.