{"id":323,"date":"2013-01-28T14:51:48","date_gmt":"2013-01-28T13:51:48","guid":{"rendered":"http:\/\/qualilogy.com\/fr\/?p=323"},"modified":"2013-01-28T17:07:57","modified_gmt":"2013-01-28T16:07:57","slug":"bonnes-pratiques-de-programmation-abap-les-defauts-critiques","status":"publish","type":"post","link":"http:\/\/qualilogy.com\/fr\/bonnes-pratiques-de-programmation-abap-les-defauts-critiques\/","title":{"rendered":"Bonnes pratiques de programmation ABAP &#8211; Les d\u00e9fauts critiques"},"content":{"rendered":"<p><a href=\"http:\/\/vicken.deviantart.com\/\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-324\" alt=\"Qualilogy - Les d\u00e9fauts critiques en programmation ABAP\" src=\"http:\/\/qualilogy.com\/fr\/wp-content\/uploads\/sites\/2\/2013\/01\/Qualilogy_ABAP_20130127.jpg\" width=\"359\" height=\"240\" srcset=\"http:\/\/qualilogy.com\/fr\/wp-content\/uploads\/sites\/2\/2013\/01\/Qualilogy_ABAP_20130127.jpg 359w, http:\/\/qualilogy.com\/fr\/wp-content\/uploads\/sites\/2\/2013\/01\/Qualilogy_ABAP_20130127-300x200.jpg 300w\" sizes=\"(max-width: 359px) 100vw, 359px\" \/><\/a>Nous avons vu dans le post pr\u00e9c\u00e9dent <a title=\"Bonnes pratiques de programmation ABAP - Les blockers\" href=\"http:\/\/qualilogy.com\/fr\/bonnes-pratiques-de-programmation-abap-les-blockers\/\" target=\"_blank\">les violations les plus graves aux bonnes pratiques de programmation ABAP<\/a>.<\/p>\n<p>Ces d\u00e9fauts sont bloquants : le code correspondant ne peut aller en production tant qu\u2019une correction n\u2019est pas effectu\u00e9e. Aucune exception n\u2019est permise : tol\u00e9rance z\u00e9ro, car le risque est trop \u00e9lev\u00e9 de voir une transaction interrompue et l\u2019utilisateur incapable d\u2019effectuer le traitement souhait\u00e9. <!--more--><\/p>\n<p>Nous avons \u00e9galement param\u00e9tr\u00e9 notre Quality Profile ABAP de mani\u00e8re \u00e0 identifier les d\u00e9fauts critiques, ceux-ci portant principalement sur la performance, et que nous allons voir dans cet article.<\/p>\n<p><a href=\"http:\/\/qualilogy.com\/fr\/wp-content\/uploads\/sites\/2\/2013\/01\/SONAR_ABAP_LOC.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignright size-full wp-image-331\" alt=\"Mon application ABAP\" src=\"http:\/\/qualilogy.com\/fr\/wp-content\/uploads\/sites\/2\/2013\/01\/SONAR_ABAP_LOC.jpg\" width=\"286\" height=\"114\" \/><\/a> J\u2019ai oubli\u00e9 de le pr\u00e9ciser la derni\u00e8re fois, mais mon analyse ABAP porte sur environ 700 fichiers repr\u00e9sentant plus de 43 000 lignes dont environ 26 000 lignes de code (le reste est du commentaire). Ceci pour vous donner un peu une id\u00e9e du nombre de d\u00e9fauts par rapport \u00e0 la taille de l\u2019application.<\/p>\n<p>Les probl\u00e8mes de performance rel\u00e8vent principalement de bonnes pratiques non respect\u00e9es en mati\u00e8re de traitements SQL. A ce titre, ils ne sont pas sp\u00e9cifiques au code ABAP. Ci-dessous, les plus nombreux :<\/p>\n<p><a href=\"http:\/\/qualilogy.com\/fr\/wp-content\/uploads\/sites\/2\/2013\/01\/SONAR_ABAP_Critical1.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-330\" alt=\"SONAR et ABAP : les d\u00e9fauts les plus critiques\" src=\"http:\/\/qualilogy.com\/fr\/wp-content\/uploads\/sites\/2\/2013\/01\/SONAR_ABAP_Critical1.jpg\" width=\"583\" height=\"202\" srcset=\"http:\/\/qualilogy.com\/fr\/wp-content\/uploads\/sites\/2\/2013\/01\/SONAR_ABAP_Critical1.jpg 583w, http:\/\/qualilogy.com\/fr\/wp-content\/uploads\/sites\/2\/2013\/01\/SONAR_ABAP_Critical1-300x103.jpg 300w\" sizes=\"(max-width: 583px) 100vw, 583px\" \/><\/a><\/p>\n<p>Le SELECT * est une pratique \u00e0 proscrire dans tous les langages, puisque cette requ\u00eate ram\u00e8ne toutes les colonnes de la table. Si le nombre de lignes retourn\u00e9es est \u00e9galement important, alors la taille des donn\u00e9es \u00e0 transporter sur le r\u00e9seau risque d\u2019impacter la performance. De plus, si des colonnes sont ajout\u00e9es ult\u00e9rieurement dans la table, les donn\u00e9es correspondant \u00e0 ces nouvelles colonnes seront dans le SELECT * alors qu\u2019elles ne sont pas utilis\u00e9es.<\/p>\n<p>Un SELECT DISTINCT permet d\u2019\u00e9viter les lignes dupliqu\u00e9es, lorsque vous avez plus d\u2019une fois un m\u00eame enregistrement. Le probl\u00e8me est que ce traitement est tr\u00e8s lourd en termes de performance, surtout si certains des champs utilis\u00e9s avec la clause DISTINCT ne sont pas index\u00e9s. De plus, il faut s\u2019assurer que ce traitement soit utile car il arrive assez souvent qu\u2019il n\u2019y ait pas de lignes en double. Enfin, il est souvent possible d\u2019\u00e9viter ce traitement en repensant et programmant diff\u00e9remment la clause WHERE.<\/p>\n<p>D\u2019une mani\u00e8re g\u00e9n\u00e9rale, il n\u2019est pas recommand\u00e9 d\u2019acc\u00e9der \u00e0 une base de donn\u00e9es \u00e0 travers une boucle, surtout pour des traitements de mise \u00e0 jour des donn\u00e9es (INSERT, UPDATE, MODIFY, DELETE). G\u00e9n\u00e9ralement, la boucle indique que l\u2019on parcourt une table ou un ensemble d\u2019enregistrements afin d\u2019effectuer cette mise-\u00e0-jour. Le probl\u00e8me de performance peut s\u2019av\u00e9rer infime pour une nouvelle application avec une table contenant peu d\u2019enregistrements, mais au fil du temps les donn\u00e9es vont s\u2019ajouter dans cette table, sa taille va grandir, la boucle sera de plus en plus longue et les probl\u00e8mes de performance commenceront \u00e0 appara\u00eetre.<\/p>\n<p>Un SELECT sans condition, c&rsquo;est-\u00e0-dire sans clause WHERE, ram\u00e8ne tous les enregistrements de la table. Il est souvent l\u2019indication d\u2019une erreur de programmation (oubli) ou d\u2019une programmation incorrecte. L\u00e0 encore, avec l\u2019ajout au fil du temps de donn\u00e9es dans la table, ce SELECT occasionnera un probl\u00e8me de performance.<\/p>\n<p>Ah, nous avons quand m\u00eame dans ces r\u00e8gles critiques une bonne pratique qui ne touche pas \u00e0 la performance, mais \u00e0 la stabilit\u00e9 de l\u2019application. Une instruction CASE \u2026 ENDCASE permet d\u2019effectuer diff\u00e9rents traitements (branchements) selon les diff\u00e9rentes valeurs d\u2019une variable ou d\u2019un champ. La clause OTHERS permet de pr\u00e9voir tous les autres cas (toutes les autres valeurs) non trait\u00e9s sp\u00e9cifiquement par le CASE. C\u2019est une simple question de gestion des erreurs : si un cas non pr\u00e9vu survient, l\u2019absence de la clause OTHERS signifie qu\u2019aucun traitement particulier ne sera effectu\u00e9. Le programme continuera de s\u2019ex\u00e9cuter, peut-\u00eatre de mani\u00e8re erron\u00e9 ou avec des valeurs incorrectes. Le risque est \u00e9lev\u00e9 que survienne une erreur et qu\u2019elle ne soit pas trait\u00e9e. De plus, cette erreur surviendra g\u00e9n\u00e9ralement bien plus loin dans le code, et donc la d\u00e9tection de son origine sera souvent assez longue et co\u00fbteuse en termes de maintenance.<br \/>\nCertains clients consid\u00e8rent que cette \u2018bad practice\u2019 est un Blocker : je suis assez d\u2019accord avec cela.<\/p>\n<p><a href=\"http:\/\/qualilogy.com\/fr\/wp-content\/uploads\/sites\/2\/2013\/01\/SONAR_ABAP_Critical2.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-332\" alt=\"SONAR et ABAP : les d\u00e9fauts les plus critiques\" src=\"http:\/\/qualilogy.com\/fr\/wp-content\/uploads\/sites\/2\/2013\/01\/SONAR_ABAP_Critical2.jpg\" width=\"531\" height=\"170\" srcset=\"http:\/\/qualilogy.com\/fr\/wp-content\/uploads\/sites\/2\/2013\/01\/SONAR_ABAP_Critical2.jpg 531w, http:\/\/qualilogy.com\/fr\/wp-content\/uploads\/sites\/2\/2013\/01\/SONAR_ABAP_Critical2-300x96.jpg 300w\" sizes=\"(max-width: 531px) 100vw, 531px\" \/><\/a><\/p>\n<p>Si nous regardons les d\u00e9faut suivants dans le code, on remarque que ceux-ci portent \u00e0 nouveau sur la programmation SQL.<\/p>\n<p>Un UPDATE ou un DELETE sans clause WHERE signifie une mise-\u00e0-jour ou une suppression de l\u2019ensemble des lignes de la table. Mieux vaut s\u2019assurer que c\u2019est bien le traitement esp\u00e9r\u00e9 et non pas\u00a0 une erreur !<\/p>\n<p>SAP propose un syst\u00e8me de buffer qui permet de lire une table directement depuis celui-ci et non pas depuis la base de donn\u00e9es, dans un objectif de meilleure performance. Or des traitements tels qu\u2019un JOIN ou des fonctions de calcul impliquant une agr\u00e9gation (COUNT, AVG, MAX, MIN, etc.) on pour effet d\u2019interdire l\u2019utilisation de ce buffer. Et cela, le programmeur ne le sait pas toujours !<\/p>\n<p>A fortiori, un traitement qui \u2018bypasse\u2019 le buffer \u2013 c\u2019est-\u00e0-dire \u00e9vite volontairement celui-ci \u2013 devra \u00eatre s\u00e9rieusement justifi\u00e9.<\/p>\n<p>Enfin, l\u2019utilisation d\u2019une clause LIKE ne permet pas, une fois de plus, de pr\u00e9dire le nombre d\u2019enregistrements retourn\u00e9s, notamment lorsque la table cro\u00eet au fil du temps. Et les queries imbriqu\u00e9s (SELECT \u2026 IN \u2026 SELECT) sont \u00e0 \u00e9viter, dans tous les langages.<\/p>\n<p>Il reste encore d\u2019autres r\u00e8gles critiques que nous n\u2019avons pas vu, tout simplement parce que je n\u2019ai pas rencontr\u00e9 de d\u00e9fauts de ce type dans le code que j\u2019ai analys\u00e9. Par exemple,<\/p>\n<ul>\n<li>Avoid SQL queries joining on too many tables<\/li>\n<li>Avoid using GROUP BY in queries<\/li>\n<\/ul>\n<p>Mais l\u2019objectif n\u2019est pas de lister toutes les \u2018bad practices\u2019 possibles en mati\u00e8re de programmation SQL. Par contre, certaines violations critiques sont sp\u00e9cifiques \u00e0 l\u2019ABAP. Par exemple : \u00ab\u00a0Avoid too many functions in function pool\u00a0\u00bb.<\/p>\n<p>Un \u2018function pool\u2019 est un groupe de fonctions utilis\u00e9es (appel\u00e9es) par un programme. Lors de cet appel, l\u2019ensemble des fonctions sont mont\u00e9es en m\u00e9moire. Et ce pour la dur\u00e9e de vie compl\u00e8te du programme. Donc plus ce module comportera de fonctions, plus son temps de chargement en m\u00e9moire et l\u2019espace pris dans celle-ci sera important, ce qui peut occasionner un probl\u00e8me de performance. SONAR liste automatiquement tous les function pools avec plus de 15 fonctions.<\/p>\n<p>Nous avons \u00e9galement quelques \u2018best practices\u2019 qui ne concernent pas la performance mais, tout comme le \u2018CASE \u2026 OTHERS\u2019, pr\u00e9sentent un risque pour la robustesse de l\u2019application :<\/p>\n<ul>\n<li>Forbid use of INSERT\/DELETE REPORT\/TEXTPOOL<\/li>\n<li>Forbid use of GENERATE REPORT \/ SUBROUTINE POOL \/ DYNPRO<\/li>\n<\/ul>\n<p>Ces instructions sont prohib\u00e9es car r\u00e9serv\u00e9es \u00e0 SAP (parce qu\u2019elles acc\u00e8dent \u00e0 des donn\u00e9es du noyau qui peuvent dispara\u00eetre dans les prochaines versions).<\/p>\n<p>La derni\u00e8re r\u00e8gle \u00ab\u00a0Prevent use of EDITOR-CALLS\u00a0\u00bb porte sur une instruction qui permet d\u2019appeler l\u2019\u00e9diteur de texte de SAP. Par contre, cette instruction ne permet pas de contr\u00f4ler les droits de l\u2019utilisateur, comme c\u2019est le cas de tout appel \u00e0 une transaction ABAP. Autrement dit, le programmeur peut donner acc\u00e8s en \u00e9dition \u00e0 quelqu\u2019un qui n\u2019a pas cet acc\u00e8s. Cette instruction est donc abandonn\u00e9es, au profit d\u2019autres permettant ce m\u00eame traitement de mani\u00e8re plus contr\u00f4l\u00e9e.<\/p>\n<p>Qu&rsquo;est ce qui justifie qu&rsquo;une r\u00e8gle soit de type &lsquo;Blocker&rsquo; ou &lsquo;Critical&rsquo; ? Apr\u00e8s tout, on pourrait consid\u00e9rer que certaines des violations rencontr\u00e9es dans cet article sont suffisamment graves pour rejoindre la cat\u00e9gorie des d\u00e9fauts bloquants. Certes, mais la diff\u00e9rence est qu&rsquo;on n&rsquo;admettra aucune exception pour un &lsquo;Blocker&rsquo; alors que cela peut s&rsquo;av\u00e9rer le cas pour les les r\u00e8gles &lsquo;Critical&rsquo;. Bien s\u00fbr, cette exception devra toujours \u00eatre justifi\u00e9e, mais vous pouvez accepter que ce code passe en production le temps de d\u00e9cider si une correction doit \u00eatre effectu\u00e9e ou non.<\/p>\n<p>Nous terminerons dans le prochain article la pr\u00e9sentation des r\u00e9gles de notre Quality Profile SONAR pour ABAP.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Nous avons vu dans le post pr\u00e9c\u00e9dent les violations les plus graves aux bonnes pratiques de programmation ABAP. Ces d\u00e9fauts sont bloquants : le code correspondant ne peut aller en production tant qu\u2019une correction n\u2019est pas effectu\u00e9e. Aucune exception n\u2019est permise : tol\u00e9rance z\u00e9ro, car le risque est trop \u00e9lev\u00e9 de voir une transaction interrompue [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13],"tags":[],"class_list":["post-323","post","type-post","status-publish","format-standard","hentry","category-sonar-abap"],"_links":{"self":[{"href":"http:\/\/qualilogy.com\/fr\/wp-json\/wp\/v2\/posts\/323"}],"collection":[{"href":"http:\/\/qualilogy.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/qualilogy.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/qualilogy.com\/fr\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"http:\/\/qualilogy.com\/fr\/wp-json\/wp\/v2\/comments?post=323"}],"version-history":[{"count":10,"href":"http:\/\/qualilogy.com\/fr\/wp-json\/wp\/v2\/posts\/323\/revisions"}],"predecessor-version":[{"id":338,"href":"http:\/\/qualilogy.com\/fr\/wp-json\/wp\/v2\/posts\/323\/revisions\/338"}],"wp:attachment":[{"href":"http:\/\/qualilogy.com\/fr\/wp-json\/wp\/v2\/media?parent=323"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/qualilogy.com\/fr\/wp-json\/wp\/v2\/categories?post=323"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/qualilogy.com\/fr\/wp-json\/wp\/v2\/tags?post=323"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}