Suite à une discussion intéressante avec des collègues, nous nous sommes posés la question suivante : « nos données, pour les applications que nous réalisons doivent être maintenues en cohérence suivant les règles métiers de l’application ; faut-il coder ces mécanismes dans la partie modèle du logiciel ou directement dans la base de données ? ».
Par exemple, lors d’un enregistrement d’une donnée sur la table A, il faut mettre à jour la table B. On peut envisager deux manières :
{1/ fabriquer un {trigger (ou gachette, voire déclencheur, en french) dans notre base de données qui va automatiquement se charger de cela}}
Par exemple sous Oracle :
CREATE TRIGGER trigger_insertion
AFTER INSERT ON table_A
FOR EACH ROW
WHEN (NEW.col_a <= 10)
BEGIN
INSERT INTO table_B VALUES(:NEW.col_b, :NEW.col_a) ;
END ;
2/ surcharger la classe gérant l’enregistrement de la table A avec un code particulier s’occupant de notre table B
Par exemple avec PHP et propel :
<?php
// on surcharge la fonction save de la classe métier gérant la table A
public function save() <em>if ($this->getColA() <= 10) {
$tableB = new TableB() ;
$tableB->setColA = $this->getColB() ;
$tableB->setColB = $this->getColA() ;
$tableB->save() ;
</em>
return parent ::save
}
?>
Le trigger est beaucoup plus performant en terme de ressources hardware, il permet aux développeurs du code PHP (dans notre exemple) de faire complètement abstraction de cette problématique de mise à jour. Il évite également des aller-retour entre le serveur de base données et le serveur applicatif. D’un point de vue purement technique c’est une option assez tentante.
Un autre argument pour le trigger est que deux applications différentes (un batch et un client lourd par exemple) peuvent profiter de l’intelligence du trigger.
Toutefois, il est nécessaire de prendre en compte quelques autres paramètres :
La portabilité
En intégrant un trigger dans votre application, celle ci devient dépendante du type de base de données. En pratique cela pose généralement peu de problèmes :
– les changements de bases de données au sein d’un SI sont peu fréquents et souvent faits à un rythme inférieur à la production des applications
– le coût de réécriture des triggers sera vraisemblablement marginal par rapport à l’ensemble du coût d’une éventuelle migration
La dispersion de l’intelligence métier
En écrivant votre logique métier dans le code l’application et des triggers, on la décrit à deux endroit différents. De plus, les traitements inclus dans les triggers ne sont pas forcément accessibles lors de l’édition du code applicatif, et vice versa. On augmente finalement les possibilités de ne plus s’y retrouver. Il faudra produire et maintenir une documentation de qualité pour faire diminuer ce risque.
La dispersion des compétences
C’est à mes yeux le problème le plus important. En plus de produire un système documentaire complet, il faudra maintenir des compétences sur votre application en elle même ainsi que sur votre base de données « intelligente ». Il faudra donc être sûr de disposer de la compétence d’un DBA[[DataBase Administrator]] capable de dialoguer fréquemment avec vos équipes.
L’argument du gain de performance est peu valable, au vu des coûts actuels du hardware par rapport à la prestation intellectuelle. Reste à voir si vous avez vraiment besoin d’un système de gestion de données autonome. Si oui, il faudra vraisemblablement en faire plus et exposer vos données via des web services, par exemple, qui feront idéalement complètement abstraction du modèle relationnel. Je vous conseille donc de ne pas installer de triggers pour vos applications ; ou au moins pas avant d’avoir bien évalué les risques liés à leurs utilisations.
Julien T
6 juin 2007
Tout à fait d’accord sur la conclusion de l’article. Pour moi le point le plus limitant est la maintenabilité de telles pratiques.
J’ai eu l’occasion d’auditer une application qui contenait une grande partie de sa logique métier dans des triggers Oracle et des procédures stockées. D’un point de vue extérieur, impossible de pénétrer dans le code et de comprendre rapidement le fonctionnement de l’application. Pas vraiment de vérification de syntaxe pour les triggers, messages d’erreur assez obscures quand il y a un problème, etc..
J’en profite pour ajouter que je lis ce blog depuis quelques temps et je le trouve très intéressant et enrichissant ! Merci donc.
loïc m.
6 juin 2007
J’ai récemment étais confronté à cette problématique.
La décision finale a été de ne pas utiliser de triggers pour comme vous le dites, éviter la dispersion de l’intelligence métier.
Au moins là, on a toute la logique métier à un endroit précis, ce qui devient beaucoup plus facile pour la maintenance de l’application, ainsi que pour sa documentation.
TristanM
7 juin 2007
Sur le fond, je suis d’accord que l’utilisation de triggers complexifie pas mal la maintenance, et nous lie plus ou moins à l’éditeur.
Cependant, comment faire lorsque l’on a plusieurs applications indépendantes, l’une allant modifier la table, et l’autre devant être notifiée en cas de changement de cette table ?
Le trigger est une solution. L’autre solution serait d’implémenter une couche logicielle intermédiaire entre les applications et la base , afin que les applications puissent s’enregistrer et être notifiées, mais j’ai l’impression que c’est assez compliqué surtout dans le cas d’applis codées dans des langages hétérogènes, non ?
Olivier Mansour
12 juin 2007
« L’autre solution serait d’implémenter une couche logicielle intermédiaire entre les applications et la base , afin que les applications puissent s’enregistrer et être notifiées, mais j’ai l’impression que c’est assez compliqué surtout dans le cas d’applis codées dans des langages hétérogènes, non »
En fait, une architecture orientée services répondrait élégamment à ce besoin. En pratique, je te l’accorde, c’est moins évident qu’il n’y parait et il n’y a pas que la technique qui pose problème … mais c’est un autre débat !
Hadrien Huvelle
3 septembre 2010
Très belle explication.
Très nette, très claire.
Qui plus est, je suis parfaitement d’accord!
Tks
Hadrien