Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Modérateur

    Contrôle des données saisies par l'utilisateur de l'application, où le mettre ?
    Bonjour,

    Je viens de relire le papier de SQLPro sur le développement en base de données épaisse et je suis toujours convaincu de sa pertinance.

    Néanmoins, j'ai des doutes - et mes collègues développeurs ou mon chef encore plus - sur la pertinence de mettre le contrôle des données saisies par l'utilisateur applicatif dans le code de la BDD.

    Soit un formulaire de saisie avec de multiples champs. Ma maîtrise actuelle du concept de développement en BDD épaisse fait que la première donnée issue de ce formulaire qui ne sera pas conforme à sa règle (trop longue, hors plage acceptable...) mettra fin à la procédure d'enregistrement et renverra un message d'erreur à l'application.
    L'utilisateur corrige la donnée et renvoie le formulaire et, malchance, une autre donnée inacceptable déclenche un nouveau message d'erreur et ainsi de suite jusqu'à ce que toutes les données soient acceptées par la procédure SQL de traitement.

    Alors que si les contrôles des données saisies sont fait dans l'application, on peut indiquer à l'utilisateur en une seule fois tout ce qui ne va pas afin qu'il corrige tout en bloc et ne soumette le formulaire qu'une seule autre fois. Avec Javascript, on peut même l'informer en temps réel des problèmes avant même qu'il soumette son formulaire renseigné.

    Y a t-il une solution pratique pour que les problèmes rencontrés sur le jeu de données fournies à la procédure SQL soient en quelque sorte stockés puis renvoyés en une seule fois à l'application ?

    Ce problème rejoint un peu celui que j'avais posé en octobre 2018 quant à l'enchaînement de procédures SQL. J'imagine en effet qu'on pourrait lancer une procédure qui ouvre une transaction et en appelle une à plusieurs autres, le tout n'étant commité que si toutes les procédures secondaires se sont déroulées sans retourner d'erreur. Dans le cas contraire, enregistrement par exemple dans une table d'erreurs ou un fichier de log l'ensemble des problèmes renvoyés puis ROLLBACK et renvoi à l'application d'un résultat d'échec du traitement.
    Et là j'ai un peu de mal à voir comment faire... surtout que je travaille avec MySQL, ou à la maison sur un projet personnel avec PostgreSQL.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  2. #2
    Expert éminent sénior
    Bonsoir Philippe

    Je ne saurai pas répondre complètement à la question posée, mais je fais quand même deux observations :
    • on peut rarement contrôler tous les éléments d'un formulaire puisque la validité de certains éléments dépend du contenu d'autres éléments.
    • sur un formulaire comportant de nombreuses zones de saisie ou de sélection, mentionner toutes les erreurs est mission impossible sauf à avoir une énorme pop-up avec toutes les explications sur chacune des erreurs


    Du coup, on ne peut pas s'éviter des allers-retours entre l'application et la BDD, un contrôle de surface côté application reste possible pour limiter la casse.

  3. #3
    Membre expert
    Citation Envoyé par CinePhil Voir le message
    Bonjour,
    Je viens de relire le papier de SQLPro sur le développement en base de données épaisse et je suis toujours convaincu de sa pertinance.
    Moi non ... et par principe ...

    Vu la suffisance et le mépris du personnage envers tout ceux qui ne sont pas d'accord avec lui (et Dieu sait si ils sont nombreux ici ! ), je me méfie désormais comme de la peste ( ou du Coronavirus ) de ses vérités révélées qu'il nous assène à longueur de messages et avec une argumentation particulièrement faible et / ou hargneuse ...

  4. #4
    Modérateur

    Citation Envoyé par CinePhil Voir le message
    Néanmoins, j'ai des doutes - et mes collègues développeurs ou mon chef encore plus - sur la pertinence de mettre le contrôle des données saisies par l'utilisateur applicatif dans le code de la BDD.
    Je pense qu'il faut les deux. Le contrôle de saisie au niveau de l'applicatif pour l'expérience utilisateur, et les contrôles d'intégrités relationnelles et de domaines dans la base pour la qualité de la base.
    Même si ça ressemble à une double implémentation de la même fonctionnalité, la finalité n'est pas la même.
    Les contraintes multi-tables sont forcément à faire côté base de données.

  5. #5
    Rédacteur

    Il n'est pas possible de simuler les contrôles que font les SGBDR en les mettant dans les applications, à l'exception des contrôles de domaines et a condition que vous n'ayez qu'une seule application !

    je démontre cela régulièrement dans mes cours....

    En effet, imaginons la situation suivante... Dans un formulaire de saisie, deux dates. Celle de début et celle de fin. L'application effectue un contrôle de saisie lors d'un événement, pas exemple au moment de l'appui sur le bouton OK. Ce contrôle valide que la date de début soit inférieure à la date de fin....
    La situation est la suivante au départ :


    Comme une base de données est accedé par de multiples utilisateurs simultanément, voici ce que fait l'utilisateur A :

    On voit bien que le 10/1/2020 est inférieur au 15/1/2020. L'UPDATE de la date de début est alors envoyé au SGBDR....

    L'utilisateur B, à ouvert au même moment que A la fenêtre de saisie et se livre à la modification suivante :

    On voit bien que le 01/1/2020 est inférieur au 5/1/2020. L'UPDATE de la date de fin est alors envoyé au SGBDR....

    Dans tous les cas, chacune des fenêtres de saisie valide parfaitement que la date de début du formulaire est bien inférieure à la date de fin !

    En base de données, à la fin de la saisie des 2 utilisateurs A et B, les valeurs de ces deux informations sont les suivantes :
    • Date de début = 10/1/2020
    • Date de fin = 05/01/2020

    la base est donc logiquement corrompue !
    Seul une contrainte SQL aurait pu pallier cette anomalie et rejeter l'une des deux saisies....

    Pour le cas de la contrainte de domaine (rappel : 1 informations à saisir => un domaine qui est l'ensemble des valeurs possible pour cette information) cela ne pose pas de problème...
    Mais si vos données viennent de différentes sources :
    • plusieurs applications,
    • un ETL,
    • un outil d'import/export...

    ... alors il faudra mettre les contrôles dans TOUS les outils et toutes les applications !
    Malheureusement, on constate en pratique, que c'est rarement le cas !

    A +
    Cette signature n'a pas pu être affichée car elle comporte des erreurs.

  6. #6
    Modérateur

    Merci Frédéric pour cet éclairage.
    Néanmoins, dans le cas particulier qui m'occupe actuellement, il sera très peu probable que deux personnes modifient le même groupe d'informations en même temps.
    Je vais transmettre à mes collègues mais je doute que l'argument soit suffisant.

    J'ai obtenu hier l'utilisation de procédures stockées pour la partie de l'application qui sera accessible depuis Internet, pour limiter au maximum les actions d'un éventuel pirate qui prendrait le contrôle du serveur applicatif. Voir cette discussion. C'est déjà ça.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  7. #7
    Expert éminent
    Pour ma part, je fais généralement un mix des deux :
    - Contrôle de la validité des types, cohérence fonctionnelle dans l'application
    - Contrôle d'intégrité dans le SGBD

    Ceci évite d'envoyer au SGBD des informations qu'on sait pertinemment fausses.
    La difficulté réside surtout, au retour du SGBD, d'interpréter le message d'erreur afin d'éviter de planter sauvagement ou d'afficher un message barbare (message d'erreur SQL) ou trop bateau ("une erreur s'est produite").
    Pour ce faire généralement je passe par une procédure stockée ou trigger qui revalide un coup le plus de règles possibles avant d'envoyer les données au moteur SQL : ça permet d'obtenir des messages d'erreur claires dans un maximum de cas, et simplifie le travail pour les cas restants.

    Le gros avantage de repasser par une PS ou trigger de validation, c'est que si les données sont modifiée hors application mais par un traitement externe (interface, mise à jour direct SQL, etc.) on ne passe pas outre les validations.
    On ne jouit bien que de ce qu’on partage.

  8. #8
    Modérateur

    Le gros avantage de repasser par une PS ou trigger de validation, c'est que si les données sont modifiée hors application mais par un traitement externe (interface, mise à jour direct SQL, etc.) on ne passe pas outre les validations.
    Avec un trigger, oui.
    Mais si on n'a qu'une procédure stockée et pas de trigger et qu'on fait une requête INSERT ou UPDATE à la place de la PS...
    D'où l'utilité, aussi, de ne pas donner ces privilèges à n'importe quel user.

    Au final, je pense qu'on va effectivement avoir un mix des deux. Comme c'est surtout moi qui vais développer la partie BDD, je crois que je ne vais pas me priver de mettre des contrôles dans les PS que je mettrai à dispo des développeurs PHP !
    Comme ça si un jour ils reçoivent un message venant d'une de mes PS pendant leurs tests, ils en comprendront peut-être l'utilité !

    Merci à tous pour vos avis.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  9. #9
    Expert éminent
    SqlPro: si les deux dates sont mises à jour dans une seule transaction, le cas ne peut pas se produire.

    Quoi qu'il en soit, chez nous c'est ceinture et bretelles: contrôle dans l'application (pour la "cohérence" de la saisie),et dans la base de données (pour l'intégrité des données), tout comme StringBuilder.

    Ainsi si un bug permet par exemple de supprimer un article présent dans un autre table, la base ne laissera pas passer (et l'application ne passera pas la phase de test ).

    Tatayo.

  10. #10
    Expert éminent
    Citation Envoyé par CinePhil Voir le message
    Avec un trigger, oui.
    Mais si on n'a qu'une procédure stockée et pas de trigger et qu'on fait une requête INSERT ou UPDATE à la place de la PS...
    D'où l'utilité, aussi, de ne pas donner ces privilèges à n'importe quel user.
    Oui en effet.
    Ce que j'ai à plusieurs reprises mis en place : deny d'accès sur l'ensemble des tables.
    Exposition de vues uniquement pour la lecture.
    Et procédure stockées pour tout le reste.
    => Du coup dans ce cas, traitement externe ou pas, obligé de passer par les PS J'aurais dû l'indiquer en effet
    Le bémol par contre c'est qu'il devient plus "compliqué" de faire des petites évolutions à la petite semaine : on est obligé à chaque fois de redévelopper une nouvelle PS ou en modifier une, modifier les vues, etc.
    Ca peut être contraignant sur certains projets ou pour certains besoins (genre inclure de la BI directement dans le programme, où on va vouloir interroger dynamiquement tout et n'importe quoi).
    On ne jouit bien que de ce qu’on partage.

  11. #11
    Expert éminent
    Citation Envoyé par tatayo Voir le message
    SqlPro: si les deux dates sont mises à jour dans une seule transaction, le cas ne peut pas se produire.

    Quoi qu'il en soit, chez nous c'est ceinture et bretelles: contrôle dans l'application (pour la "cohérence" de la saisie),et dans la base de données (pour l'intégrité des données), tout comme StringBuilder.

    Ainsi si un bug permet par exemple de supprimer un article présent dans un autre table, la base ne laissera pas passer (et l'application ne passera pas la phase de test ).

    Tatayo.
    Le cas peut surtout se produire si on utilise des objets de haut niveau dans l'application.
    En effet, la méthode "old school" c'est : "j'ai trois champs dans mon formulaire, alors j'ai un update col1 = @val1, col2 = @val2, col3 = @val3 where id = @id"

    Seulement, la plupart des outils de haut niveau (y compris un simple datagridview .NET) ne vont réellement demander au SGBD de modifier QUE ce qui a changé dans lors de la saisie : update col2 = @val2 where id = @id

    Et là on tombe direct sur le souci évoqué par SQLPro, car si col1 ou col3 ont été mis à jour entre le chargement du formulaire et sa validation, boum !
    J'ai envie de dire, dans ce cas là, il faut locker la ligne à la lecture. Mais ça peut vite devenir bloquant pour les autres traitement... surtout si Ginette va fumer sa clope et tombe sur sa copine Germaine de la compta...
    On ne jouit bien que de ce qu’on partage.

  12. #12
    Rédacteur

    Citation Envoyé par tatayo Voir le message
    SqlPro: si les deux dates sont mises à jour dans une seule transaction, le cas ne peut pas se produire.
    Absurde !

    Comment veut tu avec 2 utilisateurs différents ayant chacun leur écran effectuer une transaction ?

    A +
    Cette signature n'a pas pu être affichée car elle comporte des erreurs.

  13. #13
    Modérateur

    Citation Envoyé par StrinBuilder
    Exposition de vues uniquement pour la lecture.
    Et procédure stockées pour tout le reste.
    C'est ce que je suis en train de faire.
    Le user utilisé par l'application n'aura que les privilèges SELECT et EXECUTE sur la BDD de l'application et SELECT seul sur la BDD du référentiel. Du coup, vues et procédures SQL.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  14. #14
    Membre averti
    Citation Envoyé par SQLpro Voir le message
    Absurde !

    Comment veut tu avec 2 utilisateurs différents ayant chacun leur écran effectuer une transaction ?

    A +
    Ce qu'il voulait dire, je pense, c'est que la date de début et la date de fin sont systématiquement mises à jour pour chaque transaction, et donc contrôlées. Et je suis plutôt d'accord avec tatayo. Dans ce genre de situation je n'enregistrerais pas uniquement ce qui a changé, ça craint d'ailleurs une appli qui ferait ça. C'est le dernier qui enregistre qui a raison.

  15. #15
    Expert éminent
    Citation Envoyé par vanagreg Voir le message
    ça craint d'ailleurs une appli qui ferait ça. C'est le dernier qui enregistre qui a raison.
    Malheureusement c'est ce que font tous les framework de "haut niveau".

    Après, c'est ni bien (risque évoqué par sqlpro) ni mal (pourquoi envoyer et mettre à jour 20 Mo de données alors que seul 1 octet a réellement changé ?), il faut juste avoir conscience des risques et adapter son code en fonction.

    Dans tous les cas, tout contrôle d'intégrité doit être de toute façon revalidé par le SGBD, ne serait-ce que parce-que c'est lui seul qui est capable de centraliser les contrôles, et le seul qu'on ne pourra pas court-circuiter.

    Combien de fois j'ai vu des applications se mettre à faire de la merde après une mise à jour d'un module... alors que les autres modules continuent à travailler avec d'anciennes règles de validation pas à jour ?

    Pas plus tard que la semaine dernière j'ai passé 3 jours à restaurer des données chez un client où une application dont 100% des contraintes référentielles étaient dans le code et qu'elle est devenue folle : elle s'est mise à supprimer des données qu'elle croyait orpheline, alors que simplement l'utilisateur qui avait lancé le traitement n'avait pas les droit d'accéder à leur données parentes !

    Dans une CRM, 100 000 contacts supprimés, ça la fout mal pour bosser
    On ne jouit bien que de ce qu’on partage.

  16. #16
    Membre averti
    On est d'accord, mettre des contraintes autant que faire se peut au niveau modèle de données. Je ne pense pas qu'il faille envoyer systématiquement toutes les informations, mais dans ce genre de cas (end_date > start_date) je pense qu'il est facile d'ajouter un contrôle.
    J'ai également eu l'occasion de travailler sur des modèles pourris comme Générix, heureusement pas longtemps. A partir de l'instant où tu stockes des dates dans des varchar2 c'est même pas la peine d'aller plus loin...

  17. #17
    Expert éminent
    Citation Envoyé par vanagreg Voir le message
    On est d'accord, mettre des contraintes autant que faire se peut au niveau modèle de données. Je ne pense pas qu'il faille envoyer systématiquement toutes les informations, mais dans ce genre de cas (end_date > start_date) je pense qu'il est facile d'ajouter un contrôle.
    J'ai également eu l'occasion de travailler sur des modèles pourris comme Générix, heureusement pas longtemps. A partir de l'instant où tu stockes des dates dans des varchar2 c'est même pas la peine d'aller plus loin...
    GCE rulez !

    Bof, j'hésite entre ce qui est pire : Generix qui stocke les dates dans un varchar2 et Update qui stocke ça dans un bigint...
    Pas étonnant que ce soit Aurea qui ait racheté les deux !

    Youpi, ma boîte distribue les deux
    On ne jouit bien que de ce qu’on partage.

  18. #18
    Membre averti
    Y'a vraiment un produit qui s'appelle Update? Super choix, déjà rien que ça c'est une merveille. Pour les recherches sur ce produit ça doit être génial. Pourquoi pas Table ou Select

  19. #19
    Expert éminent
    Oui oui
    https://www.celge.fr/editeurs/update...elation-client

    On distribuait du Generix, et un jour la branche ERP a été rachetée par Aurea qui a pour ainsi dire stoppé complètement le produit.

    Du coup on a cherché un autre outil sur lequel se former pour le distribuer.

    On est tombé sur Update (un très bon produit cela dit, tout comme Generix était un très bon produit)... on en a vendu 2 ans et il a été racheté par Aurea aussi !

    Evidement, même politique : plus aucune évolution.

    On commence tout juste à revoir une roadmap qui ressemble à quelque chose, après quelques années.
    La misère quoi
    On ne jouit bien que de ce qu’on partage.

  20. #20
    Expert éminent
    Citation Envoyé par SQLpro Voir le message
    Absurde !

    Comment veut tu avec 2 utilisateurs différents ayant chacun leur écran effectuer une transaction ?

    A +
    Je m'aperçois en me relisant que ma réponse n'était pas claire du tout. Ça m'apprendra à répondre trop vite.
    J'étais resté sur le fonctionnement des applications que nous utilisons (celles que nous avons développées, et les applications externes) : deux utilisateurs ne peuvent pas modifier la même ressource en même temps (même depuis deux applications différentes).
    Mais pour nos applications internes il y a un max de contraintes dans la base, contrairement aux applications externes, qui n'ont aucune règle d'intégrité au niveau SGBD (qui dans certains cas n'utilisent même pas de transactions !).
    Nous n'utilisons pas de framework "de au niveau" car il n'y en a pas dans le langage que nous utilisons, donc tout (ou presque) est systématiquement mis à jour.
    Si effectivement une ressource peut être modifiées "en même temps", une simple transaction ne suffit pas.

    Petite anecdote: quand j'ai mis tout ça en place, j'avais mis une contrainte dans la base pour bloquer un prix de revient négatif. Et quand j'ai récupéré l'intégralité de la base article, pan, certains fiches étaient rejetées à cause de cette contrainte.
    Oui, l'ERP autorise des prix de revient négatifs.
    J'ai donc du la supprimer, même si elle me semble (semblait) incontournable.

    Tatayo.