web-dev-qa-db-fra.com

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

J'ai travaillé sur certains projets où la majeure partie de la logique métier a été implémentée sur la base de données (principalement via des procédures stockées). D'un 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 les 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 pense sont les suivants:

  • 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 refactorings (AFAIK);
  • Pas de retouches sur la migration des technologies applicatives (ex: .NET vers Java, Perl vers Python, etc.).

Les inconvénients:

  • SQL est moins productif et plus complexe pour la programmation de logique métier, en raison du manque de bibliothèques et de constructions de langage qu'offrent les langages les plus orientés application;
  • Réutilisation de code plus difficile (si possible) à travers les bibliothèques;
  • IDE moins productifs.

Remarque: Les bases de données dont je parle sont des bases de données relationnelles et populaires comme SQL Server, Oracle, MySql etc.

Merci!

118
Raphael

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

Si nous parlons d'applications à plusieurs niveaux, il semble assez clair que la logique métier, le type d'intelligence qui gère une entreprise particulière, appartient à la couche logique métier, pas à la couche 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 appliquent des relations entre différentes entités de données
  3. Ils fournissent les moyens 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 de choses dans une base de données qui se rapportent à vos préoccupations commerciales, telles que les taux de taxe, les remises, les codes d'opération, les catégories, etc. Mais la action commerciale qui est prise 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 le base de données et exécuté ailleurs.

Et bien sûr, il peut y avoir des choses qui sont effectuées dans une base de données pour des performances et d'autres raisons:

  1. Clôture d'une période comptable
  2. Chiffrage de nombre
  3. Processus par lots de nuit
  4. Basculement

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

Des procédures stockées partout

Il y a un certain attrait à 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 de performances et de sécurité maximales que le serveur de base de données pourrait fournir, et ce n'est pas rien.

Mais que risquez-vous?

  1. Verrouillage fournisseur
  2. Le besoin de développeurs avec des compétences particulières
  3. Outils de programmation Spartan, dans l'ensemble
  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 (qui est probablement là où tout cela se dirige, de toute façon), vous devrez toujours le construire.

Alors, quelle est la pratique typique?

Je dirais qu'une approche typique et moderne consiste à utiliser un mappeur objet-relationnel (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 qui est très familière à tout développeur de logiciels compétent. L'ORM génère dynamiquement du 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 et de vues stockées. Cela couvre généralement environ 80% de vos besoins d'accès aux données, principalement CRUD. Que couvre les 20% restants? 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 qui fait 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 du fournisseur, bien compris de tous et mieux pris en charge.

89
Robert Harvey

Je suis fermement partisan de garder la logique métier hors de la base de données autant que possible. Cependant, en tant que développeur de performance de mon entreprise, j'apprécie qu'il soit parfois nécessaire d'atteindre de bonnes performances. Mais je pense que c'est nécessaire beaucoup moins souvent que les gens ne le prétendent.

Je conteste vos avantages et vos inconvénients.

Vous prétendez qu'il centralise votre logique métier. Au contraire, je pense que cela le décentralise. Dans un produit sur lequel je travaille actuellement, nous utilisons une procédure stockée pour une grande partie de notre logique métier. Beaucoup 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 oblige généralement (il peut y avoir des cas où cela est faux) la base de données à exécuter votre fonction N fois, une fois par ligne. Parfois, cette fonction coûte cher. Certaines bases de données prennent en charge les index de fonction. Mais vous ne pouvez pas indexer toutes les fonctions possibles contre chaque entrée possible. Ou pouvez-vous?

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

Un autre problème que je vois appelle les procédures stockées dans une boucle car il n'y a aucun moyen de joindre ou d'intersecter les jeux de résultats de 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 l'encapsulation et les performances.

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 définies)
  3. L'équilibrage de charge
  4. Analyse

Les bases de données sont bonnes pour:

  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 comme les boucles et l'analyse de chaînes et en les conservant dans votre niveau d'application, vous pouvez mettre à l'échelle horizontalement votre application pour obtenir de meilleures performances. L'ajout de plusieurs serveurs d'applications derrière un équilibreur de charge est généralement beaucoup moins cher que la configuration de la réplication de base de données.

Vous avez cependant raison de dire qu'il dissocie votre logique métier du langage de programmation de votre application, mais je ne vois pas pourquoi c'est un avantage. Si vous avez une application Java, alors vous avez une application Java. 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 la base de données concentré sur la persistance. Comment créez-vous un nouveau widget? Vous devez insérer dans 3 tableaux et ils doivent être dans une transaction. Cela appartient à une procédure stockée.

La définition de ce qui peut être fait pour un widget et les règles métier pour trouver des widgets appartiennent à votre application.

17
Brandon

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 (performances). Étant donné que la procédure stockée est compilée, si vous avez une logique complexe pour interroger les données, il est préférable de la conserver dans la base de données elle-même. De plus, il n'enverra les données finales à votre programme qu'à 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 facile de tester la procédure stockée unitaire. N'oubliez pas qu'un programme qui n'est pas testé est un mauvais programme.

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

12

Il y a un terrain d'entente que vous devez trouver. J'ai vu des projets effrayants où les programmeurs utilisent la base de données comme rien de plus qu'un magasin de clé/valeur trop cher. J'en ai vu d'autres où les programmeurs ne parviennent pas à utiliser des clés et des index étrangers. À l'autre bout du spectre, j'ai vu des projets où la plupart sinon la totalité de la logique métier est implémentée dans le code de la base de données.

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

J'essaie de construire un modèle de données raisonnablement décent, j'utilise les fonctionnalités de la base de données pour protéger mes hypothèses sur ce modèle (c'est-à-dire les FK et les contraintes) et j'utilise 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 (c'est-à-dire une somme) que la base de données est très bonne à faire et peut vous épargner de déplacer un million d'enregistrements sur le fil lorsque vous n'en avez pas besoin.

9
Dan Pichelman

Si votre logique métier implique des opérations d'ensemble, il est fort probable qu'elle soit bien placée dans la base de données, car les systèmes de base de données sont vraiment bons pour effectuer des opérations d'ensemble.

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

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

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

9
Jon Raynor

Il n'y a pas de bonne réponse à cela. Cela dépend de l'utilisation de la base de données. Dans une application d'entreprise, vous avez besoin de la logique de la base de données via des clés étrangères, des contraintes, des déclencheurs, etc. car c'est le seul endroit où toutes les applications possibles partagent le code. De plus, mettre 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 préoccupe que du fonctionnement de l'interface graphique, mais je vous assure que les personnes qui essaient d'utiliser les données dans les rapports de conformité trouvent cela très ennuyeux et coûteux lorsqu'ils reçoivent des amendes d'un milliard de dollars pour avoir des données qui ne l'ont pas été. suivez pas les règles correctement.

Dans un environnement non réglementaire lorsque vous ne vous souciez pas autant de l'ensemble des enregistrements et qu'une ou deux applications seulement atteignent la base de données, vous pouvez peut-être vous en sortir en conservant tout dans l'application.

6
HLGEM

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

Une règle de base simple pour moi: 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 changé en une expression), mettez-le dans le code.

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

Les tentatives de placer vraiment toute la logique métier dans le code d'application dégénéreront probablement la base de données (relationnelle) en un vidage, où la conception relationnelle est principalement à complètement omise, où les données peuvent avoir un état incohérent et la normalisation est manquante (souvent principalement XML, JSON , Colonnes 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 avec l'inconvénient que l'application doit prendre soin de toute la logique elle-même, ce qui est intégré dans la base de données relationnelle depuis des décennies. Cependant, les bases de données NoSQL conviennent mieux à ce type de traitement des 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 simplement d'abus, ce qui cause toujours plus de problèmes.

Expressions (basées sur un ensemble) au lieu du 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 procédural. Un grand support pour cela est lorsque les langages de programmation prennent en charge les expressions, telles que LINQ dans le monde .NET (malheureusement, seules les requêtes actuellement, aucune manipulation). Du côté de la base de données relationnelle, il a été enseigné depuis longtemps, à préférer les expressions d'instructions SQL aux boucles de curseur procédurales. Ainsi, la base de données peut optimiser, faire l'opération en parallèle, ou tout ce qui peut être utile.

tiliser les mécanismes d'intégrité des données DB

En ce qui concerne le SGBDR avec les contraintes de clé étrangère et de vérification, les colonnes calculées, éventuellement les déclencheurs et les 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 permet de 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 des 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. L'argument de précompilation pour les SP n'est donc 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 qui peuvent être traduites en SQL.

Bien que le côté application, y compris l'ORM généré, SQL, ne soit plus à l'intérieur de la base de données, contrairement aux procédures stockées, je le compte toujours comme code de base de données. Parce qu'il nécessite toujours des connaissances SQL et de base de données (à l'exception du CRUD le plus simple) et, s'il est appliqué correctement, fonctionne très différemment du code procédural habituellement créé avec des langages de programmation comme C # ou Java.

3
Erik Hart

Cela dépend vraiment de l'entreprise, de sa culture et de son héritage. Hormis les considérations techniques (celles-ci ont été couvertes des deux côtés), les réponses données vous indiquent que cela dépend de la provenance des gens. Dans certaines organisations, les données sont roi et le DBA est une figure puissante. Il s'agit de votre environnement centralisé typique, un centre de données avec un tas de terminaux attachés. La préférence dans ce type d'environnement est claire. Le bureau peut changer radicalement plusieurs fois avant que quoi que ce soit ne change dans le centre de données et il y aura peu 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. Vous entendrez probablement une histoire différente ici. Le DBA, s'il y en a, ne sera qu'un compagnon qui effectuera certaines tâches administratives.

Un développeur d'applications des temps modernes aura plus d'affinité avec le deuxième 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 technique impliqués ici, il n'y a pas de réponse générale à cette question.

2
Martin Maat

Le terme logique métier est sujet à 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, il devrait y avoir différentes autorisations d'accès utilisateur en place. À titre d'exemple très simple, considérons une application ATM.

Pour obtenir le solde du compte, faire une sélection sur une vue appropriée devrait convenir. Mais pour transférer des fonds, vous souhaitez que la transaction soit encapsulée par une procédure stockée. La logique métier ne devrait pas être autorisée à mettre à jour directement les tableaux des montants de crédit et de débit.

Dans cet exemple, la logique métier peut vérifier le solde avant de demander le transfert ou simplement appeler le proc stocké pour le transfert et signaler l'échec. À mon humble avis, la logique métier, dans cet exemple, devrait vérifier de manière préventive que les fonds suffisants sont disponibles et que le compte cible existe et ensuite invoquer les fonds de transfert. Si un autre débit se produit entre les étapes initiales et l'appel de proc stocké, alors seulement une erreur sera renvoyée.

2
CyberFonic