<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Derniers posts du blog de Damien Pobel]]></title><description><![CDATA[Derniers posts du blog de Damien Pobel]]></description><link>https://damien.pobel.fr</link><generator>metalsmith-feed</generator><lastBuildDate>Mon, 11 May 2026 10:18:06 GMT</lastBuildDate><atom:link href="https://damien.pobel.fr/rss.xml" rel="self" type="application/rss+xml"/><item><title><![CDATA[React est horrible (React is awful)]]></title><description><![CDATA[<figure class="object-center bordered">
  <a href="/images/react-est-horrible-tout-va-bien.png">
    <img loading="lazy" src="/images/660x/react-est-horrible-tout-va-bien.png" alt="Mème : à gauche, un lapin au milieu d'un appartement en feu, avec pour légende « React est horrible », est serein sur son tabouret. À droite, le lapin dit « Tout va bien. » en souriant." />
  </a>
  <footer>Généré par <a href="https://framamemes.org/?meme=this_is_fine">Framamèmes</a></footer>
</figure>

<p><a href="https://a.tldrnewsletter.com/web-version?ep=1&lc=fbbfb5c8-4b42-11f0-b9e7-9716091ed4a1&p=5581b3de-831c-11f0-a328-396c2123b42d&pt=campaign&t=1756294286&s=d02fe564622c4f4c98bd71950074e83b99e3b9616eedb4aafede024c1f0acae6">Extrait de la newsletter TLDR Web Dev du 27 août 2025</a>,</p>
<p><strong><a href="https://github.com/cloudstreet-dev/React-is-Awful">React-is-Awful</a></strong></p>
<blockquote>
<p>An AI generated book about React that teaches React and humorously complains about its complexity and design decisions.</p>
</blockquote>
<p>Cette courte description a piqué ma curiosité autant pour le côté généré par IA
que sur le fond avec un petit bonus pour la <em>plainte humoristique</em>.</p>
<p>Dès le README du dépôt git, le ton est donné :</p>
<blockquote>
<h3 id="what-youll-learn">What You&#39;ll Learn</h3>
<ul>
<li>❌ Why it exists (Facebook&#39;s notification counter was sometimes wrong)</li>
<li>❌ The Virtual DOM (a solution to a problem React created)</li>
<li>❌ JSX (HTML and JavaScript had a baby nobody asked for)</li>
<li>❌ Hooks (functions that remember things, breaking everything functions stand for)</li>
<li>❌ useEffect (the footgun you&#39;ll shoot yourself with)</li>
<li>✅ How to get a job anyway</li>
</ul>
</blockquote>
<p>et ce ton humoristique voire sarcastique se poursuit tout au long du livre et
rend sa lecture très amusante ce qui est quand même rare dans un livre
<em>technique</em>.</p>
<p>Cet ouvrage a donc, a priori, été généré par une IA générative (Claude) et si ce
n&#39;était pas précisé dès le départ, je suis pas certain que je l&#39;aurais remarqué
en le lisant. Il y a certes quelques tournures et enchaînements qui semblent un
peu maladroits mais on en trouve aussi dans des livres écrits par des humains.
Je serais quand même curieux de voir le ou les prompts qui permettent d&#39;obtenir
ce résultat.</p>
<p>Sur le fond, le livre vise plutôt juste dans ses critiques de React (en tout cas
cohérentes avec ma propre expérience) et dans <a href="https://github.com/cloudstreet-dev/React-is-Awful/blob/main/18-chapter-acceptance.md">ses préconisations pour <em>faire
avec</em></a>.
Et contrairement à ce que pourrait suggèrer le titre, le livre reconnaît tout de
même quelques mérites à React. Il n&#39;y a guère que <a href="https://github.com/cloudstreet-dev/React-is-Awful/blob/main/14-chapter-testing-nightmare.md">le chapitre sur les
tests</a>
qui, certes, pointe un problème réel mais mériterait sans doute un peu plus de
nuances. En vrai, ce chapitre pourrait faire l&#39;objet d&#39;un livre entier à lui
tout seul 🫠</p>
<p>Bref, <a href="https://github.com/cloudstreet-dev/React-is-Awful">React-is-Awful</a> est à
la fois un ovni dans le paysage des livres techniques et un bon ouvrage pour
approfondir la compréhension de React et des compromis que son usage impose.</p>
]]></description><link>https://damien.pobel.fr/post/react-est-horrible</link><guid isPermaLink="true">https://damien.pobel.fr/post/react-est-horrible</guid><category><![CDATA[veille]]></category><category><![CDATA[métier]]></category><category><![CDATA[react]]></category><category><![CDATA[bonnes pratiques]]></category><category><![CDATA[qualité]]></category><category><![CDATA[code]]></category><category><![CDATA[ingénierie logicielle]]></category><pubDate>Wed, 03 Sep 2025 00:00:00 GMT</pubDate></item><item><title><![CDATA[Chasser le superflu]]></title><description><![CDATA[<p>Il y a quelques jours, je suis tombé sur <a href="https://qntm.org/devphilo">Developer
philosophy</a>. Je trouve l&#39;exercice amusant, je vais
essayer de faire plus ou moins la même chose ici en listant et détaillant ce que
j&#39;appellerais plutôt des principes qui me semblent essentiels et qui sont issus
de mon expérience.</p>
<figure class="object-center bordered">
  <a href="/images/superflu-superheros-inutile.png">
    <img loading="lazy" src="/images/660x/superflu-superheros-inutile.png" alt="Superflu, le superhéros inutile">
  </a>
  <footer>Extrait de <a href="https://editions.ptilouk.net/superflu/">Les aventures inutiles de Superflu</a> par <a href="https://ptilouk.net/">Gee</a> sous licence <a href="https://creativecommons.org/licenses/by-sa/2.0/fr/">CC BY-SA 2.0</a></footer>
</figure>

<p>Je commence donc par le premier qui me vient à l&#39;esprit que j&#39;aime bien exprimé
avec la citation suivante attribuée à Antoine de Saint-Exupéry :</p>
<blockquote>
<p>La perfection est atteinte, non pas lorsqu&#39;il n&#39;y a plus rien à ajouter, mais
lorsqu&#39;il n&#39;y a plus rien à retirer.</p>
</blockquote>
<p>En d&#39;autres termes, je déclare la chasse au superflu ouverte 😃
En pratique, qu&#39;est ce que cela signifie ?</p>
<p>L&#39;application la plus évidente de ce principe consiste à éliminer ce qu&#39;on
appelle <a href="https://refactoring.guru/smells/dead-code">le code mort (<em>dead code</em>)</a>.
Il s&#39;agit sans doute de l&#39;un des <em>code smells</em> les plus connus qui désigne le code
qui ne peut pas être atteint. Équipé·e d&#39;un bon <abbr title="Environnement de
développement intégré">IDE</abbr>, de quelques outils d&#39;analyse statique et <a href="/post/bon-test-unitaire-integration-fonctionnel/">de
bons tests automatisés</a>, il
est relativement facile de le détecter et de l&#39;éliminer au niveau d&#39;une fonction
ou d&#39;un fichier. En revanche, au niveau d&#39;un projet conséquent avec un peu
d&#39;historique (comprendre du code <em>legacy</em> 😜) c&#39;est une autre histoire. Petite
anecdote, il y a quelques mois, sur deux projets TypeScript j&#39;ai poussé pour
essayer de rationaliser l&#39;usage du mot clé <code>export</code> en introduisant un script
dans la CI pour détecter les changements qui incluent des <code>export</code> inutilisés
(basé sur <a href="https://www.npmjs.com/package/ts-unused-exports">ts-unused-export</a>)
et pour progressivement éliminer les <code>export</code> inutilisés existants. Cette
démarche s&#39;inscrivait déjà dans une volonté de <em>chasser le superflu</em> mais mon but
initial était surtout de faciliter le <em>refactoring</em> (sans mot clé <code>export</code>, on
est certain d&#39;avoir un périmètre limité au fichier) et au final, cet exercice
a permis de déterrer une quantité de code mort plus que conséquente (plusieurs
milliers de lignes de code 😮) qui n&#39;était là que être exporté sans être
utilisé et qui occasionnait de la confusion et zéro valeur ajoutée. Hop <a href="/post/dette-technique-partie-tetris/">un peu
moins de dette technique</a> !</p>
<figure class="object-center bordered">
  <a href="/images/superflu-manque-rien.png">
    <img loading="lazy" src="/images/660x/superflu-manque-rien.png" alt="Superflu, le superhéros inutile">
  </a>
  <footer>Extrait de <a href="https://editions.ptilouk.net/superflu/">Les aventures inutiles de Superflu</a> par <a href="https://ptilouk.net/">Gee</a> sous licence <a href="https://creativecommons.org/licenses/by-sa/2.0/fr/">CC BY-SA 2.0</a></footer>
</figure>

<p>Si on prend un peu de hauteur, appliquer ce principe dans le design d&#39;une API
(d&#39;une simple méthode comme d&#39;une API web type REST ou GraphQL) est un bon outil
pour s&#39;éviter un peu de complexité. Par exemple, si une méthode accepte des
paramètres optionnels mais qu&#39;ils ne sont jamais utilisés ou que cette méthode
reçoit un paramètre avec toujours la même valeur ou que sa valeur de retour
n&#39;est jamais utilisée vous avez probablement du <em>superflu</em> sous les yeux qui
induit <a href="/post/complexite-charge-cognitive/">une certaine complexité</a> et qui
aurait tout intérêt à être éliminé pour améliorer la maintenabilité. On parle
parfois de <em>réduire la surface d&#39;API</em>. L&#39;exercice est assez mécanique et
d&#39;autant plus simple si on l&#39;applique à la création du code en question. Pour ce
qui me concerne, c&#39;est le genre de chose que je fais au fil de l&#39;eau et que je
vérifie <a href="/post/vertus-revue-de-code/">dans une revue de code</a>.</p>
<p>Si on prend encore un peu plus de hauteur, ce principe s&#39;applique aussi très
bien à l&#39;ajout de toute fonctionnalité. Dit autrement, il est toujours
intéressant de questionner la solution vis à vis du besoin qu&#39;on cherche à
satisfaire pour systématiquement en tirer l&#39;essentiel et surtout en retirer tout le
reste. Dans ce contexte, cette démarche permet de restreindre autant que
possible le périmètre des changements et encore une fois de réduire la
complexité mais également de permettre de se concentrer sur l&#39;essentiel et
d&#39;obtenir un résultat satisfaisant le plus rapidement possible et, à partir de
là, d&#39;itérer jusqu&#39;à atteindre une solution qui apporte suffisamment de valeur.
Toute ressemblance avec l&#39;un <a href="https://agilemanifesto.org/iso/fr/principles.html">des principes du manifeste
agile</a> n&#39;est PAS fortuite
😛 :</p>
<blockquote>
<p>La simplicité – c’est à dire l&#39;art de minimiser la quantité de travail
inutile – est essentielle.</p>
</blockquote>
<p>Et puis cette démarche va au delà du code et des fonctionnalités, elle
s&#39;applique par exemple très bien au <em>workflow</em> des développeur·ses. Qui n&#39;a
jamais subi un <em>workflow</em> (CI, CD, <em>commit hook</em>,…) plus lourd que nécessaire ?
Ou à toutes ces réunions qui pourraient être un simple email 🫠 Ici, il s&#39;agit
plus <a href="/post/maximiser-efficacite-developpeurs/">d&#39;un potentiel problème
d&#39;efficacité</a> au quotidien mais là
encore le superflu peut peser lourd.</p>
<hr>
<p>Bref, sans surprise, identifier et <em>chasser le superflu</em> est un exercice
bénéfique pour la qualité d&#39;un projet logiciel et la productivité des
développeur·ses. Plus qu&#39;une simple habitude, pour moi, <strong>cette démarche doit
être active et systématique</strong>. Je la considère comme une clé dans l&#39;obtention
d&#39;un code maintenable sur le long terme et dans l&#39;efficience au quotidien.</p>
]]></description><link>https://damien.pobel.fr/post/chasser-le-superflu</link><guid isPermaLink="true">https://damien.pobel.fr/post/chasser-le-superflu</guid><category><![CDATA[code]]></category><category><![CDATA[métier]]></category><category><![CDATA[bonnes pratiques]]></category><category><![CDATA[ingénierie logicielle]]></category><category><![CDATA[qualité]]></category><category><![CDATA[complexité]]></category><category><![CDATA[dette technique]]></category><pubDate>Mon, 21 Apr 2025 00:00:00 GMT</pubDate></item><item><title><![CDATA[Personnaliser et rendre dynamique son profil GitHub]]></title><description><![CDATA[<figure class="object-center bordered">
  <img loading="lazy" src="/images/660x/fioles-apothicairerie.jpg" alt="Des fioles de l'Apothicairerie de Bourg-en-Bresse">
  <footer>Des fioles <a href="/post/apothicairerie-de-bourg-en-bresse/">de l'apothicairerie de Bourg-en-Bresse</a></footer>
</figure>

<p>Dans le numéro de <a href="https://javascriptweekly.com/issues/688">JavaScript Weekly de la
semaine dernière</a>, on trouve notamment <a href="https://tduyng.github.io/blog/dynamic-github-profile-with-bun-typescript/">Dynamic
GitHub profile with Bun and
Typescript</a>
où l&#39;auteur explique comment il personnalise et surtout rend dynamique son
profil GitHub. Cet article m&#39;a rappelé que j&#39;avais dans mes brouillons un billet
sur le même sujet et comme j&#39;utilise une approche un peu différente, c&#39;est
l&#39;occasion de le terminer de parler un peu <del>de la plomberie</del> l&#39;envers du décor.</p>
<p><a href="https://docs.github.com/fr/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/managing-your-profile-readme">La personnalisation d&#39;un profil GitHub est simple à mettre en
place</a>,
il suffit de créer un dépôt nommé comme votre nom d&#39;utilisateur
<code>username/username</code> et d&#39;y ajouter un fichier <code>README.md</code> à la racine pour que
son contenu soit repris sur le profil. Pour moi, le <code>README.md</code> de
<a href="https://github.com/dpobel/dpobel">https://github.com/dpobel/dpobel</a> se retrouve sur la page profile, ce qui donne
quelque chose comme :</p>
<figure class="object-center bordered">
  <a href="/images/profil-github-personnalise.png">
  <img loading="lazy" src="/images/660x/profil-github-personnalise.png" alt="Capture d'écran de mon profil GitHub personnalisé">
  </a>
  <footer>Capture d'écran de mon profil GitHub avant publication de ce billet</footer>
</figure>

<p>Il reste donc à mettre à jour régulièrement ce fichier pour que le profil
affiche des informations à jour. Dans mon cas, en plus d&#39;une courte
introduction, je souhaite afficher les derniers billets publiés sur ce site
ainsi que quelques billets sélectionnés. Comme l&#39;auteur de l&#39;article cité plus
haut, je pourrais mettre un peu de code dans le dépôt <code>username/username</code> et
lancer régulièrement un script <em>via</em> GitHub Actions (ou autre) pour mettre à
jour le <code>README.md</code> à partir de flux RSS. Néanmoins, je vois au moins deux
inconvénients dans cette approche (qui a quand même le mérite d&#39;une certaine
simplicité) :</p>
<ol>
<li>il faut nécessairement ajouter du code dans le dépôt <code>username/username</code>
  ce qui implique un peu de maintenance</li>
<li>l&#39;action de mise à jour doit être configurée pour s&#39;exécuter régulièrement
  quelque soit l&#39;activité sur ce site, compte tenu des hauts et des bas des
  publications par ici, ce n&#39;est probablement pas une utilisation de ressources
  très efficace 😉</li>
</ol>
<p>Par ailleurs, au moment où j&#39;ai voulu mettre en place cette personnalisation,
j&#39;avais un besoin proche qui consistait à également tenir à jour
<a href="https://dpobel.github.io/">https://dpobel.github.io/</a> en fonction de l&#39;activité ici. Là encore, j&#39;aurais pu
mettre un peu de code dans le dépôt correspondant pour construire une page ce
qui aurait occasionné les mêmes inconvénients.</p>
<p>Bref, en cherchant une alternative, j&#39;ai découvert que <a href="https://docs.github.com/fr/actions/using-workflows/manually-running-a-workflow#running-a-workflow-using-the-rest-api">GitHub expose une API
REST qui permet notamment de déclencher un <em>workflow</em> GitHub
Actions</a>
offrant ainsi une manière d&#39;éliminer le second inconvénient. À partir de là,
j&#39;ai réalisé que je pouvais facilement ajouter dans la construction de ce site
la génération du <code>README.md</code> pour le dépôt <code>username/username</code> et d&#39;une page
HTML destinée à <a href="https://dpobel.github.io/">https://dpobel.github.io/</a> et qu&#39;ensuite à l&#39;issue du
déploiement, il suffisait de <a href="https://github.com/dpobel/damien.pobel.fr/blob/654a576227a853d00bd58133e7975eebc8e0197b/bin/deploy.sh#L14-L17">déclencher un <em>workflow</em> GitHub Actions par API
pour chacun de ces
dépôts</a>
qui peuvent se contenter de <a href="https://github.com/dpobel/dpobel/blob/7f68525f980af68294c0dd0d0f3b6db1cbf27a0b/.github/workflows/main.yml">télécharger un fichier et de le
<em>commiter</em></a>.
De cette manière, l&#39;essentiel de la logique est concentré dans la construction
de ce site qui pilote les mises à jour externes.</p>
<p>Pour résumer la recette de ma potion magique 🧙 :</p>
<ol>
<li>générer le <code>README.md</code> sur son site pour qu&#39;il soit déployé avec le
reste (ou le rendre disponible à une URL connue si vous utilisez un CMS dynamique)</li>
<li>Configurer un <em>workflow</em> GitHub Actions pour télécharger ce fichier et le
<em>commiter</em> sur le dépôt <code>username/username</code></li>
<li>sur un évènement par exemple au déploiement ou si vous utilisez un CMS sur la
publication d&#39;un nouveau contenu, faire un appel API pour déclencher ce
<em>workflow</em>.</li>
</ol>
<p>Et hop la magie opère ✨️ La même mécanique est à l&#39;œuvre pour la mise à jour de
<a href="https://dpobel.github.io/">https://dpobel.github.io/</a>. Si j&#39;en crois <a href="https://github.com/dpobel/dpobel/commits/main/">l&#39;historique des <em>commits</em> du dépôt
pour le profil</a> et <a href="https://github.com/dpobel/dpobel.github.io/commits/main/">de celui de
la page</a>, la magie
opère depuis un peu plus de 3 ans sans quasiment aucune intervention manuelle
sur ces dépôts.</p>
]]></description><link>https://damien.pobel.fr/post/personnaliser-rendre-dynamique-son-profil-github</link><guid isPermaLink="true">https://damien.pobel.fr/post/personnaliser-rendre-dynamique-son-profil-github</guid><category><![CDATA[github]]></category><category><![CDATA[github actions]]></category><category><![CDATA[architecture]]></category><category><![CDATA[blog]]></category><pubDate>Wed, 22 May 2024 00:00:00 GMT</pubDate></item><item><title><![CDATA[Structurer les tests pour les rendre plus lisibles et maintenables]]></title><description><![CDATA[<figure class="object-center bordered">
  <img loading="lazy" src="/images/660x/structure.jpg" alt="Photo de la structure d'un pylone en acier vue de son pied">
  <footer>Photo de <a href="https://pixabay.com/users/didgeman-153208/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=4459235">Thomas</a></footer>
</figure>


<p>Si vous écrivez des tests en JavaScript / TypeScript, il est plus que probable
que vous ayez déjà croisé les fonctions <code>describe</code> et <code>it</code> . En effet, les
frameworks de test les plus populaires comme Jest, Mocha ou encore Jasmine
<a href="https://bignerdranch.com/blog/why-do-javascript-test-frameworks-use-describe-and-beforeeach/">s&#39;inspirent tous de
RSpec</a>
et mettent à disposition ces fonctions pour écrire et structurer les suites de
tests. Dans sa documentation, Mocha désigne cette API <a href="https://mochajs.org/#bdd">l&#39;interface <abbr
title="Behavior Driven Development">BDD</abbr></a>.</p>
<p>Un autre pratique courante pour structurer le code d&#39;un cas de test est
d&#39;utiliser des commentaires pour séparer les différentes étapes du test
notamment le triptyque <code>Given</code>, <code>When</code>, <code>Then</code> (inspiré de BDD encore) ou son
équivalent souvent abrégé <code>AAA</code>: <code>Arrange</code>, <code>Act</code>, <code>Assert</code>. Par exemple :</p>
<pre><code class="language-javascript"><span class="hljs-title function_">describe</span>(<span class="hljs-string">&#x27;MyComponent&#x27;</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> sut = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyComponent</span>();

  <span class="hljs-title function_">it</span>(<span class="hljs-string">&#x27;should do stuff when the input is something&#x27;</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Given</span>
    <span class="hljs-keyword">const</span> input = <span class="hljs-title function_">buildSomeInput</span>();

    <span class="hljs-comment">// When</span>
    sut.<span class="hljs-title function_">doStuff</span>(input);

    <span class="hljs-comment">// Then</span>
    <span class="hljs-title function_">expect</span>(sut).<span class="hljs-title function_">toHaveDoneSomething</span>();
  });
});
</code></pre>
<p>Ces commentaires peuvent être une aide pour structurer son code mais comme
d&#39;habitude, <a href="/post/juste-dose-commentaires-dans-le-code/">ils sont une bonne occasion de se demander si il n&#39;est pas possible
de rendre le code plus expressif</a>
et <em>spoiler alert</em>, c&#39;est le sujet de cet article 😉</p>
<p>On peut déjà remarquer que la ligne après <code>Given</code> est la mise en place de l&#39;état
indiqué par <code>when the input is something</code> dans l&#39;intitulé du test. Également,
quelque soit le framework de test utilisé, <code>describe</code> est non seulement une API
pour grouper des cas de tests mais cette fonction offre aussi la possibilité
d&#39;utiliser des <em>hooks</em> notamment pour déclencher des actions avant chaque cas de
test ou avant tous les tests inclus dans ce <code>describe</code>. Donc en combinant une
bonne description (le premier paramètre de <code>describe</code>) par exemple commençant
par <em>given</em> et un <em>hook</em> on obtient un code plus expressif qui incorpore ce
commentaire <code>Given</code> et lui associe le comportement correspondant. Reste <code>When</code>
et <code>Then</code>, mais sont ils bien utiles ? Systématiquement <code>When</code> sera destiné à la
première ligne du cas de test et vraisemblablement <code>Then</code> à tout le reste…</p>
<p>En d&#39;autre termes, l&#39;exemple ci-dessus peut-être réécrit de la manière
suivante :</p>
<pre><code class="language-javascript"><span class="hljs-title function_">describe</span>(<span class="hljs-string">&#x27;MyComponent&#x27;</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> sut = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyComponent</span>();

  <span class="hljs-title function_">describe</span>(<span class="hljs-string">&#x27;given the input is something&#x27;</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">let</span> input;

    <span class="hljs-title function_">beforeEach</span>(<span class="hljs-function">() =&gt;</span> {
      input = <span class="hljs-title function_">buildSomeInput</span>();
    });

    <span class="hljs-title function_">it</span>(<span class="hljs-string">&#x27;should do stuff&#x27;</span>, <span class="hljs-function">() =&gt;</span> {
      sut.<span class="hljs-title function_">doStuff</span>(input);

      <span class="hljs-title function_">expect</span>(sut).<span class="hljs-title function_">toHaveDoneSomething</span>();
    });
  })
});
</code></pre>
<p>Évidemment sur un exemple aussi simple, la différence est minime mais sur des
suites de tests combinant plusieurs états ce <em>pattern</em> s&#39;avère particulièrement
pratique, par exemple imaginons un composant dont la responsabilité est de
notifier un utilisateur en fonction de son profil et d&#39;une configuration, la
suite de tests pourrait ressembler à :</p>
<pre><code class="language-javascript"><span class="hljs-title function_">describe</span>(<span class="hljs-string">&quot;Notifier&quot;</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> sut = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Notifier</span>(<span class="hljs-comment">/* some dependencies */</span>);

  <span class="hljs-title function_">describe</span>(<span class="hljs-string">&quot;given the user is a free user&quot;</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-title function_">beforeEach</span>(<span class="hljs-function">() =&gt;</span> {
      <span class="hljs-comment">// … setup the user as a free user</span>
    })

    <span class="hljs-title function_">it</span>(<span class="hljs-string">&quot;should not notify the user&quot;</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-comment">// …</span>
    });
  })

  <span class="hljs-title function_">describe</span>(<span class="hljs-string">&quot;given the user is a premium user&quot;</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-title function_">beforeEach</span>(<span class="hljs-function">() =&gt;</span> {
      <span class="hljs-comment">// … setup the user as a premium user</span>
    })

    <span class="hljs-title function_">describe</span>(<span class="hljs-string">&quot;given she has configured the notifications to be issued by SMS&quot;</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-title function_">beforeEach</span>(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-comment">// … setup user&#x27;s notification to sms</span>
      })

      <span class="hljs-title function_">it</span>(<span class="hljs-string">&quot;should notify the user by sms&quot;</span>, <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-comment">// …</span>
      });
    });

    <span class="hljs-title function_">describe</span>(<span class="hljs-string">&quot;given she has configured the notifications to be issued by email&quot;</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-title function_">beforeEach</span>(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-comment">// … setup user&#x27;s notification to email</span>
      })

      <span class="hljs-title function_">it</span>(<span class="hljs-string">&quot;should notify the user by email&quot;</span>, <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-comment">// …</span>
      });
    });
  })
});
</code></pre>
<p>Cette structuration offre plusieurs avantages :</p>
<ol>
<li>le couple systématique <code>describe(&quot;given …&quot;)</code> / <code>beforeEach</code> introduit une forme de
cohésion, il est facile de voir si le <em>hook</em> implémente réellement la
description ou à l&#39;inverse de comprendre ce qu&#39;implique la pré-condition ;</li>
<li>la suite de tests est facile à faire évoluer, par exemple si demain une
nouvelle configuration permet d&#39;envoyer des notifications par Slack ou tout
autre moyen, il suffit d&#39;ajouter un bloc <code>describe</code> et le tour est joué ;</li>
<li>en lançant le test, on obtient une spécification du composant testé (en
fonction du <em>reporter</em> utilisé), dans cette exemple, quelque chose comme :<pre><code class="language-txt">Notifier
  given the user is a free user
    ✔ should not notify the user
  given the user is a premium user
    given she has configured the notifications to be issued by SMS
      ✔ should notify the user by sms
    given she has configured the notifications to be issued by email
      ✔ should notify the user by email
</code></pre>
ce qui s&#39;avère bien pratique pour comprendre une base de code existante ;</li>
<li>lorsqu&#39;un test échouera, la structure a toutes les chances de faciliter la
compréhension de l&#39;erreur et avec un peu de chance de faciliter
l&#39;identification du bug.</li>
</ol>
<p>Et j&#39;en oublie probablement !</p>
<p>En bref, l&#39;utilisation de <code>describe</code> et de ses <em>hooks</em> permet de structurer les
tests. Cette structure impose notamment d&#39;isoler et surtout de nommer
correctement les différents états ce qui rend les tests plus lisibles et maintenables à
relativement peu de frais en <a href="/post/tests-antipatterns-agacants/#les-tests-incompr%C3%A9hensibles-car-r%C3%A9dig%C3%A9s-avec-des-termes-inconnus">s&#39;éloignant de quelques <em>antipatterns</em>
courants</a>
ou au contraire pour essayer <a href="/post/bon-test-unitaire-integration-fonctionnel/#facile-%C3%A0-interpr%C3%A9ter-quand-il-%C3%A9choue">d&#39;écrire de bons
tests</a>.</p>
]]></description><link>https://damien.pobel.fr/post/structurer-tests-lisibles-describe</link><guid isPermaLink="true">https://damien.pobel.fr/post/structurer-tests-lisibles-describe</guid><category><![CDATA[unit test]]></category><category><![CDATA[bonnes pratiques]]></category><category><![CDATA[qualité]]></category><category><![CDATA[code]]></category><category><![CDATA[javascript]]></category><category><![CDATA[typescript]]></category><category><![CDATA[ingénierie logicielle]]></category><category><![CDATA[behaviour driven development]]></category><pubDate>Tue, 09 Apr 2024 00:00:00 GMT</pubDate></item><item><title><![CDATA[La qualité est systémique]]></title><description><![CDATA[<figure class="object-center bordered">
    <img loading="lazy" src="/images/660x/feuille.jpg" alt="Photo d'une feuille mettant en évidence sa structure">
    <footer>Photo de <a href="https://unsplash.com/fr/@ohutcherson">Olivia Hutcherson</a></footer>
</figure>

<p>Je suis tombé aujourd&#39;hui sur <a href="https://jacobian.org/2022/sep/9/quality-is-systemic/">Quality is
systemic</a> de <a href="https://jacobian.org/">Jacob
Kaplan-Moss</a> que je trouve particulièrement juste.</p>
<p>Traduction rapide du premier paragraphe :</p>
<blockquote>
<p>La qualité logicielle est plus le résultat d&#39;un système conçu pour produire de
la qualité et pas tellement le résultat de performances individuelles.
C&#39;est-à-dire : un groupe de programmeurs médiocres travaillant avec une
structure conçue pour produire de la qualité produira un meilleur logiciel
qu&#39;un groupe de programmeurs fantastiques travaillant dans un système conçu
pour d&#39;autres objectifs.</p>
</blockquote>
<p>En d&#39;autres termes pour obtenir de la qualité il faut une organisation
construite pour la produire. L&#39;auteur donne quelques exemples de
caractéristiques systémiques permettant de produire de la qualité :</p>
<ul>
<li>une organisation et une culture qui permettent et encouragent <a href="/post/bon-test-unitaire-integration-fonctionnel/">l&#39;écriture de
bons tests</a> ;</li>
<li>une culture qui ne pousse pas à mettre en production du code qui n&#39;est pas
prêt ou <a href="/post/au-cas-ou/">qui est inutile</a> ;</li>
<li>une cadence de développement qui permet de correctement architecturer le code
et de le documenter ;</li>
<li>un environnement de travail où les personnes se sentent en sécurité et
n&#39;hésitent pas à demander de l&#39;aide au besoin ;</li>
<li>une culture où les échecs sont analysés sans chercher de coupable et où le
système est amélioré pour éviter les échecs similaires.</li>
</ul>
<p>Je trouve ce dernier point particulièrement important. À titre personnel c&#39;est
quelque chose que je m&#39;attache à toujours faire mais j&#39;ai vu relativement peu
d&#39;organisations où c&#39;était une démarche systématique.</p>
<p>Et il existe probablement des tas d&#39;autres paramètres comme une culture qui
permet une forme d&#39;auto-organisation et offre une certaine liberté, une
organisation où on ne travaille que sur un seul sujet à la fois ou encore une
culture qui célèbre autant voire plus la suppression de code que l&#39;ajout… Tout
ceci fait largement écho à <a href="/post/maximiser-efficacite-developpeurs/">Maximiser l&#39;efficacité des
développeur·ses</a> sous un angle plus…
systémique.</p>
]]></description><link>https://damien.pobel.fr/post/la-qualite-est-systemique</link><guid isPermaLink="true">https://damien.pobel.fr/post/la-qualite-est-systemique</guid><category><![CDATA[veille]]></category><category><![CDATA[métier]]></category><category><![CDATA[bonnes pratiques]]></category><category><![CDATA[qualité]]></category><category><![CDATA[code]]></category><category><![CDATA[architecture]]></category><category><![CDATA[unit test]]></category><category><![CDATA[ingénierie logicielle]]></category><pubDate>Sat, 23 Mar 2024 00:00:00 GMT</pubDate></item><item><title><![CDATA[La maintenabilité comme critère de décision]]></title><description><![CDATA[<figure class="object-center bordered">
  <img loading="lazy" src="/images/660x/shrug.png" alt="Image où il est inscrit
  ¯\_(ツ)_/¯ qui signifie shrug ou haussement d'épaule.">
</figure>

<p>En début d&#39;année, j&#39;ai lu <a href="https://www.packtpub.com/product/get-your-hands-dirty-on-clean-architecture-second-edition/9781805128373">Get Your Hands Dirty on Clean Architecture (Second
Edition)</a>
de <a href="https://reflectoring.io/authors/tom/">Tom Hombergs</a>. Comme son titre
l&#39;indique, ce très bon livre traite de la <em>Clean Architecture</em> et plus
particulièrement de <a href="https://fr.wikipedia.org/wiki/Architecture_hexagonale">l&#39;architecture
hexagonale</a>. Tout au long
des quelques 140 pages, l&#39;auteur aborde ce type d&#39;architecture sous différents
aspects mais il en est un qui revient régulièrement tout en étant le sujet du
premier chapitre : <strong>la maintenabilité</strong>.</p>
<p>Une bonne partie de ce premier chapitre peut se résumer par cette expression
<em>pseudo-mathématique</em> :</p>
<pre><code class="language-plaintext">maintenabilité &gt;&gt;&gt; tout le reste
</code></pre>
<p>Dans <em>tout le reste</em> rentrent les qualités qu&#39;on cherche souvent à atteindre
dans la construction d&#39;un logiciel par exemple les performances, la
<em>scalabilité</em>, la robustesse, la flexibilité et bien d&#39;autres… Et comme
l&#39;explique très bien l&#39;auteur, la maintenabilité a ceci de spécial qu&#39;elle est
une qualité qui permet d&#39;atteindre toutes les autres. En effet, dès qu&#39;un
logiciel est maintenable, il est facile à faire évoluer pour atteindre certaines
qualités <a href="/post/au-cas-ou/">dès que le besoin émerge</a>. Évidemment, l&#39;ajout de
fonctionnalités et la correction des bugs sont également d&#39;autant plus simples que le
code est maintenable. En d&#39;autres termes, la maintenabilité aide à la fois à
atteindre des objectifs fonctionnels et non fonctionnels.</p>
<p>Je formule généralement cette idée de la manière suivante :</p>
<blockquote>
<p>Un bon code est un code facile à changer.</p>
</blockquote>
<p>Ni plus, ni moins. Jusque là, rien de très original je crois mais ça va mieux en
le disant 😁</p>
<p>Dans ce chapitre, Tom Hombergs pousse la réflexion un peu plus loin et notamment
en énonçant ce qui m&#39;apparaît maintenant comme un corollaire :</p>
<blockquote>
<p>Whenever we have to decide between multiple options, we can choose the one
that makes the code easier to change in the future. No more agonizing between
different options. We just take the one that increases maintainability the
most.</p>
</blockquote>
<p>ce qui peut se traduire par :</p>
<blockquote>
<p>Chaque fois que nous devons choisir entre plusieurs options, nous pouvons
choisir celle qui rendra le code plus facile à changer dans le futur. Plus
besoin de se torturer l&#39;esprit entre différentes options. Nous choisissons
simplement celle qui augmente le plus la maintenabilité.</p>
</blockquote>
<p>Quand j&#39;ai lu cette partie, je dois dire qu&#39;une petite lumière s&#39;est allumée
dans ma tête 💡 J&#39;ai beau être convaincu de l&#39;importance de la maintenabilité
depuis de nombreuses années maintenant, je n&#39;avais jamais considéré cette
qualité comme une aide à la décision de manière aussi directe. Et forcément, en
regardant un peu dans le rétroviseur, je me rends compte qu&#39;appliquer ce
principe dans certaines décisions aurait potentiellement mener à de meilleurs
choix.</p>
<p>Comme souvent avec ce genre de principe général, il s&#39;agit d&#39;un élément parmi
beaucoup d&#39;autres et comme l&#39;indique Tom Hombergs, le <em>bon</em> choix n&#39;est parfois
pas celui qui améliore ou conserve la maintenabilité. Néanmoins opter pour ce
principe par défaut me semble être une bonne approche.</p>
]]></description><link>https://damien.pobel.fr/post/la-maintenabilite-comme-critere-de-decision</link><guid isPermaLink="true">https://damien.pobel.fr/post/la-maintenabilite-comme-critere-de-decision</guid><category><![CDATA[bonnes pratiques]]></category><category><![CDATA[métier]]></category><category><![CDATA[travail]]></category><category><![CDATA[qualité]]></category><category><![CDATA[code]]></category><category><![CDATA[veille]]></category><category><![CDATA[ingénierie logicielle]]></category><pubDate>Sat, 02 Mar 2024 00:00:00 GMT</pubDate></item><item><title><![CDATA[Utils et helper sont sur un bateau…]]></title><description><![CDATA[<figure class="object-center bordered">
  <img loading="lazy" src="/images/660x/plouf.jpg" alt="Petites vaguelettes
  provoquées par un objet tombant à l'eau avec une luminosité évoquant un
  coucher de soleil">
</figure>

<p>Et si on les <del>jetait à l&#39;eau</del> <em>refactorisait</em> ? 😀</p>
<p>Dans <a href="/post/vertus-revue-de-code/">une revue de code</a> ou en explorant une base
code, ces noms là, tout comme dans une certaine mesure les <em>handlers</em> et autres
<em>managers</em>, déclenchent systématiquement dans ma tête une petite alarme 🔔 qui
appelle à aller regarder de plus près ce qui se cache derrière.</p>
<p>Ces termes sont très génériques même si ils sont souvent
accompagnés d&#39;un préfixe, d&#39;un suffixe ou d&#39;un chemin un peu spécifique (encore
qu&#39;on a tous dû tomber au moins une fois sur un <code>src/utils.js</code> quand ce n&#39;est
pas <code>src/tools/utils.js</code> 😉). Et par
conséquent, la ou les responsabilités de ces composants sont loin d&#39;être
claires. D&#39;ailleurs, ce genre de composant a une sérieuse tendance à être un
fourre-tout avec beaucoup plus qu&#39;une unique responsabilité.</p>
<p>Aussi, quand ce genre de composant occupe une place importante dans le code en
terme de quantité de logique, c&#39;est autant de logique qui n&#39;est pas là où elle
aurait plus de sens. L&#39;utilisation abusive de ce genre de composant va de pair
avec d&#39;autres <em>code smells</em>, notamment :</p>
<ul>
<li><a href="https://martinfowler.com/bliki/AnemicDomainModel.html">des objets
anémiques</a> : les objets
métiers se retrouvent dépourvus de comportement puisqu&#39;il est relégué dans ces
<em>helpers</em> et <em>utils</em> ;</li>
<li><a href="https://fr.wikipedia.org/wiki/Encapsulation_(programmation)">un manque
d&#39;encapsulation</a> :
les objets exposent nécessairement plus qu&#39;ils ne devraient pour que ces
composants puissent faire leur travail ;</li>
<li>des abstractions manquantes : là encore, une responsibilité qui pourrait être
proprement isolée dans un composant bien nommé se retrouve diluée.</li>
</ul>
<p>C&#39;est pourquoi, en ce qui me concerne, chaque mention d&#39;un <em>utils</em> ou d&#39;un
<em>helper</em> me rend plus que méfiant. Quasiment systématiquement il existe une
meilleure solution en terme d&#39;expressivité, de qualité de code et <a href="/post/la-maintenabilite-comme-critere-de-decision/">de
maintenabilité</a>.</p>
]]></description><link>https://damien.pobel.fr/post/utils-helper-sont-sur-un-bateau</link><guid isPermaLink="true">https://damien.pobel.fr/post/utils-helper-sont-sur-un-bateau</guid><category><![CDATA[bonnes pratiques]]></category><category><![CDATA[métier]]></category><category><![CDATA[travail]]></category><category><![CDATA[qualité]]></category><category><![CDATA[code]]></category><category><![CDATA[ingénierie logicielle]]></category><pubDate>Fri, 23 Feb 2024 00:00:00 GMT</pubDate></item><item><title><![CDATA[Quelques défis liés à l'édition d'un logiciel destiné à être intégré]]></title><description><![CDATA[<figure class="object-center bordered">
    <img loading="lazy" src="/images/660x/shape.jpg" alt="Une poterie en cours
    de façonnage">
    <footer>
    Photo par <a
    href="https://pixabay.com/users/marcelkessler-3217273/">marcelkessler</a>
    </footer>
</figure>

<p>J&#39;ai écrit un petit blabla sur le tout neuf <a href="https://developers.front-commerce.com/blog">Developers blog de
Front-Commerce</a> (oui on a pas
vraiment fait dans l&#39;originalité 😉) sur quelques défis lié à l&#39;édition d&#39;un
logiciel destiné à être intégré par rapport à d&#39;autres contextes comme le service
ou la distribution en <abbr title="Software As A Service, Logiciel en tant que
service">SAAS</a>.</p>
<p>Traduction libre de l&#39;introduction:</p>
<blockquote>
<p>Pour l&#39;essentiel, Front-Commerce est un logiciel destiné à être intégré par
des développeurs pour qu&#39;un marchand puisse vendre des produits à ses clients
dans une boutique en ligne à son image et même en s&#39;appuyant sur une
infrastructure existante. S&#39;il s&#39;agit probablement de la définition la plus
simple de Front-Commerce (plus ou moins celle que j&#39;utilise pour décrire mon
travail à ma famille et mes amis 😉), elle cache néanmoins un certain nombre
de défis au quotidien.</p>
</blockquote>
<p>La suite <del>va vous étonner</del> est disponible dans <a href="https://developers.front-commerce.com/blog/some-challenges-of-being-the-editor-of-a-software-intended-to-be-integrated#three-targets-developers-merchants-and-customers">Some challenges of being the editor of
a software intended to be
integrated</a> (en anglais).</p>
]]></description><link>https://damien.pobel.fr/post/quelques-defis-editeur-logiciel-integration</link><guid isPermaLink="true">https://damien.pobel.fr/post/quelques-defis-editeur-logiciel-integration</guid><category><![CDATA[travail]]></category><category><![CDATA[métier]]></category><category><![CDATA[code]]></category><pubDate>Wed, 07 Dec 2022 00:00:00 GMT</pubDate></item><item><title><![CDATA[Tests : mon top 8 des anti-patrons les plus agaçants]]></title><description><![CDATA[<p>Il y a un peu plus trois ans, je publiais <a href="/post/bon-test-unitaire-integration-fonctionnel">Au fait, c&#39;est quoi un bon test
unitaire, d&#39;intégration ou
fonctionnel ?</a>, un billet où je
décrivais quelques caractéristiques d&#39;une bonne suite de tests logiciel. Ce
billet reste d&#39;actualité mais depuis, je me suis frotté à plusieurs
environnements accumulant parfois plusieurs <em>antipatterns</em>, certains
particulièrement pénibles. Alors cette fois ci, je prends le sujet dans l&#39;autre
sens, voici une sélection des anti-patrons liés aux tests que j&#39;ai pu croisés
plus ou moins récemment.</p>
<figure class="object-center bordered">
    <img loading="lazy" src="/images/660x/angry-cat.jpg" alt="Un chat donnant l'impression d'être agacé">
    <footer>
    Photo par <a
    href="https://pixabay.com/users/skitterphoto-324082/">Skitterphoto</a>
    </footer>
</figure>

<h2 id="les-tests-pas-lancés-automatiquement">Les tests pas lancés automatiquement</h2>
<p>Une suite de tests qui n&#39;est pas lancée automatiquement ne sert (quasiment) à
rien. Bien sûr, si on se lance dans un effort pour écrire des tests (en
particulier des tests <em>end to end</em> ou fonctionnels), cet état peut être
<em>transitoire</em> le temps d&#39;investir suffisamment de temps pour automatiser
l&#39;ensemble mais clairement il faut essayer d&#39;en sortir le plus rapidement
possible sinon arrivera invariablement le moment où un·e développeur·se cassera
quelque chose sans s&#39;en rendre compte et généralement, il faut pas longtemps 😉</p>
<p>Dans cette catégorie, il arrive aussi qu&#39;une partie des tests ne soient pas
lancer automatiquement, par exemple lors de l&#39;ajout de code dans un endroit pour
lequel le <em>test runner</em> n&#39;est pas configuré. C&#39;est assez vicieux et pas
forcément évident à détecter; on peut éventuellement
surveiller l&#39;évolution <a href="/post/code-coverage-taux-couverture-tests/">du taux de couverture et/ou jeter un œil à un rapport de
couverture</a>.</p>
<h2 id="les-tests-superficiels">Les tests superficiels</h2>
<blockquote>
<p>ce rapport de bug est surprenant, on a un test qui vérifie exactement ce comportement<br>[quelques minutes plus tard…]<br>aaah reproduit, le test ne vérifiait rien en fait 😠</p>
</blockquote>
<p>Écrire des tests c&#39;est bien, écrire des tests qui vérifient réellement un
comportement c&#39;est encore mieux. Par exemple, imaginons que vous vouliez tester
une API HTTP plus ou moins RESTful qui permette de créer une entité quelconque
avec une requête <code>POST</code> et qui lorsque tout se passe bien renvoie <a href="https://httpstatuses.com/201">une réponse
201</a>. Si les tests de cette fonctionnalité se
contentent de ne vérifier que le statut HTTP ou quelques trucs dans le contenu
de la réponse, eh bien vous avez un test (très) superficiel, il ne teste que
quelques détails et passe à côté de la fonctionnalité principale qui pourrait
très bien être complètement cassée sans que le test supposé la couvrir n&#39;échoue.
Bon c&#39;est mieux que rien mais ça donne un faux sentiment de sécurité.</p>
<p>Pour valider la qualité et la précision des tests, il est possible d&#39;employer
une technique appeler <a href="https://blog.ippon.fr/2020/05/20/le-mutation-testing-ou-comment-tester-ses-tests/">Mutation
testing</a>.
Il s&#39;agit en quelques sorte de tester les tests en introduisant artificiellement
des bugs pour vérifier sur les tests échouent, si ce n&#39;est pas le cas, vous avez
probablement des tests superficiels !</p>
<h2 id="les-tests-flaky">Les tests <em>flaky</em></h2>
<blockquote>
<p>ptet bien que oui, ptet bien que non</p>
<p>-- un test <em>flaky</em></p>
</blockquote>
<p>Le grand classique des tests qui échouent seulement de temps à autre sans raison
apparente. Ce type de problème peut être particulièrement compliqué à
diagnostiquer et plus les tests sont de haut niveau plus le nombre de
dépendances augmentent et avec elles les risques de <em>flakyness</em>.</p>
<p>Parfois, c&#39;est beaucoup plus simple qu&#39;il n&#39;y paraît. Pour l&#39;anecdote, il m&#39;est
déjà arrivé de subir des échecs aléatoires de tests en raison d&#39;une mauvaise
utilisation de <a href="https://www.php.net/rand"><code>rand()</code></a> dans des <em>fixtures</em> qui
n&#39;avaient de toute manière aucune raison d&#39;être aléatoires.</p>
<p>Malheureusement sur cet aspect, il n&#39;y a pas de solution magique. Je dirais que
le principal est de surveiller activement ce genre de comportement et surtout ne
pas laisser la situation s&#39;enliser car les choses auront plutôt tendance à
empirer qu&#39;à se résoudre d&#39;elles-mêmes.</p>
<h2 id="les-tests-difficiles-à-interpréter-car-trop-verbeux">Les tests difficiles à interpréter car trop verbeux</h2>
<blockquote>
<p>Ah je crois que les tests sont en train d&#39;échouer… Ah non en fait, ah je sais
pas, c&#39;est normal d&#39;avoir 3000 lignes sur la sortie après une minute
d&#39;éxécution sur la CI ?</p>
<p>-- un·e dévéloppeur·se proche de la noyade</p>
</blockquote>
<p>Ce problème est assez typique des tests avec du code en JavaScript, il faut dire
que les méthodes <code>console.log</code> et consorts sont tellement faciles d&#39;accès,
qu&#39;elles finissent par être utilisées avec un peu trop de zèle au moindre cas
limite. La sortie des tests finit par être un joyeux bazar au point que
parfois il devient difficile de savoir si les tests passent ou échouent.
<a href="https://jestjs.io/docs/cli#--silent">Jest propose une option
<code>--silent</code></a> mais pour moi cela
s&#39;apparente plus à mettre la poussière sous le tapis qu&#39;à résoudre le soucis.
Dans un monde idéal, les tests devraient être silencieux et si quelque chose
n&#39;est pas correct, ils devraient juste échouer; <a href="https://github.com/facebook/prop-types/issues/28">oui, prop-types c&#39;est quoi que
je regarde en fronçant les sourcils</a> !</p>
<h2 id="les-tests-incompréhensibles-car-rédigés-avec-des-termes-inconnus">Les tests incompréhensibles car rédigés avec des termes inconnus</h2>
<blockquote>
<p>Entretien d&#39;embauche :</p>
<ul>
<li>nous on fait du <abbr title="Domain Driven
Design">DDD</abbr> et on a des tests en mode <abbr title="Behavior Driven
Development">BDD</abbr></li>
<li>super, vous mettez l&#39;accent sur la qualité, où est ce que je signe ?</li>
</ul>
</blockquote>
<p>En réalité, c&#39;était l&#39;un des plus gros mensonges de ma
carrière professionnelle… Il y avait vaguement <a href="https://www.lilobase.me/le-domain-driven-design-sous-langle-strategique-une-introduction/">une approche DDD
technique ou
tactique</a>
et oui des tests écrits en Gherkin mais <a href="https://blog.ippon.fr/2021/02/24/4-idees-recues-sur-le-bdd-behavior-driven-development/">sans l&#39;aspect
comportement ni la plupart du temps le moindre bout de domaine</a>
et je parle pas de l&#39;implémentation des phrases…</p>
<p>Bref, qu&#39;on fasse du BDD ou non, <a href="/post/structurer-tests-lisibles-describe/">en lisant les tests, le ou la développeur·se
doit pouvoir comprendre ce que fait le composant/la fonction/l&#39;API testée</a> et
comment elle est supposée être utilisée. C&#39;est pourquoi le nommage doit être
particulièrement soigné. Il est aussi évident que les tests sont des bouts de
code qui vont nécessiter de la maintenance. Dans ces conditions appliquer <a href="/post/clean-code/">les
principes de <em>clean code</em></a> est plus que jamais une bonne idée
que votre futur·e vous appréciera sans aucun doute.</p>
<h2 id="les-tests-qui-échouent-avec-un-message-derreur-cryptique">Les tests qui échouent avec un message d&#39;erreur cryptique</h2>
<p>En contrôlant la verbosité et en soignant le nommage, on évite pas mal d&#39;écueils
à ce niveau. Malgré tout, lorsqu&#39;on écrit des tests, il faut toujours avoir à
l&#39;esprit que le but est qu&#39;ils échouent en communiquant clairement le problème.
Par exemple, si vous utilisez <a href="https://docs.phpunit.de/en/11.1/assertions.html">les assertions de
PHPUnit</a>, il est plus que
probable que vous devriez penser à utiliser le paramètre optionnel <code>$message</code>
pour améliorer cet aspect. Toujours avec PHPUnit, l&#39;utilisation de <em>data
provider</em> permet généralement de tester rapidement un grand nombre combinaisons
mais dans ce cas,
<a href="https://docs.phpunit.de/en/11.1/writing-tests-for-phpunit.html#data-providers">bien nommer chaque combinaison améliorera grandement la compréhensibilité d&#39;un
éventuel
échec</a>
et en bonus devoir trouver un nom à chaque combinaison, vous forcera peut-être à
<a href="/post/au-cas-ou/">simplifier votre API</a> et/ou à détecter des cas qui n&#39;ont
aucun sens dans votre domaine.</p>
<h2 id="les-tests-qui-mockent-lunivers">Les tests qui <em>mockent</em> l&#39;Univers</h2>
<p>Un grand classique d&#39;une stratégie de tests pas vraiment réfléchie du genre
<em>tout doit être testé unitairement</em> et/ou d&#39;un
peu trop d&#39;attention portée <a href="/post/code-coverage-taux-couverture-tests/">au taux de
couverture</a>. En soit, il est normal
de <em>mocker</em> les dépendances d&#39;un composant que l&#39;on souhaite tester
unitairement. Néanmoins, si le composant en question a beaucoup de dépendances
et/ou <a href="https://matthiasnoback.nl/2018/02/mocking-at-architectural-boundaries-persistence-and-time/">des dépendances qui proviennent d&#39;autres projets</a>,
il est clair que le test risque d&#39;être pénible à maintenir et pire, il pourrait
même être un frein au <em>refactoring</em> et à l&#39;évolution du composant testé ! Pour
éviter cela, deux solutions complémentaires :</p>
<ol>
<li>D&#39;un côté, on peut considérer que le composant en question nécessite un
<em>refactoring</em> pour diminuer le nombre de dépendances (avec autant de
dépendances il est probable qu&#39;il ait un peu trop de responsabilités) et pour
s&#39;abstraire des dépendances que l&#39;on ne contrôle pas, l&#39;idée étant de tendre
vers <a href="https://fr.wikipedia.org/wiki/Architecture_hexagonale_(logiciel)#Variantes">une architecture hexagonale ou en
oignon</a>.</li>
<li>On peut aussi opter pour des tests de plus haut niveau comme des tests
d&#39;intégration ou fonctionnels pour éviter de tout <em>mocker</em> et tester un peu
moins unitairement chaque composant. Le prix à payer est une mise en place
des tests potentiellement un peu plus complexe et éventuellement un peu
moins de couverture (certains cas limites peuvent être plus difficiles à
obtenir) mais en contrepartie ces tests seront plus simples et surtout à
partir du moment où la fonctionnalité est couverte, on peut la retravailler
en tout sérénité et éventuellement se lancer dans le <em>refactoring</em> évoqué
précédemment.</li>
</ol>
<p>Comme toujours en développement, c&#39;est une affaire de contexte, de compromis et
de stratégie.</p>
<h2 id="les-tests-interdépendants">Les tests interdépendants</h2>
<blockquote>
<p>Je comprends pas, j&#39;ai changé 3 détails dans une méthode et j&#39;ai 30 tests qui
échouent dans les tests fonctionnels de l&#39;API REST</p>
<p>-- Un·e développeur·se devant un château de cartes qui s&#39;effondre</p>
</blockquote>
<p>Alors bien sûr il est possible de faire échouer beaucoup de tests avec peu de
changements mais la dernière fois où je me suis trouvé en face de cette
situation la raison était un peu différente. J&#39;avais effectivement introduit un bug
dans la création d&#39;une entité quelconque ce qui aurait du faire échouer 3
tests mais en fait les 27 autres assumaient que ces premiers tests
passaient pour utiliser les données créées… une belle manière de rendre les
choses confuses. J&#39;ai aussi vu des suites de tests ou certains tests en
appellent directement d&#39;autres voire même issues d&#39;une autre suite de tests ! Là
encore, c&#39;est l&#39;effet château de cartes au moindre bug.</p>
<hr>
<p>Tout ceci est du vécu ; heureusement pour ma santé
mentale, j&#39;ai jamais vu de projet qui cumulait tous ces <em>antipatterns</em>, après
j&#39;ai aussi vu pas mal de projets <em>critiques</em> sans aucun test 😀</p>
<p>Plus sérieusement, tous ces défauts ne sont pas seulement agaçants, ce sont
surtout des obstacles <a href="/post/maximiser-efficacite-developpeurs/">pour travailler
efficacement</a> et pour produire un
logiciel robuste et de qualité ce qui est quand même un comble pour une
technique justement supposée améliorer ces aspects.</p>
]]></description><link>https://damien.pobel.fr/post/tests-antipatterns-agacants</link><guid isPermaLink="true">https://damien.pobel.fr/post/tests-antipatterns-agacants</guid><category><![CDATA[bonnes pratiques]]></category><category><![CDATA[unit test]]></category><category><![CDATA[qualité]]></category><category><![CDATA[code]]></category><category><![CDATA[behaviour driven development]]></category><category><![CDATA[tdd]]></category><category><![CDATA[php]]></category><category><![CDATA[javascript]]></category><category><![CDATA[ingénierie logicielle]]></category><category><![CDATA[clean code]]></category><pubDate>Thu, 08 Apr 2021 00:00:00 GMT</pubDate></item><item><title><![CDATA[Pourquoi utiliser des hooks sur-mesure dans vos composants React]]></title><description><![CDATA[<figure class="object-center bordered">
    <img loading="lazy" src="/images/660x/funny-box.jpg" alt="Une boîte de laquelle sort un mouton en peluche rigolo">
    <footer>Photo de <a href="https://pixabay.com/users/alexas_fotos-686414/">Alexas_Fotos</a></footer>
</figure>

<p><a href="https://kyleshevlin.com/use-encapsulation">useEncapsulation or Why Your React Components Should Only Use Custom
Hooks</a> par Kyle Shevlin donne une
excellente explication :</p>
<blockquote>
<p>[…] These custom hooks give us a little more context to what they mean, and we
don&#39;t have the implementation details of our state handler functions sitting
in the middle of our component function.</p>
</blockquote>
<p>que je traduis grossièrement par :</p>
<blockquote>
<p>[…] Ces hooks sur-mesure donnent un peu plus de contexte sur leur
signification et permettent de ne pas mélanger leurs détails d&#39;implémentation
avec la fonction qui sert de composant.</p>
</blockquote>
<p>ou autrement dit, cette approche permet de séparer la logique purement
d&#39;affichage de la logique disons <em>métier</em> (même si les exemples sont simplistes)
à laquelle il est obligatoire de donner un nom. Le bénéfice est immédiat : <strong>une
bien meilleure lisibilité</strong>.</p>
<p>Ce n&#39;est pas mentionné dans l&#39;article, mais en bonus cette approche donne
l&#39;opportunité de tester unitairement cette logique <em>métier</em> et d&#39;éventuellement
laisser de côté l&#39;affichage (ou de le tester différemment) et également de
pouvoir composer d&#39;autres composants avec cette même logique.</p>
<p>Dernier point, quand je regarde ce hook sur-mesure :</p>
<pre><code class="language-js"><span class="hljs-keyword">function</span> <span class="hljs-title function_">useInput</span>(<span class="hljs-params">initialState = <span class="hljs-string">&#x27;&#x27;</span></span>) {
  <span class="hljs-keyword">const</span> [state, setState] = <span class="hljs-title class_">React</span>.<span class="hljs-title function_">useState</span>(initialState)

  <span class="hljs-keyword">const</span> handlers = <span class="hljs-title class_">React</span>.<span class="hljs-title function_">useMemo</span>(
    <span class="hljs-function">() =&gt;</span> ({
      <span class="hljs-attr">handleInputChange</span>: <span class="hljs-function"><span class="hljs-params">e</span> =&gt;</span> {
        <span class="hljs-title function_">setState</span>(e.<span class="hljs-property">target</span>.<span class="hljs-property">value</span>)
      },
      <span class="hljs-attr">resetInput</span>: <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-title function_">setState</span>(initialState)
      },
    }),
    [initialState]
  )

  <span class="hljs-keyword">return</span> [state, handlers]
}
</code></pre>
<p>Même si cette fonction renvoie un tableau, je dois dire que j&#39;y vois ni plus ni
moins qu&#39;une structure avec les méthodes pour la manipuler, c&#39;est à dire quelque
chose qui ressemble sérieusement à… <a href="https://fr.wikipedia.org/wiki/Programmation_orient%C3%A9e_objet#Objet_(attributs_et_m%C3%A9thodes)">un objet au sens de la programmation
orientée
objet</a> !
Ce qui est plutôt ironique pour une approche qui se veut fonctionnelle 😇</p>
]]></description><link>https://damien.pobel.fr/post/custom-hooks-react</link><guid isPermaLink="true">https://damien.pobel.fr/post/custom-hooks-react</guid><category><![CDATA[veille]]></category><category><![CDATA[bonnes pratiques]]></category><category><![CDATA[react]]></category><category><![CDATA[javascript]]></category><category><![CDATA[code]]></category><category><![CDATA[ingénierie logicielle]]></category><pubDate>Mon, 15 Mar 2021 00:00:00 GMT</pubDate></item></channel></rss>