{"id":32848,"date":"2019-10-31T21:49:16","date_gmt":"2019-10-31T18:49:16","guid":{"rendered":"https:\/\/prohoster.info\/blog\/vnedryajte-staticheskij-analiz-v-protsess-a-ne-ishhite-s-ego-pomoshhyu-bagi\/"},"modified":"2019-10-31T21:49:16","modified_gmt":"2019-10-31T18:49:16","slug":"vnedryajte-staticheskij-analiz-v-protsess-a-ne-ishhite-s-ego-pomoshhyu-bagi","status":"publish","type":"post","link":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/vnedryajte-staticheskij-analiz-v-protsess-a-ne-ishhite-s-ego-pomoshhyu-bagi","title":{"rendered":"Int\u00e9grez l'analyse statique dans le processus au lieu de l'utiliser pour chercher des bugs.","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>L'\u00e9criture de cet article a \u00e9t\u00e9 motiv\u00e9e par la grande quantit\u00e9 de contenus sur l'analyse statique, qui attirent de plus en plus mon attention. Tout d'abord, c'est <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/en\/company\/pvs-studio\/blog\/\">le blog PVS-studio<\/a><\/noindex>, qui se promeut activement sur Habr gr\u00e2ce \u00e0 des revues des erreurs d\u00e9tect\u00e9es par son outil dans des projets open source. R\u00e9cemment, PVS-studio a introduit <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/en\/company\/pvs-studio\/blog\/436496\/\">le support de Java<\/a><\/noindex>, et bien s\u00fbr, les d\u00e9veloppeurs d'IntelliJ IDEA, dont l'analyseur int\u00e9gr\u00e9 est sans doute le plus avanc\u00e9 pour Java aujourd'hui, <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/en\/company\/JetBrains\/blog\/436278\/\">ne pouvaient pas rester indiff\u00e9rents<\/a><\/noindex>. <\/p>\n<p>En lisant de telles revues, on a l'impression qu'il s'agit d'une potion magique : appuyez sur un bouton, et voil\u00e0 \u2014 la liste des d\u00e9fauts devant vos yeux. On aurait l'impression qu'\u00e0 mesure que les analyseurs s'am\u00e9liorent, de plus en plus de bugs seront automatiquement trouv\u00e9s et que les produits scann\u00e9s par ces robots deviendront de mieux en mieux, sans aucun effort de notre part.<\/p>\n<p>Mais il n'existe pas de potions magiques. Je voudrais parler de ce dont on ne parle g\u00e9n\u00e9ralement pas dans les articles du type \u00ab voici ce que notre robot peut trouver \u00bb : ce que les analyseurs ne peuvent pas faire, quel est leur v\u00e9ritable r\u00f4le et place dans le processus de livraison logicielle, et comment les int\u00e9grer correctement.<\/p>\n<p><img decoding=\"async\" alt=\"Int\u00e9grez l&#039;analyse statique dans le processus au lieu de l&#039;utiliser pour chercher des bugs.\" src=\"\/wp-content\/uploads\/2019\/05\/2a0339f10edcaed3310676ab6e2f975a.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Cloche \u00e0 rats (source : <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%A5%D1%80%D0%B0%D0%BF%D0%BE%D0%B2%D0%BE%D0%B9_%D0%BC%D0%B5%D1%85%D0%B0%D0%BD%D0%B8%D0%B7%D0%BC#\/media\/File:Sperrklinke_Schema.svg\">wikip\u00e9dia<\/a><\/noindex>).<\/i><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Ce que les analyseurs statiques ne pourront jamais accomplir<\/h2>\n<p>\nQu'est-ce que, du point de vue pratique, l'analyse de code source ? Nous soumettons certains codes sources, et en sortie, en peu de temps (beaucoup plus court que les tests) nous obtenons des informations sur notre syst\u00e8me. La limitation fondamentale et math\u00e9matiquement insurmontable est que nous ne pouvons obtenir qu'une classe d'informations plut\u00f4t \u00e9troite de cette mani\u00e8re.<\/p>\n<p>Le cas le plus c\u00e9l\u00e8bre d'une t\u00e2che non r\u00e9soluble par l'analyse statique est <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Halting_problem\">le probl\u00e8me d'arr\u00eat<\/a><\/noindex>: c'est un th\u00e9or\u00e8me qui prouve qu'il est impossible de d\u00e9velopper un algorithme g\u00e9n\u00e9ral qui, \u00e0 partir du code source d'un programme, d\u00e9terminerait s'il va entrer dans une boucle ou se terminer en un temps fini. Une extension de ce th\u00e9or\u00e8me est <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Rice%27s_theorem\">le th\u00e9or\u00e8me de Rice<\/a><\/noindex>, affirmant que pour toute propri\u00e9t\u00e9 non triviale des fonctions calculables, la question de savoir si un programme arbitraire calcule une fonction avec cette propri\u00e9t\u00e9 est une t\u00e2che algorithmiquement ind\u00e9cidable. Par exemple, il est impossible d'\u00e9crire un analyseur qui d\u00e9termine, pour tout code source, si le programme analys\u00e9 est une impl\u00e9mentation d'un algorithme calculant, disons, le carr\u00e9 d'un entier.<\/p>\n<p>Ainsi, la fonctionnalit\u00e9 des analyseurs statiques a des limitations insurmontables. Un analyseur statique ne pourra jamais, dans tous les cas, d\u00e9terminer des \u00e9l\u00e9ments comme, par exemple, l'occurrence d'une \u00ab null pointer exception \u00bb dans des langages permettant une valeur nulle, ou dans tous les cas, d\u00e9terminer la survenue d'un \u00ab attribute not found \u00bb dans des langages \u00e0 typage dynamique. Tout ce qu'un analyseur statique le plus performant peut faire, c'est mettre en \u00e9vidence des cas particuliers, dont le nombre parmi tous les probl\u00e8mes potentiels avec votre code source est, sans exag\u00e9ration, une goutte dans l'oc\u00e9an.<\/p>\n<h2>L'analyse statique n'est pas une recherche de bogues<\/h2>\n<p>\nDe ce qui pr\u00e9c\u00e8de, on peut conclure que l'analyse statique n'est pas un moyen de r\u00e9duire le nombre de d\u00e9fauts dans un programme. Je me risque \u00e0 affirmer que, lorsqu'elle est appliqu\u00e9e pour la premi\u00e8re fois \u00e0 votre projet, elle trouvera des \u00ab endroits int\u00e9ressants \u00bb dans le code, mais ne trouvera probablement aucun d\u00e9faut affectant la qualit\u00e9 de votre programme.<\/p>\n<p>Les exemples de d\u00e9fauts automatiquement trouv\u00e9s par les analyseurs sont impressionnants, mais il ne faut pas oublier que ces exemples ont \u00e9t\u00e9 trouv\u00e9s gr\u00e2ce \u00e0 l'analyse d'un grand ensemble de grandes bases de code. Sur le m\u00eame principe, les hackers capables de tester plusieurs mots de passe simples sur un grand nombre de comptes finissent par trouver ceux pour lesquels le mot de passe est simple.<\/p>\n<p>Cela signifie-t-il qu'il ne faut pas appliquer l'analyse statique ? Bien s\u00fbr que non ! Et pour la m\u00eame raison pour laquelle il est utile de v\u00e9rifier chaque nouveau mot de passe contre la liste noire des \u00ab mots de passe simples \u00bb.<\/p>\n<h2>L'analyse statique est plus qu'une recherche de bogues<\/h2>\n<p>\nEn r\u00e9alit\u00e9, les t\u00e2ches pratiquement r\u00e9solues par l'analyse sont beaucoup plus larges. En effet, l'analyse statique est toute v\u00e9rification des sources effectu\u00e9e avant leur ex\u00e9cution. Voici quelques-unes des choses que l'on peut faire :<\/p>\n<ul>\n<li> La v\u00e9rification du style de code au sens large du terme. Cela inclut \u00e0 la fois la v\u00e9rification du formatage et la recherche de l'utilisation de parenth\u00e8ses vides\/superflues, l'\u00e9tablissement de seuils pour des m\u00e9triques telles que le nombre de lignes\/la complexit\u00e9 cyclomatique des m\u00e9thodes, etc. \u2014 tout ce qui peut potentiellement compliquer la lisibilit\u00e9 et la maintenabilit\u00e9 du code. En Java, un tel outil est Checkstyle, en Python \u2014 flake8. Les programmes de ce type sont g\u00e9n\u00e9ralement appel\u00e9s \u00ab linters \u00bb.<\/li>\n<li>L'analyse peut porter non seulement sur le code ex\u00e9cutable. Les fichiers de ressources, tels que JSON, YAML, XML, .properties peuvent (et doivent !) \u00eatre v\u00e9rifi\u00e9s automatiquement pour leur validit\u00e9. Apr\u00e8s tout, il vaut mieux d\u00e9couvrir qu'en raison de guillemets non appari\u00e9s la structure JSON est rompue \u00e0 un stade pr\u00e9coce de la v\u00e9rification automatique de la Pull Request, plut\u00f4t qu'en ex\u00e9cutant des tests ou en runtime ? Des outils correspondants sont disponibles : par exemple, <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/adrienverge\/yamllint\">YAMLlint<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zaach\/jsonlint\">JSONLint<\/a><\/noindex>.<\/li>\n<li> La compilation (ou le parsing pour les langages de programmation dynamiques) est \u00e9galement une forme d'analyse statique. En g\u00e9n\u00e9ral, les compilateurs sont capables de fournir des avertissements signalant des probl\u00e8mes de qualit\u00e9 du code source, et ils ne doivent pas \u00eatre ignor\u00e9s.<\/li>\n<li>Parfois, la compilation n'est pas seulement la compilation du code ex\u00e9cutable. Par exemple, si vous avez de la documentation au format <noindex><a rel=\"nofollow\" href=\"https:\/\/asciidoctor.org\/\">AsciiDoctor<\/a><\/noindex>, alors au moment de la transformer en HTML\/PDF, le processeur AsciiDoctor (<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/asciidoctor\/asciidoctor-maven-plugin\">plugin Maven<\/a><\/noindex>) peut \u00e9mettre des avertissements, par exemple sur des liens internes rompues. Et c'est une raison solide de ne pas accepter la Pull Request avec des modifications de la documentation.<\/li>\n<li>La v\u00e9rification orthographique est aussi une forme d'analyse statique. L'outil <noindex><a rel=\"nofollow\" href=\"http:\/\/aspell.net\/\">aspell<\/a><\/noindex> peut v\u00e9rifier l'orthographe non seulement dans la documentation, mais aussi dans le code source des programmes (commentaires et litt\u00e9raux) dans diff\u00e9rents langages de programmation, y compris C\/C++, Java et Python. Une faute d'orthographe dans l'interface utilisateur ou la documentation est aussi un d\u00e9faut !<\/li>\n<li>Les tests de configuration (pour ce que c'est, voir <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=KaeEjsAjV6A&amp;index=30&amp;list=PLsVTVVvrKX9tuYyCtL8mASB6IOaa-kRCA&amp;t=0s\">celui-ci<\/a><\/noindex> et <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=Tk_nmV-mWOA\">celui-ci<\/a><\/noindex> les rapports), bien qu'ils soient effectu\u00e9s dans l'environnement d'ex\u00e9cution de tests unitaires comme pytest, sont en r\u00e9alit\u00e9 aussi une forme d'analyse statique, car ils n'ex\u00e9cutent pas le code source lors de leur ex\u00e9cution.<\/li>\n<\/ul>\n<p>\nComme nous le voyons, la recherche de bogues dans cette liste occupe un r\u00f4le moins important, tandis que tout le reste est accessible par l'utilisation d'outils open source gratuits.<\/p>\n<p>Quels types d'analyse statique devez-vous appliquer dans votre projet ? Bien s\u00fbr, tous, plus il y en a, mieux c'est ! L'essentiel est de bien les int\u00e9grer, c'est ce dont nous allons parler ensuite.<\/p>\n<h2>Le pipeline de livraison comme un filtre multi-niveaux et l'analyse statique comme son premier niveau.<\/h2>\n<p>\nLa m\u00e9taphore classique de l'int\u00e9gration continue est le pipeline, o\u00f9 les changements circulent \u2014 de la modification du code source \u00e0 la livraison en production. La s\u00e9quence standard des \u00e9tapes de ce pipeline est la suivante :<\/p>\n<ol>\n<li>analyse statique<\/li>\n<li>compilation<\/li>\n<li>tests unitaires<\/li>\n<li>tests d'int\u00e9gration<\/li>\n<li>tests UI<\/li>\n<li>v\u00e9rification manuelle<\/li>\n<\/ol>\n<p>\nLes modifications rejet\u00e9es \u00e0 l'\u00e9tape N du pipeline ne sont pas transmises \u00e0 l'\u00e9tape N+1.<\/p>\n<p>Pourquoi ainsi et non autrement ? Dans la partie du pipeline qui concerne les tests, les testeurs d\u00e9couvrent la fameuse pyramide des tests.<\/p>\n<p><img decoding=\"async\" alt=\"Int\u00e9grez l&#039;analyse statique dans le processus au lieu de l&#039;utiliser pour chercher des bugs.\" src=\"\/wp-content\/uploads\/2019\/05\/f155307fd4c1663800843c394098ea6f.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Pyramide des tests. Source : <noindex><a rel=\"nofollow\" href=\"https:\/\/martinfowler.com\/bliki\/TestPyramid.html\">article<\/a><\/noindex> Martin Fowler.<\/i><\/p>\n<p>En bas de cette pyramide se trouvent des tests qui sont plus faciles \u00e0 \u00e9crire, qui s'ex\u00e9cutent plus rapidement et qui n'ont pas tendance \u00e0 d\u00e9clencher de faux positifs. Ils doivent donc \u00eatre plus nombreux, couvrir plus de code et s'ex\u00e9cuter en premier. En haut de la pyramide, c'est tout le contraire, c'est pourquoi le nombre de tests d'int\u00e9gration et de tests UI doit \u00eatre r\u00e9duit au minimum n\u00e9cessaire. L'humain dans cette cha\u00eene est la ressource la plus ch\u00e8re, la plus lente et la moins fiable, c'est pourquoi il se trouve \u00e0 la fin et n'effectue son travail que si les \u00e9tapes pr\u00e9c\u00e9dentes n'ont d\u00e9tect\u00e9 aucun d\u00e9faut. Cependant, le pipeline est construit selon les m\u00eames principes dans les parties non directement li\u00e9es aux tests !<\/p>\n<p>Je voudrais proposer une analogie avec un syst\u00e8me de filtration d'eau multi-niveaux. \u00c0 l'entr\u00e9e, de l'eau sale (des changements avec des d\u00e9fauts) est fournie, \u00e0 la sortie, nous devons obtenir de l'eau propre, o\u00f9 toutes les impuret\u00e9s ind\u00e9sirables ont \u00e9t\u00e9 \u00e9limin\u00e9es.<\/p>\n<p><img decoding=\"async\" alt=\"Int\u00e9grez l&#039;analyse statique dans le processus au lieu de l&#039;utiliser pour chercher des bugs.\" src=\"\/wp-content\/uploads\/2019\/05\/76b5be8f13d55c16970d67e09767a045.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Filtre multi-niveaux. Source : <noindex><a rel=\"nofollow\" href=\"https:\/\/commons.wikimedia.org\/wiki\/File:Milli-Q_Water_filtration_station.JPG\">Wikimedia Commons<\/a><\/noindex><\/i><\/p>\n<p>Comme vous le savez, les filtres de nettoyage sont con\u00e7us de telle mani\u00e8re que chaque cascade suivante peut \u00e9liminer des fractions de pollution de plus en plus fines. Les cascades de nettoyage le plus grossier, quant \u00e0 elles, ont une plus grande capacit\u00e9 de passage et sont moins co\u00fbteuses. Dans notre analogie, cela signifie que les portes de qualit\u00e9 \u00e0 l'entr\u00e9e ont de meilleures performances, n\u00e9cessitent moins d'efforts pour \u00eatre lanc\u00e9es et sont en elles-m\u00eames plus faciles \u00e0 utiliser \u2014 et c'est pr\u00e9cis\u00e9ment dans cet ordre qu'elles sont agenc\u00e9es. Le r\u00f4le de l'analyse statique, qui, comme nous le comprenons maintenant, ne peut filtrer que les d\u00e9fauts les plus grossiers \u2014 c'est le r\u00f4le de la grille \u00ab grossi\u00e8re \u00bb au tout d\u00e9but de la cascade de filtres.<\/p>\n<p>L'analyse statique en elle-m\u00eame n'am\u00e9liore pas la qualit\u00e9 du produit final, comme un filtre grossier ne rend pas l'eau potable. N\u00e9anmoins, dans l'ensemble, son importance est \u00e9vidente lorsqu'elle est associ\u00e9e \u00e0 d'autres \u00e9l\u00e9ments de la cha\u00eene. Bien que dans un filtre \u00e0 plusieurs cascades, les cascades de sortie puissent potentiellement capturer exactement ce que les cascades d'entr\u00e9e attrapent \u2014 il est clair quelles en seraient les cons\u00e9quences si l'on n'utilisait que des cascades de nettoyage fines, sans celles d'entr\u00e9e.<\/p>\n<p>Le but du \u00ab filtre grossier \u00bb est de d\u00e9charger les cascades suivantes de la d\u00e9tection de d\u00e9fauts vraiment grossiers. Par exemple, au minimum, la personne effectuant la r\u00e9vision de code ne devrait pas \u00eatre distrait par du code mal format\u00e9 et des violations des normes de codage \u00e9tablies (comme des parenth\u00e8ses en trop ou des imbrications trop profondes). Les bugs tels que les NPE doivent \u00eatre d\u00e9tect\u00e9s par des tests unitaires, mais si l'analyseur nous indique qu'un bug doit in\u00e9vitablement se produire avant m\u00eame le test \u2014 cela acc\u00e9l\u00e9rera consid\u00e9rablement sa correction.<\/p>\n<p>Je suppose qu'il est maintenant clair pourquoi l'analyse statique n'am\u00e9liore pas la qualit\u00e9 du produit lorsqu'elle est appliqu\u00e9e \u00e9pisodiquement, et qu'elle doit \u00eatre appliqu\u00e9e de mani\u00e8re continue pour \u00e9liminer les changements ayant des d\u00e9fauts grossiers. La question de savoir si l'application d'un analyseur statique am\u00e9liorera la qualit\u00e9 de votre produit est \u00e0 peu pr\u00e8s \u00e9quivalente \u00e0 celle de \u00ab l'eau tir\u00e9e d'un r\u00e9servoir sale s'am\u00e9liorera-t-elle si elle est pass\u00e9e au travers d'une passoire ? \u00bb<\/p>\n<h2>Int\u00e9gration dans un projet h\u00e9rit\u00e9<\/h2>\n<p>\nQuestion pratique importante : comment int\u00e9grer l'analyse statique dans le processus d'int\u00e9gration continue en tant que \u00ab quality gate \u00bb ? Dans le cas des tests automatis\u00e9s, tout est clair : il existe un ensemble de tests, et l'\u00e9chec de l'un d'eux est un motif suffisant pour consid\u00e9rer que la construction n'a pas franchi le quality gate. Essayer d'\u00e9tablir un gate bas\u00e9 sur les r\u00e9sultats de l'analyse statique \u00e9choue : avec le code h\u00e9rit\u00e9, il y a trop d'avertissements d'analyse, on ne veut pas les ignorer compl\u00e8tement, mais il n'est pas possible d'arr\u00eater la livraison du produit simplement parce qu'il contient des avertissements de l'analyseur.<\/p>\n<p>Lorsqu'il est utilis\u00e9 pour la premi\u00e8re fois, l'analyseur g\u00e9n\u00e8re un grand nombre d'avertissements, la grande majorit\u00e9 desquels n'ont pas de rapport avec le bon fonctionnement du produit. Il est impossible de corriger imm\u00e9diatement tous ces commentaires, et beaucoup ne le sont m\u00eame pas. Apr\u00e8s tout, nous savons que notre produit fonctionne globalement, m\u00eame avant l'int\u00e9gration de l'analyse statique !<\/p>\n<p>En fin de compte, beaucoup se contentent d'une utilisation \u00e9pisodique de l'analyse statique, ou l'utilisent uniquement en mode d'information, o\u00f9 un rapport de l'analyseur est simplement g\u00e9n\u00e9r\u00e9 lors de la construction. Cela \u00e9quivaut \u00e0 une absence totale d'analyse, car si nous avons d\u00e9j\u00e0 de nombreux avertissements, l'apparition d'un autre (quel qu'il soit) lors de la modification du code reste inaper\u00e7ue.<\/p>\n<p>Les m\u00e9thodes suivantes pour \u00e9tablir des quality gates sont connues :<\/p>\n<ul>\n<li>\u00c9tablir une limite sur le nombre total d'avertissements ou sur le nombre d'avertissements divis\u00e9 par le nombre de lignes de code. Cela fonctionne mal, car un tel gate laisse passer librement des modifications avec de nouveaux d\u00e9fauts tant que leur limite n'est pas d\u00e9pass\u00e9e.<\/li>\n<li>La fixation, \u00e0 un moment donn\u00e9, de tous les anciens avertissements dans le code comme \u00e9tant ignor\u00e9s, et le refus de la construction en cas de nouveaux avertissements. Cette fonctionnalit\u00e9 est fournie par PVS-Studio et certains ressources en ligne, comme Codacy. Je n'ai pas eu l'occasion de travailler avec PVS-Studio, en ce qui concerne mon exp\u00e9rience avec Codacy, leur principal probl\u00e8me r\u00e9side dans le fait que d\u00e9terminer ce qu'est une \u00ab ancienne \u00bb erreur et ce qu'est une \u00ab nouvelle \u00bb erreur est un algorithme assez complexe et qui ne fonctionne pas toujours correctement, surtout si les fichiers sont fortement modifi\u00e9s ou renomm\u00e9s. De m\u00e9moire, Codacy a pu passer de nouveaux avertissements dans une pull request, tout en refusant celle-ci en raison d'avertissements non li\u00e9s aux modifications du code de cette PR.<\/li>\n<li>\u00c0 mon avis, la solution la plus efficace est celle d\u00e9crite dans le livre <noindex><a rel=\"nofollow\" href=\"https:\/\/www.amazon.com\/Continuous-Delivery-Deployment-Automation-Addison-Wesley\/dp\/0321601912\">Livraison continue<\/a><\/noindex> \u00ab m\u00e9thode du cliquet \u00bb (\u00ab ratcheting \u00bb). L'id\u00e9e principale est que la propri\u00e9t\u00e9 de chaque version est le nombre d'avertissements d'analyse statique, et seules les modifications qui n'augmentent pas le nombre total d'avertissements sont autoris\u00e9es.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Cliquet<\/h2>\n<p>\nCela fonctionne de la mani\u00e8re suivante :<\/p>\n<ol>\n<li>\u00c0 l'\u00e9tape initiale, une inscription dans les m\u00e9tadonn\u00e9es de la version du nombre d'avertissements dans le code, trouv\u00e9s par les analyseurs, est mise en \u0153uvre. Ainsi, lors de la construction de la branche principale, votre gestionnaire de d\u00e9p\u00f4ts enregistre non seulement \u00ab version 7.0.2 \u00bb, mais \u00ab version 7.0.2, contenant 100500 avertissements Checkstyle \u00bb. Si vous utilisez un gestionnaire de d\u00e9p\u00f4ts avanc\u00e9 (comme Artifactory), il est facile de conserver de telles m\u00e9tadonn\u00e9es sur votre version.<\/li>\n<li>Maintenant, chaque pull request lors de la construction compare le nombre d'avertissements obtenus avec celui qui existe dans la version actuelle. Si la PR entra\u00eene une augmentation de ce nombre, le code ne passe pas le quality gate pour l'analyse statique. Si le nombre d'avertissements diminue ou ne change pas - alors il est valid\u00e9.<\/li>\n<li>Lors de la prochaine version, le nombre d'avertissements recalcul\u00e9 sera de nouveau enregistr\u00e9 dans les m\u00e9tadonn\u00e9es de la version.<\/li>\n<\/ol>\n<p>\nAinsi, progressivement mais s\u00fbrement (comme avec le travail d'un cliquet), le nombre d'avertissements tendra vers z\u00e9ro. Bien s\u00fbr, le syst\u00e8me peut \u00eatre tromp\u00e9 en ajoutant un nouvel avertissement tout en corrigeant celui d'un autre. C'est acceptable, car \u00e0 long terme, cela produit des r\u00e9sultats : les avertissements sont g\u00e9n\u00e9ralement corrig\u00e9s non pas un par un, mais en groupe selon un type d\u00e9fini, et tous les avertissements facilement supprimables sont rapidement r\u00e9solus.<\/p>\n<p>Ce graphique montre le nombre total d'avertissements Checkstyle sur une p\u00e9riode de six mois de fonctionnement de ce \u00ab cliquet \u00bb sur <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/CourseOrchestra\/celesta\">l'un de nos projets OpenSource<\/a><\/noindex>. Le nombre d'avertissements a diminu\u00e9 d'un ordre de grandeur, et cela s'est produit naturellement, parall\u00e8lement au d\u00e9veloppement du produit !<\/p>\n<p><img decoding=\"async\" alt=\"Int\u00e9grez l&#039;analyse statique dans le processus au lieu de l&#039;utiliser pour chercher des bugs.\" src=\"\/wp-content\/uploads\/2019\/05\/9529bb2fb32187057088e8d2c4203333.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nJ'applique une version modifi\u00e9e de cette m\u00e9thode, en comptant s\u00e9par\u00e9ment les avertissements par module de projet et par outils d'analyse, le fichier YAML g\u00e9n\u00e9r\u00e9 avec les m\u00e9tadonn\u00e9es de la construction ressemble approximativement \u00e0 ceci :<\/p>\n<pre><code class=\"plaintext\">celesta-sql:\n  checkstyle: 434\n  spotbugs: 45\ncelesta-core:\n  checkstyle: 206\n  spotbugs: 13\ncelesta-maven-plugin:\n  checkstyle: 19\n  spotbugs: 0\ncelesta-unit:\n  checkstyle: 0\n  spotbugs: 0\n<\/code><\/pre>\n<p>\nDans tout syst\u00e8me CI avanc\u00e9, un \u00ab cliquet \u00bb peut \u00eatre mis en \u0153uvre pour n'importe quel outil d'analyse statique, sans s'appuyer sur des plugins ou des outils tiers. Chacun des analyseurs fournit son rapport au format texte simple ou XML, facilement analysable. Il ne reste plus qu'\u00e0 r\u00e9diger la logique requise dans le script CI. Vous pouvez voir comment cela est r\u00e9alis\u00e9 dans nos projets open source bas\u00e9s sur Jenkins et Artifactory. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/CourseOrchestra\/2bass\/blob\/dev\/Jenkinsfile\">ici<\/a><\/noindex> ou <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/CourseOrchestra\/celesta\/blob\/dev\/Jenkinsfile\">ici<\/a><\/noindex>. Les deux exemples d\u00e9pendent de la biblioth\u00e8que <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/inponomarev\/ratchetlib\">ratchetlib<\/a><\/noindex>: la m\u00e9thode <code>countWarnings()<\/code> compte de mani\u00e8re ordinaire les balises xml dans les fichiers g\u00e9n\u00e9r\u00e9s par Checkstyle et Spotbugs, et <code>compareWarningMaps()<\/code> met en \u0153uvre ce fameux cliquet, g\u00e9n\u00e9rant une erreur lorsque le nombre d'avertissements dans l'une des cat\u00e9gories augmente.<\/p>\n<p>Une option int\u00e9ressante pour mettre en \u0153uvre un \u00ab syst\u00e8me \u00e0 cliquet \u00bb est possible pour l'analyse orthographique des commentaires, des litt\u00e9raux textuels et de la documentation \u00e0 l'aide d'aspell. Comme on le sait, lors de la v\u00e9rification orthographique, tous les mots qui ne sont pas connus du dictionnaire standard ne sont pas n\u00e9cessairement incorrects ; ils peuvent \u00eatre ajout\u00e9s au dictionnaire personnel. Si le dictionnaire personnel fait partie du code source du projet, alors la porte de qualit\u00e9 relative \u00e0 l'orthographe peut \u00eatre formul\u00e9e comme suit : ex\u00e9cuter aspell avec le dictionnaire standard et le dictionnaire personnel. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/CourseOrchestra\/celesta\/blob\/271dcfc8dc3ad65ac2d1dcaa39b7fd3ea8fb5891\/Jenkinsfile#L36\">ne doit pas<\/a><\/noindex> trouver des erreurs d'orthographe.<\/p>\n<h2>L'importance de la fixation de la version de l'analyseur<\/h2>\n<p>\nEn conclusion, il convient de noter ce qui suit : peu importe la mani\u00e8re dont vous int\u00e9grez l'analyse dans votre pipeline de livraison, la version de l'analyseur doit \u00eatre fix\u00e9e. Si on laisse l'analyseur se mettre \u00e0 jour de mani\u00e8re spontan\u00e9e, de nouveaux d\u00e9fauts peuvent \u00ab \u00e9merger \u00bb lors de la compilation d'une nouvelle demande de tirage, qui ne sont pas li\u00e9s \u00e0 un changement de code, mais simplement au fait que le nouvel analyseur peut identifier plus de d\u00e9fauts \u2014 ce qui perturbera votre processus d'acceptation des demandes de tirage. La mise \u00e0 niveau de l'analyseur doit \u00eatre un acte conscient. Cependant, la fixation stricte de la version de chaque composant de la compilation est g\u00e9n\u00e9ralement une exigence n\u00e9cessaire et un sujet \u00e0 part enti\u00e8re.<\/p>\n<h2>Conclusions<\/h2>\n<p><\/p>\n<ul>\n<li>L'analyse statique ne trouvera pas de bogues pour vous et n'am\u00e9liorera pas la qualit\u00e9 de votre produit si elle n'est appliqu\u00e9e qu'une seule fois. Un effet positif sur la qualit\u00e9 ne peut \u00eatre obtenu que par son application continue tout au long du processus de livraison.<\/li>\n<li>La recherche de bogues n'est pas du tout la principale t\u00e2che de l'analyse ; la quasi-totalit\u00e9 des fonctionnalit\u00e9s utiles est disponible dans les outils open source.<\/li>\n<li>Mettez en place des portes de qualit\u00e9 en fonction des r\u00e9sultats de l'analyse statique d\u00e8s la premi\u00e8re \u00e9tape du pipeline de livraison, en utilisant le \u00ab syst\u00e8me \u00e0 cliquet \u00bb pour le code h\u00e9rit\u00e9.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Liens<\/h2>\n<p><\/p>\n<ol>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.amazon.com\/Continuous-Delivery-Deployment-Automation-Addison-Wesley\/dp\/0321601912\">Livraison continue<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=8Cx3LHNjI24\">A. Koudivtsev : Analyse de programmes : comment savoir si vous \u00eates un bon programmeur<\/a><\/noindex> pr\u00e9sentation sur diff\u00e9rentes m\u00e9thodes d'analyse de code (pas seulement statiques !)<\/li>\n<\/ol>\n<p>Source : <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/436868\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u044c\u044e \u043c\u0435\u043d\u044f \u0441\u043f\u043e\u0434\u0432\u0438\u0433\u043b\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0430\u043d\u0430\u043b\u0438\u0437\u0435, \u0432\u0441\u0451 \u0447\u0430\u0449\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u043d\u0430 \u0433\u043b\u0430\u0437\u0430. \u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u044d\u0442\u043e \u0431\u043b\u043e\u0433 PVS-studio, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u043f\u0440\u043e\u0434\u0432\u0438\u0433\u0430\u0435\u0442 \u0441\u0435\u0431\u044f \u043d\u0430 \u0425\u0430\u0431\u0440\u0435 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043e\u0431\u0437\u043e\u0440\u043e\u0432 \u043e\u0448\u0438\u0431\u043e\u043a, \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u044b\u0445 \u0438\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u043a\u043e\u0434\u043e\u043c. \u041d\u0435\u0434\u0430\u0432\u043d\u043e PVS-studio \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 Java, \u0438, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 IntelliJ IDEA, \u0447\u0435\u0439 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0433\u043e\u0434\u043d\u044f, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":24622,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-32848","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u044c\u044e \u043c\u0435\u043d\u044f \u0441\u043f\u043e\u0434\u0432\u0438\u0433\u043b\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0430\u043d\u0430\u043b\u0438\u0437\u0435, \u0432\u0441\u0451 \u0447\u0430\u0449\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u043d\u0430 \u0433\u043b\u0430\u0437\u0430.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/vnedryajte-staticheskij-analiz-v-protsess-a-ne-ishhite-s-ego-pomoshhyu-bagi\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"fr_FR\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0412\u043d\u0435\u0434\u0440\u044f\u0439\u0442\u0435 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u043d\u0430\u043b\u0438\u0437 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u0430 \u043d\u0435 \u0438\u0449\u0438\u0442\u0435 \u0441 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0431\u0430\u0433\u0438 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u044c\u044e \u043c\u0435\u043d\u044f \u0441\u043f\u043e\u0434\u0432\u0438\u0433\u043b\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0430\u043d\u0430\u043b\u0438\u0437\u0435, \u0432\u0441\u0451 \u0447\u0430\u0449\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u043d\u0430 \u0433\u043b\u0430\u0437\u0430.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/vnedryajte-staticheskij-analiz-v-protsess-a-ne-ishhite-s-ego-pomoshhyu-bagi\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:49:16+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:49:16+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Impl\u00e9mentez l'analyse statique dans le processus et ne cherchez pas de bogues gr\u00e2ce \u00e0 elle | ProHoster","description":"C'est la grande quantit\u00e9 de mat\u00e9riel sur l'analyse statique que je rencontre de plus en plus souvent qui m'a pouss\u00e9 \u00e0 \u00e9crire cet article.","canonical_url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/vnedryajte-staticheskij-analiz-v-protsess-a-ne-ishhite-s-ego-pomoshhyu-bagi","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"fr_FR","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0412\u043d\u0435\u0434\u0440\u044f\u0439\u0442\u0435 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u043d\u0430\u043b\u0438\u0437 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u0430 \u043d\u0435 \u0438\u0449\u0438\u0442\u0435 \u0441 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0431\u0430\u0433\u0438 | ProHoster","og:description":"\u041d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u044c\u044e \u043c\u0435\u043d\u044f \u0441\u043f\u043e\u0434\u0432\u0438\u0433\u043b\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0430\u043d\u0430\u043b\u0438\u0437\u0435, \u0432\u0441\u0451 \u0447\u0430\u0449\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u043d\u0430 \u0433\u043b\u0430\u0437\u0430.","og:url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/vnedryajte-staticheskij-analiz-v-protsess-a-ne-ishhite-s-ego-pomoshhyu-bagi","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:49:16+00:00","article:modified_time":"2019-10-31T18:49:16+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"32848","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 12:50:20","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 02:51:27","updated":"2026-01-21 12:50:20","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/32848","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/comments?post=32848"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/32848\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media\/24622"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media?parent=32848"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/categories?post=32848"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/tags?post=32848"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}