<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>qualité de code - Tag - Jordan Chapuy - Blog d'un développeur passionné ❤️</title><link>https://jordanchapuy.com/tags/qualit%C3%A9-de-code/</link><description>qualité de code - Tag - Jordan Chapuy - Blog d'un développeur passionné ❤️</description><generator>Hugo -- gohugo.io</generator><language>fr</language><lastBuildDate>Sat, 25 Feb 2023 16:44:00 +0100</lastBuildDate><atom:link href="https://jordanchapuy.com/tags/qualit%C3%A9-de-code/" rel="self" type="application/rss+xml"/><item><title>Des guides plus que des dogmes</title><link>https://jordanchapuy.com/posts/2023/02/des-guides-plus-que-des-dogmes/</link><pubDate>Sat, 25 Feb 2023 16:44:00 +0100</pubDate><author>Auteur</author><guid>https://jordanchapuy.com/posts/2023/02/des-guides-plus-que-des-dogmes/</guid><description><![CDATA[<p>On est entouré de principes, de lois, de modèles, de méthodes et d&rsquo;un tas d&rsquo;autres concepts. C&rsquo;est utile pour construire des choses complexes comme des logiciels - on a besoin d&rsquo;être aidé. Pour autant, je conseille de garder un minimum de recul et de questionnement face à ces <em>grands écrits</em> - ce ne sont pas des vérités absolues en toutes circonstances. Notre cerveau est plus que jamais important.</p>
<p>J&rsquo;aime considérer les principes (&amp; co) comme des <strong>guides</strong>. Ils me donnent des indications sur ce que je fais pour prendre de la hauteur. Ça m&rsquo;aide à réfléchir et à <strong>me questionner</strong>. Suis-je dans une bonne direction ? Pourquoi ce principe semble m&rsquo;alerter ici ? Qu&rsquo;est-ce que ça va m&rsquo;apporter ? De quoi ai-je besoin ? En me posant des questions, je m&rsquo;assure de <strong>prendre en compte mon contexte</strong> et de m&rsquo;y adapter. Je cherche aussi à bien comprendre le principe, pour qu&rsquo;il me guide au mieux. Peut-être que ça ne fait pas sens de l&rsquo;appliquer ici.</p>
<p>Un exemple avec le principe <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself" target="_blank" rel="noopener noreffer">DRY</a> (Don&rsquo;t Repeat Yourself). Je viens d&rsquo;écrire du code qui ressemble à un autre morceau de code ailleurs dans le projet. Le voyant DRY s&rsquo;allume et me dit d&rsquo;éviter la duplication. En prenant du recul, je peux me demander si c&rsquo;est réellement de la duplication. Est-ce qu&rsquo;ils sont dans le même domaine métier ? Est-ce qu&rsquo;ils ont les mêmes raisons de changer ? À quel point est-ce identique ? Ou même, est-ce trop tôt ? Même si le principe peut m&rsquo;indiquer un comportement à adopter, je prends d&rsquo;abord soin de réfléchir et d&rsquo;analyser mon contexte.</p>
<p>À l&rsquo;opposé, une approche plus <strong>dogmatique</strong> des principes. On arrête de réfléchir, on ne se pose pas (trop) de questions. On <strong>applique bêtement</strong> ce que le principe nous dit. En même temps il n&rsquo;y a pas à réfléchir, si le principe le dit, c&rsquo;est forcément vrai. Alors on le fait. On commence même à avoir une <strong>vision binaire</strong> : je respecte ou je ne respecte pas. D&rsquo;ailleurs, si je ne respecte pas, c&rsquo;est évidemment mal.</p>
<p>En reprenant l&rsquo;exemple du principe DRY, j&rsquo;aurais sûrement supprimé la duplication tout de suite. Sans questionnement. Deux bouts de code qui se ressemblent ? Oula, vite ! Qu&rsquo;on me supprime cette duplication ! Pourtant, il s&rsquo;agissait de règles métiers de deux domaines différents. Peu de temps après, j&rsquo;aurais cassé le comportement d&rsquo;un des deux domaines en modifiant ce bout de code non dupliqué. Espérons qu&rsquo;un test unitaire soit passé au rouge et que ce ne soit pas les retours alarmants de la prod qui auront mis en avant le problème.</p>
<p>Continuons de réfléchir, de creuser les principes en profondeur et de prendre en compte notre contexte. N&rsquo;appliquons pas bêtement et évitons les vérités absolues.</p>
]]></description></item><item><title>Permis de développer</title><link>https://jordanchapuy.com/posts/2022/01/permis-de-developper/</link><pubDate>Thu, 06 Jan 2022 15:30:00 +0100</pubDate><author>Auteur</author><guid>https://jordanchapuy.com/posts/2022/01/permis-de-developper/</guid><description><![CDATA[<p>Un développeur a-t-il besoin d&rsquo;une permission pour écrire des tests ? Pratiquer le Test-Driven Development ? Faire du <a href="https://jordanchapuy.com/posts/2021/06/le-refactoring/" rel="">refactoring</a> ? Travailler en Pair Programming ? Faut-il un permis à l&rsquo;image de la légendaire <em>licence to kill</em> de James Bond ?</p>
<p>Ma réponse est <strong>NON</strong> (sans surprise, comme la plupart des articles qui commencent avec une grande question fermée). Un développeur doit être autonome et décider de lui-même pour ce genre de pratiques. Il n&rsquo;a pas à demander l&rsquo;autorisation à un manager, ni un chef, ni un PO, ni un SM, ni même à un tech lead ou un autre développeur.</p>
<p>Encore moins se voir interdire (anecdote récente lors d&rsquo;un entretien technique, un développeur m&rsquo;a indiqué que son client lui interdisait d&rsquo;écrire des tests parce que ça prenait du temps). Au contraire, il faut promouvoir et pousser ces pratiques aux développeurs et aux équipes.</p>
<h1 id="ça-fait-partie-du-job">Ça fait partie du job</h1>
<p>L&rsquo;écriture de tests, le TDD, le Refactoring, le Pair Programming, et j&rsquo;en passe, ce sont des pratiques répandues dans l&rsquo;industrie. Elles sont reconnues et proviennent de mouvements comme le Software Craftsmanship, l&rsquo;eXtreme programming, ou le Domain Driven Design. Ce n&rsquo;est pas le n-ième <em>nouveau super framework</em> à la mode.</p>
<p>On parle ici de pratiques qui améliorent la qualité du code et du produit, qui facilite le changement, qui permettent de mieux collaborer, de mieux retranscrire le métier. Elles font partie intégrante du métier de développeur.</p>
<p>Un développeur n&rsquo;est pas un exécutant. Il n&rsquo;est pas là juste pour pisser du code. Il a un (grand) rôle à jouer pour concevoir un produit de qualité. Il existe de nombreux ouvrages sur ces pratiques et également sur la posture de développeur. Pour en citer un, <em>Sandro Mancuso</em> en parle très bien dans son livre <em>The Software Craftsman</em>.</p>
<h1 id="just-do-it">Just do it</h1>
<p>Je donnerais comme conseil aux développeurs de faire, de passer à l&rsquo;action, d&rsquo;utiliser ces pratiques. Sans attendre une permission officielle, sans aller chercher une approbation quelconque. Faites-le, tout simplement.</p>
<p>Il y a un proverbe qui dit <code>Il vaut mieux demander pardon que demander la permission</code>. Je l&rsquo;aime bien, et je trouve qu&rsquo;il a du sens dans cette situation. Vous êtes développeur et vous hésitez ? Lancez-vous, essayez, montrez par l&rsquo;exemple. Probablement, quelque chose de bon en sortira et on ne viendra pas vous taper sur les doigts. Ce n&rsquo;est pas parfait ? Vous deviendrez meilleur en continuant d&rsquo;essayer et de vous améliorer.</p>
<p>Rappelons que le développeur a l&rsquo;expertise. Il sait comment travailler, il connaît sa boîte à outils. Mon propos n&rsquo;est pas d&rsquo;enfermer le développeur dans sa vision - il doit rester ouvert, comme tout le monde - mais de lui faire confiance et de lui donner de l&rsquo;autonomie.</p>
<p>Ce qui n&rsquo;empêche pas de le challenger. Et quand on touche à ses limites, à sa zone où il ne maîtrise pas, on se penchera plutôt sur comment former, comment apprendre, comment expérimenter, plutôt que d&rsquo;empêcher.</p>
<h1 id="former-les-équipes">Former les équipes</h1>
<p>Ça fait partie du job, d&rsquo;utiliser ces pratiques, ça fait également partie du job de se former. Elles ne tomberont pas soudainement du ciel. Avis aux développeurs qui doivent faire l&rsquo;effort autant qu&rsquo;aux managers qui doivent investir ;)</p>
<p>On se forme, on forme les équipes, on expérimente, on s&rsquo;améliore en continue. Le retour sur l&rsquo;investissement est positif, on ira plus vite, on délivrera mieux. On veut démarrer un cercle vertueux (on apprend, on améliore le code, on change plus facilement, on livre plus vite, on satisfait davantage l&rsquo;utilisateur) plutôt que vicieux (on empêche, on n&rsquo;apprend pas, le code se détériore, les évolutions deviennent difficiles, on cumule des problèmes, on met du temps à livrer à l&rsquo;utilisateur).</p>
<p>Il y a un tas de moyens pour apprendre. Quelques idées : inviter des personnes à faire un BBL, l&rsquo;intervention de coachs, faire des katas seul ou en groupe, du mob-programming sur le projet, assister à des conférences, lire des livres, etc.</p>
<h1 id="casser-les-idées-reçues">Casser les idées reçues</h1>
<p>Et s&rsquo;il y a du blocage, des interdictions, des permissions à demander pour utiliser ces pratiques ? J&rsquo;essaierais de comprendre pourquoi, de challenger, de rappeler que ça fait partie du job, et de casser certaines idées reçues.</p>
<p>En rappelant la vision, la philosophie de certaines pratiques. Le <a href="https://jordanchapuy.com/posts/2021/06/le-refactoring/" rel="">refactoring</a>, ce n&rsquo;est pas un chantier de 3 mois en tunnel. Ce sont des petites étapes, ce sont des améliorations que l&rsquo;on fait au quotidien, qui facilitent le changement, qui améliorent la qualité.</p>
<p><a href="https://jordanchapuy.com/posts/2021/12/ce-nest-pas-plus-long-de-pratiquer-le-tdd/" rel="">L&rsquo;écriture de tests et le TDD, ce n&rsquo;est pas plus long</a>. C&rsquo;est une aide pour le développeur, un guide pour bien retranscrire le métier, le comportement. On obtient en plus de la sérénité quand il faut effectuer des changements. On entre dans des situations où l&rsquo;on ira plus vite.</p>
<p>Le Pair-Programming, ce n&rsquo;est pas juste deux ressources humaines qui se mettent sur un poste pour travailler sur un seul problème à la fois. C&rsquo;est une collaboration poussée, c&rsquo;est un feedback rapide, c&rsquo;est une transmission de connaissances, d&rsquo;informations, c&rsquo;est de l&rsquo;amélioration en continue. Là aussi on entre dans des situations où l&rsquo;on ira plus vite.</p>
<p>On améliore la qualité, on gagne du temps, on gagne de l&rsquo;argent. Trois arguments que l&rsquo;on peut aligner en fonction de l&rsquo;interlocuteur. On pourrait citer en touche finale  <em>Accelerate</em>, un livre qui montre, via une étude sur plusieurs années incluant de très nombreuses entreprises, qu&rsquo;il y a une corrélation entre la performance technique et la performance business.</p>
]]></description></item><item><title>Ce n'est pas plus long de pratiquer le TDD</title><link>https://jordanchapuy.com/posts/2021/12/ce-nest-pas-plus-long-de-pratiquer-le-tdd/</link><pubDate>Sat, 11 Dec 2021 14:35:00 +0100</pubDate><author>Auteur</author><guid>https://jordanchapuy.com/posts/2021/12/ce-nest-pas-plus-long-de-pratiquer-le-tdd/</guid><description><![CDATA[<p>J&rsquo;entends et lis parfois que ça prend du temps d&rsquo;écrire des tests unitaires et de pratiquer le Test-Driven Development. Que c&rsquo;est bien plus long que de ne pas en faire. Je ne suis pas en phase.</p>
<p>J&rsquo;ai la conviction que ça ne prend pas forcément plus de temps de travailler en TDD. On est sensiblement sur la même longueur, parfois même plus rapide parce que ça nous guide. On est très loin du laïus <em>&ldquo;c&rsquo;est une perte de temps&rdquo;</em>, surtout lorsque l&rsquo;on regarde sur différents horizons de temps.</p>
<p>Il n&rsquo;y a d&rsquo;ailleurs pas que le temps qui entre en jeu, d&rsquo;autres bénéfices gravitent autour de l&rsquo;écriture des tests et de la pratique du TDD. Pour étayer mes affirmations, j&rsquo;ai envie d&rsquo;en parler à travers plusieurs prismes.</p>
<h2 id="jai-une-mauvaise-utilisation-du-tdd">J&rsquo;ai une mauvaise utilisation du TDD</h2>
<p>Pour le premier prisme, je prends un développeur qui pratique le TDD mais qui l&rsquo;utilise mal, qui ne le maîtrise pas. Je commence par ce postulat parce que c&rsquo;est sûrement là qu&rsquo;il y a le plus de confusion et de mécompréhension. Les personnes qui ne maîtrisent pas l&rsquo;art de tester et du TDD se forgent un avis sur la base d&rsquo;une expérience incomplète.</p>
<p>Qu&rsquo;est-ce que c&rsquo;est, <em>ne pas maîtriser</em> ? Penser que ça se résume à <em>écrire un test en premier</em>, que c&rsquo;est purement de la <em>technique</em> (versus métier), ou que ça se limite à suivre le <em>Red-Green-Refactor</em>, par exemple.</p>
<p>En adoptant une mauvaise pratique, on va se mettre des bâtons dans les roues. On va vouloir tout mocker, on va tester l&rsquo;implémentation, on ne va pas faire de petites étapes, etc. Résultat, on va trouver ça plus long. On va peut-être préférer ne pas faire de TDD, finalement. C&rsquo;est plus long et il y a un tas de trucs chiants à faire, pourquoi s&rsquo;emmerder.</p>
<p>Dans ce contexte, la méthode est mal comprise et mal appliquée. C&rsquo;est probablement plus long de pratiquer le TDD, oui. Mais peut-on juger la méthode dans ces conditions ? J&rsquo;y répondrais par une autre question. Est-ce qu&rsquo;une voiture est lente parce qu&rsquo;on roule avec le frein à main ? Ou parce qu&rsquo;on ne sait pas comment passer les vitesses ? Non.</p>
<p>=&gt; Oui, une mauvaise application du TDD peut demander davantage de temps. Non, dans ce contexte, c&rsquo;est inexact de déduire qu&rsquo;une bonne pratique du TDD prend du temps.</p>
<h2 id="japprends-le-tdd">J&rsquo;apprends le TDD</h2>
<p>Dans ce second prisme, j&rsquo;introduis une nuance : un développeur qui s&rsquo;exerce à pratiquer le TDD mais qui ne le maîtrise pas encore parce qu&rsquo;il est en phase d&rsquo;apprentissage. La différence avec le premier prisme ? Il a conscience de la bonne pratique du TDD et il s&rsquo;améliore pour y arriver. Il ne va pas mal faire tout en supposant qu&rsquo;il maîtrise la méthode.</p>
<p>Disons les choses. Le TDD, c&rsquo;est difficile. Ça demande du temps pour le maîtriser. Ça demande de s&rsquo;entraîner, de répéter, de s&rsquo;améliorer. Mais pour autant, c&rsquo;est la phase d&rsquo;apprentissage qui requiert du temps. Ce n&rsquo;est pas l&rsquo;application de la méthode elle-même. Encore une fois, juge-t-on la vitesse d&rsquo;une voiture avec un pilote qui apprend à passer les vitesses ? Non.</p>
<p>Ok. Et durant cet apprentissage alors, à quel point ça prends du temps de faire du TDD ? Ça dépend. Ça dépend du contexte, ça dépend du niveau de compétence que l&rsquo;on a acquis à cet instant.</p>
<p>Il y a des situations où l&rsquo;on ne sera pas encore à l&rsquo;aise, on devra ralentir pour bien faire, on prendra davantage de temps sur le moment. À l&rsquo;inverse, il y a des situations où l&rsquo;on sera guidé par le TDD et où l&rsquo;on obtiendra plus rapidement un bon résultat. On va commencer à bénéficier des effets positifs (j&rsquo;en parlerais après).</p>
<p>=&gt; Oui, l&rsquo;apprentissage du TDD demande du temps. Non, on ne peut pas dire que la pratique elle-même, une fois maîtrisée, prend du temps.</p>
<h2 id="jécris-mes-tests-après">J&rsquo;écris mes tests après</h2>
<p>Je me mets maintenant dans le prisme d&rsquo;un développeur qui écrit ses tests après coup. Que se passe-t-il si je me mets à faire du TDD ? On pourrait se dire que l&rsquo;on va prendre davantage de temps, on écrit déjà des tests, pourquoi se compliquer la vie à s&rsquo;ajouter une méthode ?</p>
<p>Eh bien, dans ce contexte, pratiquer le TDD sera probablement plus efficace et plus rapide. Le TDD va guider l&rsquo;écriture de l&rsquo;implémentation. On obtiendra une meilleure conception, on avancera par petites étapes et on sera guidé par le comportement métier. Ce sera une aide pour écrire de meilleurs tests et un meilleur code.</p>
<p>De fait, on s&rsquo;évitera les pièges d&rsquo;écrire du code non-testable, d&rsquo;en faire trop, ou de ne pas correctement retranscrire le métier, comme on pourrait le faire en écrivant les tests a posteriori.</p>
<p>En écrivant les tests après, on subit l&rsquo;implémentation. Et plus on attend pour tester, plus on subit. Il y aura davantage de changements à effectuer, le coût va augmenter. Le refactoring sera d&rsquo;ailleurs difficile ; les tests ne sont pas écrits, on n&rsquo;a pas encore notre filet de sécurité en place.</p>
<p>=&gt; Non, ce n&rsquo;est pas plus long de pratiquer le TDD lorsque l&rsquo;on écrit déjà des tests a posteriori. C&rsquo;est un gain de temps, et en plus, un gain de qualité.</p>
<h2 id="je-ne-teste-pas">Je ne teste pas</h2>
<p>Je termine avec un dernier prisme qui n&rsquo;en ait pas moins intéressant : celui du développeur qui ne teste pas. Alors là, réflexe, on va se dire que c&rsquo;est bien plus long. Non seulement, il faut écrire du code supplémentaire (les tests), et en plus, il faut se coltiner une discipline stricte. On va perdre du temps, non ? Je propose de regarder sous deux horizons de temps.</p>
<h3 id="court-terme">Court terme</h3>
<p>À court terme, sur l&rsquo;instant, le TDD va nous guider. C&rsquo;est une de ses principales forces. Il nous guide pour concevoir le code de production, l&rsquo;implémentation. Il nous guide pour retranscrire le métier. Il nous offre une boucle de feedback extrêmement rapide pour créer et améliorer.</p>
<p>On prends le temps de bien faire et de réfléchir, mais pour autant, ce n&rsquo;est pas forcément plus long. Parce qu&rsquo;on se concentre sur l&rsquo;essentiel en progressant par petites étapes, parce qu&rsquo;on est guidé pour coder l&rsquo;implémentation, parce qu&rsquo;on a un feedback rapide contrairement aux tests manuels.</p>
<p>La pratique du TDD ne va pas seulement nous faire écrire des tests avant de coder, elle va nous aider à coder, à concevoir. Au final, on ralentit tout en gagnant du temps, pour mieux faire. On passe sensiblement le même temps à développer notre fonctionnalité.</p>
<p>Dans certains contextes, on est plus rapide, parce qu&rsquo;on se serait perdu en chemin sans le TDD, parce qu&rsquo;on aurait fait trop compliqué ou parce qu&rsquo;il y a beaucoup de logique. On perd vite du temps à explorer sans test et sans guide. Dans quelques autres contextes, ça peut être plus long de pratiquer le TDD, mais c&rsquo;est sans compter les effets obtenus à plus long terme.</p>
<h3 id="moyen-et-long-terme">Moyen et Long terme</h3>
<p>À moyen et long terme, on va obtenir de nouveaux bénéfices grâce à la pratique du TDD. Les tests vont couvrir notre code et vont faciliter le <a href="https://jordanchapuy.com/posts/2021/06/le-refactoring/" rel="">refactoring</a> et réduire les régressions. On va gagner du temps.</p>
<p>La facilité de faire du refactoring va aider à améliorer continuellement le système. On va le maintenir et le faire évoluer plus facilement. On va le changer facilement. On va gagner du temps.</p>
<p>On aura du code et des tests qui reflètent mieux le métier et les cas d&rsquo;utilisations. On va mieux comprendre notre système. On va mieux échanger avec les autres. On va gagner du temps.</p>
<hr>
<h1 id="bref">Bref</h1>
<p>Au final, en regardant à travers ces différents prismes, on peut observer que les situations où un développeur trouve que c&rsquo;est plus long de pratiquer le TDD est peut-être à décorréler de la méthode elle-même. Souvent parce qu&rsquo;elle n&rsquo;est pas encore maîtrisée.</p>
<p>Dès lors qu&rsquo;on a une bonne pratique du TDD, des bénéfices apparaissent immédiatement, à court terme. La force que le TDD propose pour guider et donner du feedback rapide est assez puissante pour être d&rsquo;une grande aide pour le développeur tout en ne faisant pas <em>perdre de temps</em>.</p>
<p>Ces effets s&rsquo;accentuent à plus long terme, et d&rsquo;autres viennent s&rsquo;ajouter. On y voit un cercle vertueux d&rsquo;amélioration continue. Ce n&rsquo;est plus juste une question de temps, on y gagne sur plusieurs niveaux.</p>
]]></description></item><item><title>Le Refactoring</title><link>https://jordanchapuy.com/posts/2021/06/le-refactoring/</link><pubDate>Thu, 10 Jun 2021 08:42:00 +0200</pubDate><author>Auteur</author><guid>https://jordanchapuy.com/posts/2021/06/le-refactoring/</guid><description><![CDATA[<p>La machine à café, c’est un peu un objet magique pour les développeurs. On peut y voir deux principales capacités. Elle provoque des résolutions de problèmes spontanées suite à des discussions proche de la machine. Et elle produit le café qui, une fois assimilé par le développeur, se transforme en d’innombrables lignes de code. Alors quand on possède un tel objet, on n’a pas envie de le casser. On voudra certainement l’améliorer, mais en le gardant fonctionnel. Tiens, ne commencerait-on pas à parler de refactoring ?</p>
<p>Avant d’entrer dans les détails, je vous propose de sortir un stylo et une feuille afin de vous poser la question suivante : <strong>qu’est-ce que le refactoring ?</strong> Faites couler l’encre, gravez votre définition dans les fibres du papier.</p>
<figure>
</figure>

<h2 id="définitions-et-fondamentaux">Définitions et fondamentaux</h2>
<p>Le refactoring demande de la <strong>discipline</strong> et de l’<strong>apprentissage</strong>. Il existe des méthodologies, des principes et de multiples techniques. <em>Ah bon, ce n’est pas juste tout refaire ?</em> Non. On voit trop souvent ces fameux « chantiers » qui durent des mois, effectués en silo, sans visibilité et qui ont un résultat peu satisfaisant. Ils auront souvent duré bien plus longtemps que prévu, ou comporteront des régressions, ou seront abandonnés avant la fin. J&rsquo;en ai vu et j&rsquo;en vois malheureusement encore. J&rsquo;en ai également fait, mais depuis, j&rsquo;ai appris et je continue d&rsquo;apprendre.</p>
<p>Aujourd’hui, j’ai envie de parler de ce qu’est le refactoring, de ses grands principes. Avant de se lancer dans ces grands chantiers, comprenons de quoi on parle. Je vais m’appuyer sur les définitions de Martin Fowler. Si vous ne le connaissez pas, c’est un des grands noms quand on parle de refactoring. Je vous recommande son site et ses livres.</p>
<blockquote>
<p>noun: a change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior.</p>
</blockquote>
<blockquote>
<p>verb: to restructure software by applying a series of refactorings without changing its observable behavior.</p>
</blockquote>
<p>Je vois plusieurs fondamentaux dans ces définitions. C’est bien plus que « tout ré-écrire » ou même que « ré-écrire pour améliorer » (déjà plus précis, mais encore trop simpliste).</p>
<p>Faire du refactoring, c’est <strong>conserver le même comportement</strong>. Ne pas casser l’existant. Si on change le comportement, ce n’est plus du refactoring. On sépare le refactoring des évolutions et corrections de bugs. Dans le cycle du TDD, il y a une étape dédiée pour le refactoring ; ce n’est pas pendant qu’on écrit le test ni pendant qu’on fait émerger une solution. Lorsque l’on fait du refactoring sur la machine à café, on veut qu’elle continue à faire du café lorsque l’on a terminé. On ne veut pas qu’elle fasse un thé, ni un tiramisu. Et on veut encore moins qu’elle soit en panne.</p>
<p>Faire du refactoring, c’est <strong>avancer par petites étapes</strong>. On enchaîne une série d’améliorations, on évite de vouloir tout changer d’un coup. Ce sont des petites étapes que l’on peut <strong>partager régulièrement</strong>. C’est à dire les rendre disponibles aux autres, les committer, les rapatrier sur la branche principale. Ainsi, on peut s’arrêter à tout moment. Si soudainement on doit faire quelque chose de plus prioritaire ou partir en vacances, <strong>le projet est toujours dans un bon état</strong> et nos petites améliorations seront en plus intégrées. Dans l’hypothèse où les développeurs tirent leurs super-pouvoirs du café, si pendant un mois la machine est en chantier, donc inutilisable, ça posera des problèmes.</p>
<p>Faire du refactoring dans le but d’<strong>améliorer la compréhension et de diminuer le coût du changement</strong>. On peut vouloir rendre le code plus lisible, avec une intention plus claire, un métier mieux projeté. L’amélioration continue est importante. On peut vouloir également rendre le changement plus facile, donc moins couteux. Ré-écrire uniquement pour le plaisir du développeur d’intégrer le dernier framework X-2000 est peut-être une moins bonne raison. Notre machine à café a besoin d’un refactoring, car elle ne prend en charge qu’un seul type de dosette très précis.</p>
<p>Je pense qu’il est important de prendre conscience de ces fondamentaux et d’être dans cet état d’esprit afin d’améliorer son approche du refactoring. Bien sûr, il reste du chemin ensuite, ce n’est que le début du voyage, mais c’est une étape essentielle.</p>
<h2 id="aller-plus-loin">Aller plus loin</h2>
<p>Pour continuer d’approfondir le refactoring, on peut regarder du côté de la détection de code smells, de l’apprentissage des techniques de refactoring, de méthodes pour structurer un refactoring, ou encore de l’art de tester du code legacy (casser des dépendances, introduire des tests, …). Oui, la liste est grande, ce n&rsquo;est pas si simple. Et oui, il ne faut pas oublier les tests pour s&rsquo;ajouter un filet de sécurité.</p>
<p>Quelques ressources autour du refactoring :</p>
<ul>
<li>Martin Fowler. Une figure incontournable avec son le site <a href="https://refactoring.com/" target="_blank" rel="noopener noreffer">refactoring.com</a> et son livre <em>Refactoring Improving the Design of Existing Code</em>.</li>
<li>Michael Feathers. Une seconde figure incontournable, plus axée sur le code legacy avec son livre <em>Working Effectively with Legacy Code</em>.</li>
<li>Le site <a href="https://refactoring.guru/" target="_blank" rel="noopener noreffer">refactoring.guru</a> listant techniques de refactoring et code smells.</li>
<li>Divers katas pour s&rsquo;exercer comme le Gilded Rose, Tennis Game, Trivia, etc.</li>
<li>Ici même, avec le temps, via le tag <a href="https://jordanchapuy.com/tags/refactoring/" rel="">#refactoring</a>.</li>
</ul>
<h2 id="seconde-édition">Seconde édition</h2>
<p>Vous avez toujours le bout de papier avec votre première définition ? Reprenez-le. Je vous propose d’écrire une nouvelle fois ce que représente le refactoring pour vous pour terminer. Au dos de la feuille ou sans relire les définitions a minima.</p>
<p>Amusez-vous à comparer les trois définitions maintenant. Et si le cœur vous en dit, partagez-moi vos écrits :)</p>
]]></description></item><item><title>Et si on arrêtait les revues de code ?</title><link>https://jordanchapuy.com/posts/2021/02/et-si-on-arretait-les-revues-de-code/</link><pubDate>Mon, 22 Feb 2021 09:05:00 +0100</pubDate><author>Auteur</author><guid>https://jordanchapuy.com/posts/2021/02/et-si-on-arretait-les-revues-de-code/</guid><description><![CDATA[<p>Qu-Quoi ?! On arrêterait de contrôler la qualité ? « Hérétique, au bûcher ! » s’exclameraient certains paladins de la relecture de code. Et si, au lieu de contrôler la qualité en fin de chaîne, on co-créait cette qualité tout au long de la conception ?</p>
<p>Oui, je fais allusion au pair programming. Mais avant d’en parler, plongeons-nous dans une histoire. Une histoire que j’ai déjà vécu et que vous avez probablement aussi vécu. Je dirais même que beaucoup ont vécu, d’un côté de la revue ou de l’autre.</p>
<div class="details admonition quote open">
        <div class="details-summary admonition-title">
            <i class="icon fas fa-quote-right fa-fw"></i>Une revue de code<i class="details-icon fas fa-angle-right fa-fw"></i>
        </div>
        <div class="details-content">
            <div class="admonition-content"><p>Perceval est un des développeurs de l’équipe. Aujourd’hui, il commence une nouvelle tâche. Perceval veut bien faire. Il prend le temps de concevoir cette nouvelle fonctionnalité et de penser son code. Après 4-5 jours, il termine et ouvre une Merge Request. Il passe ensuite à autre chose, une correction de bug.</p>
<p>Le lendemain, Arthur commence la revue de code sur GitLab. Aïe. Ce n’est pas du tout ce à quoi il pensait. Il avait une tout autre vision du design de code. Et il le fait savoir à travers de multiples commentaires écrits. Refaire ci, refaire ça, structurer de cette manière-là, utiliser ces composants, mettre ça ici, etc. Tout un chantier.</p>
<p>Deux heures après, Perceval lit les commentaires. Il met en pause sa recherche d’un correctif et retourne sur la branche de sa première tâche. Il retravaille ses modifications afin de prendre en compte les retours d’Arthur. Ce travail occupera une grande partie de l’après-midi de Perceval. Commit, push, merge request assignée à Arthur. Retour sur le correctif.</p>
<p>En fin de journée, Arthur prend le temps de regarder les changements effectués. Il repense à ce qu’il avait dit à Perceval, et globalement, ce qu’il voit lui plaît bien. Juste quelques petits retours sur des nommages à améliorer et une fonction qui pourrait être créée afin d’éviter la duplication.</p>
<p>Des changements rapides, que Perceval effectuera le lendemain matin. Il y a cependant quelques conflits à résoudre, la branche a pris du retard. S’en suivra une validation de la part d’Arthur une heure après. Tout est validé, la story est terminée et le déjeuner mérité.</p>
</div>
        </div>
    </div>
<p>Cette histoire vous est-elle familière ? À quel point la vivez-vous ? Vous en êtes-vous déjà rendu compte ? La review est-elle douloureuse pour vous ou votre équipe ? Prenez le temps de vous poser des questions.</p>
<h2 id="ce-que-lon-peut-observer">Ce que l&rsquo;on peut observer</h2>
<p>Une grande partie du travail est refait. Perceval ayant créé quelque chose qui ne convient pas, du code est jeté. C’est du temps en partie perdu. De plus, la durée de la tâche s’allonge : qui dit suppression dit ré-écriture. Perceval a dû reprendre son travail avec une autre manière de faire. Les chances d&rsquo;avoir des conflits à résoudre pour merge augmentent, leurs complexités aussi.</p>
<p>Perceval a passé beaucoup de temps tout seul et n’a eu <strong>le premier feedback que très tardivement</strong> - une fois qu’il pensait avoir terminé, ce qui augmente le coût de re-travail. Arthur a également mis du temps à faire la revue car il y avait beaucoup de code à lire.</p>
<p>Les discussions sont à l’écrit, et en décalées. La revue est ouverte, plus tard des commentaires sont ajoutés, plus tard des retours sont effectués, et ainsi de suite. Le temps d’attente peut être long. La tâche met plus de temps à être terminée.</p>
<p>À chaque aller-retour, il y a un <strong>changement de contexte</strong>. La personne (auteur ou lecteur) doit arrêter ce qu’elle était en train de faire, doit se plonger dans la revue, puis se remettre sur son ancienne tâche avec la nécessité de se re-plonger dans ce qu’elle faisait. Ce temps n’est pas négligeable.</p>
<p>Et que ressent Perceval ? Quand il apprend qu’il doit tout refaire. Quand il lit les commentaires d’Arthur, sujet à interprétation, pouvant être pris personnellement.</p>
<h2 id="ce-que-lon-peut-faire">Ce que l&rsquo;on peut faire</h2>
<p>On communique davantage. On donne du feedback tôt et régulièrement. On collabore. Perceval et Arthur peuvent échanger dès le début de la tâche, pendant, et même à la fin lors de la revue. Ils peuvent la faire ensemble sur le même poste. Et soyons fous, ils peuvent se mettre au pair programming. Ça y est, on y vient.</p>
<div class="details admonition quote open">
        <div class="details-summary admonition-title">
            <i class="icon fas fa-quote-right fa-fw"></i>Du pair programming<i class="details-icon fas fa-angle-right fa-fw"></i>
        </div>
        <div class="details-content">
            <div class="admonition-content"><p>Ce matin, Perceval et Arthur s’assoient côte à côte afin de développer une nouvelle fonctionnalité ensemble. À tour de rôle, ils écrivent du code et échangent tout le long. Ils challengent le code et la qualité. Arthur et Perceval apprennent l’un de l’autre, se transmettent des connaissances, des bonnes pratiques.</p>
<p>À la fin de la journée, la fonctionnalité est terminée. Le design du code et la qualité sont encore meilleurs que ce qu’ils pensaient faire chacun dans leur tête avant de commencer. Ils rapatrient la fonctionnalité sur la branche principale. Fin.</p>
</div>
        </div>
    </div>
<p>Qu’en pensez-vous ? Remémorez-vous la première histoire.</p>
<p>En travaillant de paire, <strong>le feedback est immédiat et continu</strong>. Arthur accompagne en temps réel Perceval. Il n’y a plus d’aller-retour ou d’échanges à l’écrit, ni d’attente, ni de changement de contexte. Il n’y a même plus besoin de faire de code review, chaque retour a été pris en compte sur le moment et le résultat est de meilleure qualité. Avec le pair programming, la revue de code est poussée à son extrême : le binôme en fait tout le long, à chaque instant.</p>
<p><strong>Les échanges sont plus humains et plus riches</strong>. Chacun apprend, partage. Chacun challenge et améliore le code écrit. Chacun comprend le code et la fonctionnalité - la propriété est collective. Les bénéfices du pair programming sont multiples. Alors pourquoi attendre ? Une heure, une journée, une fonctionnalité de bout-en-bout, … Lancez-vous. À votre rythme, mais lancez-vous.</p>
<p>Testez, observez ce qui change, prenez du feedback. Apprenez à faire du pair programming, acceptez au début de ne pas savoir faire, améliorez-vous. Et appréciez :)</p>
<hr>
<p><em>Post-scriptum du prêtre : toute ressemblance avec des personnes existantes ou ayant existé dans la légende arthurienne ne saurait être que fortuite. Ou pas. Je suis en manque de film Kaamelott.</em></p>
]]></description></item><item><title>Clean Architecture - Et si on passait à côté ?</title><link>https://jordanchapuy.com/posts/2020/11/clean-architecture-et-si-on-passait-a-cote/</link><pubDate>Tue, 17 Nov 2020 09:17:00 +0100</pubDate><author>Auteur</author><guid>https://jordanchapuy.com/posts/2020/11/clean-architecture-et-si-on-passait-a-cote/</guid><description><![CDATA[<p>Je vois de plus en plus la Clean Architecture comme le SCRUM. Quelque chose qui est souvent mal appliqué et mal compris. Quelque chose dont on oublie ou met de côté la philosophie, l&rsquo;essence même. Quelque chose qu&rsquo;on utilise parce que c&rsquo;est <em>à la mode</em>.</p>
<p>J&rsquo;observe un nombre grandissant de discussions autour de la Clean Architecture. C&rsquo;est davantage présent dans les projets, dans les souhaits, dans les échanges, dans les publications. Pourtant, je pense qu&rsquo;une (trop grande) partie des personnes passe à côté de concepts essentiels et ne se pose pas les bonnes questions. Malgré la bonne intention, ça peut être dangereux. J&rsquo;aimerais amorcer une prise de recul et ouvrir des questions.</p>
<h2 id="et-si-on-prenait-du-recul-">Et si on prenait du recul ?</h2>
<p>Je vois des discussions qui tournent seulement autour du pattern, du diagramme de classe. <em>&ldquo;Le Presenter fait ceci et cela. Il parle à celui-ci ou à celui-là.&rdquo;</em> Quand je demande ce qu&rsquo;est la Clean Architecture, on me répond souvent en me récitant un diagramme de classe. Pas un mot sur l&rsquo;abstraction, l&rsquo;entrée/sortie, l&rsquo;inversion de contrôle, &hellip; Et encore moins sur l&rsquo;isolation du métier.</p>
<p>J&rsquo;ai également assisté à des entretiens et des échanges avec des développeurs qui s&rsquo;acharnent avec des suites de questions pour savoir si <em>Machin</em> va plutôt dans le Router ou Interactor ou Presenter, si c&rsquo;est pas à <em>Bidule</em> de faire ça, et le rôle de <em>Truc</em> là-dedans, &hellip; Plutôt que de parler de l&rsquo;esprit de la Clean Architecture, ils ne parlent que des classes.</p>
<p>Certaines équipes utilisent la Clean Architecture comme cadre pour empêcher les développeurs d&rsquo;en sortir, en suivant un modèle à la lettre. Faire sans comprendre, sans réfléchir ne mène pas très loin. À quel point cela vaut le coup, de rendre des choses difficiles, d&rsquo;ajouter de la complexité pour empêcher des développeurs de sortir des rails ? Il y a peut-être d&rsquo;autres choix à explorer.</p>
<p>Dans tout ça, on oublie le <em>pourquoi</em>. On se concentre trop sur le <em>comment</em>. Pourquoi on l&rsquo;utilise ? <em>&ldquo;C&rsquo;est pour découper. C&rsquo;est pour pouvoir tester.&rdquo;</em> me dit-on souvent, sans trop détailler. Oui, mais pourquoi ça devient <em>&ldquo;plus découpé&rdquo;, &ldquo;plus testable&rdquo;</em> ? Quels concepts y a-t-il derrière ? Pourquoi fait-on cela ?</p>
<h2 id="et-si-on-se-recentrait-sur-le-métier-">Et si on se recentrait sur le métier ?</h2>
<p>Le métier est la partie la plus importante du produit. Sans métier, le produit n&rsquo;existerait pas, l&rsquo;équipe ne le fabriquerait pas. C&rsquo;est le cœur du programme et de l&rsquo;entreprise. Certaines règles vont au-delà du programme. La répartition des places dans un train par exemple. Cette règle peut être présente dans plusieurs programmes différents et existe même en dehors de tout ça, dans le monde réel.</p>
<p>Ces règles ne dépendent pas d&rsquo;un choix technique ou d&rsquo;un framework, elles ne sont pas affectées par un changement technique. On change de base de données ? Pas de problème. On n&rsquo;a pas encore choisi la base de données ? Pas de problème non plus. On change de framework ? Aucun souci.</p>
<p>Les règles devraient pouvoir changer aisément, le monde évolue constamment. On devrait les trouver et les comprendre facilement puisque c&rsquo;est le cœur du programme. C&rsquo;est pour toutes ces raisons qu&rsquo;il est important d&rsquo;apporter une grande attention sur cette brique. De la protéger de l&rsquo;extérieur. De la rendre compréhensible, lisible. De la tester.</p>
<p>Le schéma de Clean Architecture représenté par <a href="https://blog.cleancoder.com/uncle-bob/images/2012-08-13-the-clean-architecture/CleanArchitecture.jpg" target="_blank" rel="noopener noreffer">les 4 cercles</a> va d&rsquo;ailleurs dans ce sens. On retrouve les règles métiers et les règles applicatives au centre. Et uniquement ça. Pas de framework, pas de base de données, pas d&rsquo;interface graphique. Les frontières protègent les cercles à l&rsquo;intérieur de l&rsquo;extérieur. C&rsquo;est aussi l&rsquo;esprit de l&rsquo;architecture hexagonale et du DDD (Domain-Driven Design).</p>
<p>Le métier est au centre parce qu&rsquo;il est très important. Parce qu&rsquo;on veut le protéger. Parce qu&rsquo;on veut en prendre soin. Le reste, c&rsquo;est du détail. Du détail d&rsquo;implémentation.</p>
<h2 id="et-si-on-se-penchait-sur-les-principes-">Et si on se penchait sur les principes ?</h2>
<p>La programmation orientée-objet a son rôle à jouer, bien plus que ce que l&rsquo;on apprend souvent à l&rsquo;école (vous savez, ce fameux héritage pour classifier des animaux). Certains concepts qui gravitent autour de la POO se cachent derrière la Clean Architecture et sa séparation des couches.</p>
<p>L&rsquo;abstraction par exemple. Avec l&rsquo;abstraction, on cache les détails de l&rsquo;implémentation. On veut utiliser quelque chose sans savoir comment ça fonctionne derrière. On s&rsquo;enlève cette complexité. Je veux enregistrer un favori sans savoir de quelle manière il sera stocké.</p>
<p>L&rsquo;inversion de contrôle et l&rsquo;injection de dépendances sont un autre exemple. Ces concepts sont présents pour renforcer les frontières, pour protéger les cercles. On veut que les cercles discutent entre eux, mais sans qu&rsquo;un cercle intérieur n&rsquo;ait connaissance d&rsquo;un cercle extérieur. On découple. Un <em>Use Case</em> peut interagir avec une base de données sans que ce code ne soit à l&rsquo;intérieur du cercle, de son module. Cette brique est indépendante. Ainsi, les changements autour de la base de données ne vont pas affecter le <em>Use Case</em>. Et c&rsquo;est tout de même le <em>Use Case</em> qui est aux commandes, qui utilise la base de données.</p>
<p>On parle de modularité en programmation orientée objet. D&rsquo;autres concepts sont également là. Je vous conseille de prendre le temps de les découvrir et de les comprendre. De voir comment tout cela s&rsquo;articule, et d&rsquo;aller au-delà de la Clean Architecture. S&rsquo;ils ne vous intéressent pas, alors prenez encore plus de temps pour creuser le sujet. Mais n&rsquo;en restez pas à l&rsquo;application d&rsquo;un pattern.</p>
<h2 id="et-si-on-explorait-plus-loin-">Et si on explorait plus loin ?</h2>
<p>La Clean Architecture apporte de bonnes choses, mais ce n&rsquo;est pas une <em>silver bullet</em> pour autant. La solution miracle n&rsquo;existe pas. C&rsquo;est une solution parmi d&rsquo;autres. Il faut la comprendre, savoir ses forces et faiblesses, connaître ses principes, l&rsquo;approfondir.</p>
<p>Il faut également explorer ce qu&rsquo;il y a autour. L&rsquo;architecture hexagonale est une approche similaire par exemple. Elle accorde beaucoup d&rsquo;importance au métier, le place au centre et le protège avec un système de <em>ports</em> et d&rsquo;<em>adapters</em>. Une approche simple qui se marie très bien avec le Domain-Driven Design (un tas de choses à voir là-dedans, je recommande pleinement de s&rsquo;y plonger). Le <em>Functionnal Core, Imperative Shell</em> me semble être un autre moyen intéressant.</p>
<p>Et il faut garder en tête les différents principes de programmation. Ils sont toujours là, peu importe le choix de l&rsquo;architecture. Ils vous accompagneront pendant longtemps.</p>
<p>Cherchez à comprendre et approfondissez, n&rsquo;appliquez pas sans réfléchir. Soyez ouvert et explorateur, ne restez pas enfermé dans une vision unique. Et appréciez :)</p>
]]></description></item><item><title>FIRST : 5 principes pour guider l’écriture des tests unitaires</title><link>https://jordanchapuy.com/posts/2020/04/first-5-principes-pour-guider-l-ecriture-des-tests-unitaires/</link><pubDate>Mon, 20 Apr 2020 09:00:00 +0200</pubDate><author>Auteur</author><guid>https://jordanchapuy.com/posts/2020/04/first-5-principes-pour-guider-l-ecriture-des-tests-unitaires/</guid><description><![CDATA[<p>Écrire du code propre est essentiel, et écrire des tests propres l’est tout autant, si ce n’est plus. Design émergent, aide pour retranscrire le métier, documentation, maintenabilité et évolution du code, les tests jouent de multiples rôles au sein d’un projet. C’est pourquoi il est important d’avoir des tests de qualité.</p>
<p>Dans cet article, je vous propose d’explorer 5 principes qui pourront vous guider et vous challenger pour l’écriture de vos tests unitaires. Ces principes sont connus sous l’acronyme FIRST, signifiant avoir des tests :</p>
<ul>
<li>Fast 🚅</li>
<li>Independent 📦</li>
<li>Repeatable ♻️</li>
<li>Self-validating ✅</li>
<li>Timely ⏱</li>
</ul>
<p>En s’inspirant de ces bonnes pratiques, la qualité de vos tests s’améliorera et la qualité du projet et du code de production suivra. Pour mieux comprendre ces principes, faisons le tour de chacun d’eux en explorant leurs raisons d’être, les possibles problèmes en cause et des pistes de solutions.</p>
<figure>
</figure>

<hr>
<h1 id="f--fast-">F : Fast 🚅</h1>
<p>Exécuter un test doit être rapide, et surtout, lancer l’ensemble des tests doit être rapide. Cela inclut le temps des <em>setup</em> et <em>teardown</em>, et même de la compilation. Un test unitaire rapide mais avec une longue compilation ou un long setup est un test long. <strong>Si vous hésitez pour lancer vos tests après une modification, c’est que vos tests sont probablement trop longs</strong>.</p>
<p>Lorsque les tests sont longs, les workflow de développement et de déploiement sont ralentis. Par ailleurs, un des bénéfices des tests unitaires est d’obtenir un feedback rapide. Pour conserver cet aspect, il faut que les tests soient rapides.</p>
<p>C’est encore plus important lorsque vous utilisez un outil qui exécute automatiquement les tests unitaires impactés par vos modifications. C’est le cas en C# par exemple, avec Visual Studio et le <a href="https://docs.microsoft.com/fr-fr/visualstudio/test/live-unit-testing?view=vs-2019" target="_blank" rel="noopener noreffer">Live Unit Testing</a>.</p>
<p>Mais alors, qu’est-ce qu’un test long ? Prenons 150ms. Ça n’a l’air de rien, mais si chaque test prend 150ms, le cumul peut devenir bien plus long. Sur un projet ayant 2000 tests, et cela peut vite augmenter si l’équipe en ajoute régulièrement, on arrive à un total de 5 minutes ! Cumulé sur une journée, c’est énorme et c’est sans compter le temps de compilation ou de setup.</p>
<p>Un temps aussi grand va créer un point de douleur qui va démotiver le développeur, ce qui aura pour conséquence de diminuer la fréquence à laquelle il lance les tests. Dans le pire des cas, il pourrait même ne plus du tout lancer les tests.</p>
<p>Pour avoir un feedback rapide, il est nécessaire de lancer très souvent les tests pendant que l’on développe. En perdant le feedback rapide, on perd aussi du temps. On obtient bien plus tard l’information que quelque chose a cassé. De nombreuses modifications ont pu être ajoutées et il faut identifier laquelle est responsable de l’erreur.</p>
<h2 id="causes">Causes</h2>
<p>Les dépendances lourdes comme les accès à une base de données, les appels réseaux, ou les lectures de fichiers sont souvent les responsables d’un test long. Ces opérations durent des centaines de millisecondes, voire plusieurs secondes.</p>
<p>Parfois, les traitements asynchrones ralentissent les tests par le traitement lourd qu’ils peuvent faire, et possiblement aussi par la manière dont les tests gèrent l’asynchronisme (le test étant bloqué tant qu’une réponse n’est pas arrivée). Le multithreading peut poser le même problème.</p>
<h2 id="solutions">Solutions</h2>
<p>L’injection de dépendance, ou le principe d’inversion de contrôle, est un moyen efficace de s’abstraire des dépendances. Les implémentations réelles sont remplacées par des simulacres, comme des <a href="https://martinfowler.com/bliki/TestDouble.html" target="_blank" rel="noopener noreffer">Test Double</a>, qui permettent de simuler des comportements.</p>
<p>En créant une classe qui agira à la place d’un service effectuant une requête HTTP, par exemple, on obtient la flexibilité d’avoir la valeur que l’on souhaite immédiatement. Retourner des objets prédéfinis dans une fonction est une instruction instantanée contrairement à un appel réseau.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-swift" data-lang="swift"><span class="line"><span class="cl"><span class="kd">class</span> <span class="nc">TimeoutArticlesProvider</span><span class="p">:</span> <span class="n">ArticlesProvider</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">    <span class="kd">func</span> <span class="nf">fetchAllArticles</span><span class="p">(</span><span class="n">completion</span><span class="p">:</span> <span class="p">((</span><span class="n">Result</span><span class="p">&lt;</span><span class="nb">String</span><span class="p">,</span> <span class="n">ApiError</span><span class="p">&gt;)</span> <span class="p">-&gt;</span> <span class="nb">Void</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">completion</span><span class="p">(.</span><span class="n">failure</span><span class="p">(.</span><span class="n">timeout</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><hr>
<h1 id="i--independent-">I : Independent 📦</h1>
<p>Un test ne doit pas dépendre d’un autre test. Le résultat d’un test ne doit pas non plus affecter un autre test. Cela peut causer des faux positifs ou cacher un problème. On perdrait du temps à parcourir plusieurs tests pour découvrir l’origine d’une erreur.</p>
<p>On devrait pouvoir lancer les tests dans n’importe quel ordre. De même, on devrait pouvoir lancer n’importe quel sous-ensemble de tests : un seul, une suite de plusieurs tests, ou tous. Si ce n’est pas le cas, c’est une indication que certains tests dépendent les uns des autres.</p>
<p>Tendre vers des tests indépendants permet de focaliser chaque test sur un comportement précis, ce qui donne davantage de sens au mot <em>unitaire</em>. <strong>Un test ne devrait avoir qu’une seule raison d’échouer</strong>. Cela permet d’identifier rapidement la cause d’une erreur, on comprend tout de suite pourquoi le test a échoué. On évite ainsi une longue session de debug.</p>
<p>On veut donc se rendre indépendant d&rsquo;une base de données par exemple, pour éviter que l&rsquo;écriture dans un test A affecte le résultat d&rsquo;un test B. Ce peut être la même chose pour des singletons, des fichiers. Eventuellement, on va vouloir devenir indépendant de choses lourdes comme les appels réseaux, notamment pour respecter les principes <em>Fast</em> et <em>Repeatable</em>.</p>
<p>Attention à ne pas tomber dans l&rsquo;extrême. On ne veut pas que le SUT (System Under Test) soit isolé de tout. Non. On veut seulement rendre le test indépendant. Le SUT peut être une classe comme un ensemble de classes, un module. Tout mocker posera des problèmes et rendra le test fragile.</p>
<h2 id="causes-1">Causes</h2>
<p>Compter sur un enchaînement de plusieurs tests afin d’effectuer des actions prérequises à l’exécution d’un autre test va créer un lien de dépendance. De même que partager un état avec d’autres tests. On peut par exemple retrouver ces états dans des propriétés de la classe de test, dans des singletons, dans des bases de données, dans la lecture et l&rsquo;écriture de fichiers&hellip; Bref, tout ce qui est partagé.</p>
<h2 id="solutions-1">Solutions</h2>
<p>Ici aussi l&rsquo;injection de dépendance aidera à remplacer les dépendances gênantes pour le test. A celà, on peut ajouter le modèle <strong>Arrange-Act-Assert</strong> afin de structurer l’écriture d’un test en trois grandes parties en plus d’apporter de la rigueur et de la cohérence entre les tests.</p>
<ul>
<li><em>Arrange</em> : on prépare toutes les données requises pour le test, ainsi que l’état dans lequel le test doit se trouver. On s’abstrait des autres tests et de l’environnement, ainsi que des dépendances en créant les <a href="https://martinfowler.com/bliki/TestDouble.html" target="_blank" rel="noopener noreffer">Test Double</a> nécessaires.</li>
<li><em>Act</em> : la méthode testée est appelée. Les données requises ont été initialisées dans l’étape précédente, et les dépendances injectées.</li>
<li><em>Assert</em> : on vérifie que le résultat est bien celui qu’on attend grâce aux différentes méthodes <em>Assert</em> du framework de test. Un test doit tendre à n’avoir qu’un seul assert pour n’avoir qu’une seule raison d’échouer. Dans certains cas, on peut avoir plusieurs assert lorsqu’ils se regroupent sous une même logique.</li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-swift" data-lang="swift"><span class="line"><span class="cl"><span class="kd">class</span> <span class="nc">HelloServiceTests</span><span class="p">:</span> <span class="n">XCTestCase</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="kd">func</span> <span class="nf">testMakeMessage</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// Arrange</span>
</span></span><span class="line"><span class="cl">        <span class="kd">let</span> <span class="nv">now</span> <span class="p">=</span> <span class="mi">1587301244</span>
</span></span><span class="line"><span class="cl">        <span class="kd">let</span> <span class="nv">dateProvider</span> <span class="p">=</span> <span class="n">FakeDateProvider</span><span class="p">(</span><span class="n">now</span><span class="p">:</span> <span class="n">now</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="kd">let</span> <span class="nv">service</span> <span class="p">=</span> <span class="n">HelloService</span><span class="p">(</span><span class="n">dateProvider</span><span class="p">:</span> <span class="n">dateProvider</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="c1">// Act</span>
</span></span><span class="line"><span class="cl">        <span class="kd">let</span> <span class="nv">message</span> <span class="p">=</span> <span class="n">service</span><span class="p">.</span><span class="n">makeMessage</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="c1">// Assert</span>
</span></span><span class="line"><span class="cl">        <span class="n">XCTAssertEqual</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="s">&#34;1587301244 - Hello.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Un autre moyen de donner de l’indépendance aux tests est d’utiliser les méthodes de <em>setup</em> et de <em>teardown</em>. Ces méthodes sont respectivement appelées avant et après l’exécution de chaque test. Le teardown est très utile pour effectuer un nettoyage après chaque test, par exemple.</p>
<p>Le nommage des tests a son importance et peut aider à rendre des tests indépendants. Chercher à mettre en valeur l’intention du test à travers son nom force à tester un comportement plus précis. Et par la même occasion, cela facilite la compréhension pour déterminer pourquoi le test a échoué.</p>
<p>Certains frameworks ou IDEs proposent d’exécuter les tests dans un ordre aléatoire. Activez cette option. Vous aurez rapidement une idée quels tests ont un problème, et cela vous empêchera peut-être d&rsquo;ajouter un nouveau test dépendant.</p>
<hr>
<h1 id="r--repeatable-">R : Repeatable ♻️</h1>
<p>Un test doit toujours produire le même résultat. Toujours. Peu importe le nombre de fois où il est exécuté, la date ou le lieu. Si un test ne réagit parfois pas de la même manière, on ne peut pas lui faire confiance.</p>
<p>Comment savoir si la raison d’un échec est “normale” ou réellement problématique ? À quel point les erreurs sont bien détectées ? <strong>En se posant sans cesse des questions sur les tests, on perd en sérénité</strong>, rendant alors les changements dans le code plus difficiles et plus hésitants.</p>
<p>Pour un état de départ donné et une action exécutée, on doit pouvoir prédire la réponse. Sans résultat déterministe, les sessions de debug seront plus compliquées lorsque des erreurs surviendront (et idéalement, on n&rsquo;a pas besoin de debugguer). Certains problèmes pourraient être difficiles, voire impossibles à reproduire à l’identique.</p>
<p>Un test doit éviter de dépendre de sources de données non-prévisibles. Des sources changeantes, pouvant être indisponibles, des états extérieurs ou des environnements sont des dépendances empêchant d’obtenir continuellement le même résultat.</p>
<h2 id="causes-2">Causes</h2>
<p>Les bases de données sont des sources de données changeantes. Elles pourraient être modifiées par d’autres tests ou d’autres lancements. Les APIs web peuvent également exposer des données différentes à chaque appel, en plus d’être potentiellement indisponible (serveur en maintenance) ou inaccessible (panne de réseau).</p>
<p>Tester du code utilisant ces types de dépendances donnera un résultat incertain. Les singletons, les configurations et les environnements peuvent aussi être responsables d’un test ayant une sortie non garantie. Plus souvent oubliés : l’utilisation des dates et des fonctions aléatoires.</p>
<h2 id="solutions-2">Solutions</h2>
<p>On veut toujours avoir le même résultat, donc on veut contrôler entièrement le test, donc on doit rendre contrôlable certaines dépendances. L’injection de dépendance permettra de s’abstraire des sources de données non-prévisibles en ayant le contrôle sur les réponses générées. Par exemple, on peut simuler une requête échouant suite à un timeout pour les besoins d’un test, et par ailleurs simuler un succès pour un autre test.</p>
<p>Cette même solution peut être utilisée pour gérer les dates et les fonctions aléatoires. Pour cela, on transforme l’accès à la date en le rendant indirect, via une interface, afin d’ajouter une abstraction qui permettra de remplacer la valeur réelle par un Test Double dans les tests.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-swift" data-lang="swift"><span class="line"><span class="cl"><span class="kd">protocol</span> <span class="nc">DateProvider</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kd">var</span> <span class="nv">now</span><span class="p">:</span> <span class="n">Date</span> <span class="p">{</span> <span class="kr">get</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">class</span> <span class="nc">DeviceDateProvider</span><span class="p">:</span> <span class="n">DateProvider</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kd">var</span> <span class="nv">now</span><span class="p">:</span> <span class="n">Date</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">Date</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">class</span> <span class="nc">HelloService</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="kd">private</span> <span class="kd">let</span> <span class="nv">dateProvider</span><span class="p">:</span> <span class="n">DateProvider</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="kd">init</span><span class="p">(</span><span class="n">dateProvider</span><span class="p">:</span> <span class="n">DateProvider</span> <span class="p">=</span> <span class="n">DeviceDateProvider</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kc">self</span><span class="p">.</span><span class="n">dateProvider</span> <span class="p">=</span> <span class="n">dateProvider</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="kd">func</span> <span class="nf">makeMessage</span><span class="p">()</span> <span class="p">-&gt;</span> <span class="nb">String</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kd">let</span> <span class="nv">now</span> <span class="p">=</span> <span class="nb">Int</span><span class="p">(</span><span class="n">dateProvider</span><span class="p">.</span><span class="n">now</span><span class="p">.</span><span class="n">timeIntervalSince1970</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="s">&#34;</span><span class="si">\(</span><span class="n">now</span><span class="si">)</span><span class="s"> - Hello.&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>En complément, le modèle <em>Arrange-Act-Assert</em> apporte la structure pour définir la valeur des Test Double et l’état initial. On peut aussi s’appuyer sur les méthodes de <em>teardown</em> pour faire un nettoyage après chaque test.</p>
<hr>
<h1 id="s--self-validating-">S : Self-validating ✅</h1>
<p>Chaque test doit être autonome pour déterminer si le résultat correspond aux attentes. <strong>Personne ne devrait intervenir.</strong> Sa sortie est simple : un test a réussi ou a échoué.</p>
<p>Il ne devrait pas y avoir besoin d’interprétation manuelle. Si on est amené à lire un fichier, à comparer des résultats, à chercher des informations, il y a un risque de faire une erreur humaine. C’est aussi plus long et rébarbatif, ce qui pourrait décourager les développeurs de lancer les tests.</p>
<p>Un test ne devrait pas non plus nécessiter d’action manuelle, ni avant le lancement, ni après. Il ne faut pas avoir à intervenir pour préparer un environnement ou nettoyer des artefacts, par exemple. Si un tel besoin est présent, il faut l’automatiser ou l’intégrer dans le test.</p>
<h2 id="solutions-3">Solutions</h2>
<p>Avec les outils actuels, les tests respectent globalement déjà ce principe. Il suffit d&rsquo;ajouter une assertion dans un test pour qu&rsquo;il puisse valider lui-même le résultat ; le framework et l&rsquo;outillage s&rsquo;occupe du reste. L’assertion la plus basique est une déclaration indiquant que quelque chose doit être vrai.</p>
<p>Les frameworks de tests proposent en général plusieurs méthodes d’assertion : <em>assert true</em>, <em>assert not null</em>, <em>assert equal</em>, <em>assert throw exception</em>, etc. Au moins l’une de ces instructions doit être présente dans un test.</p>
<p>L’interprétation du résultat des tests peut s’améliorer avec des solutions plus visuelles. Certains frameworks et IDE proposent des interfaces graphiques listant les tests et mettant en valeur les succès et les échecs.</p>
<p>En ce qui concerne l’automatisation pour éviter une intervention manuelle, là encore l’injection de dépendance et la structure <em>Arrange-Act-Assert</em> sont utiles. En préparant et simulant un environnement spécifique pour un test, par exemple.</p>
<hr>
<h1 id="t--timely-">T : Timely ⏱</h1>
<p>Un test doit être écrit au bon moment. Idéalement, <strong>le test est écrit juste avant le code de production qui fera réussir le test</strong>. Ce mode opératoire apporte de réels bénéfices et fait la différence. De cette manière, on avance par plus petits bouts et on se concentre sur l’essentiel. Les tests, déjà écrits, nous aident et nous guident. On voit émerger le design du code.</p>
<p>À l’opposé, écrire les tests après le code de production comporte des risques. L’ajout de tests a posteriori est plus long et plus difficile. Cela nécessite un travail supplémentaire : il faut souvent adapter le code de production qui n’est pas testable. Ce travail est parfois conséquent et coûteux. Plus on éloigne l’écriture des tests, plus ce risque sera grand.</p>
<p>Outre la difficulté, la motivation peut baisser lorsqu’il s’agit d’écrire des tests lorsque l’on a terminé. Un sentiment de culpabilité peut également naître en pensant au temps supplémentaire à passer pour ajouter des tests et adapter le code de production alors que tout est déjà prêt.</p>
<h2 id="solutions-4">Solutions</h2>
<p>Commencer par écrire un test fait partie de l&rsquo;approche Test-Driven Development (TDD). Le développement est guidé par les tests. On est guidé pour implémenter le comportement par petites étapes. Suivre cette pratique, c’est suivre un cycle précis : <em>RED, GREEN, REFACTOR</em>.</p>
<p>Pour faire simple, on écrit d’abord un test qui échoue ou ne compile pas : c’est <em>rouge</em>. On cherche ensuite à passer au <em>vert</em> en écrivant le minimum de code de production, en allant au plus simple. Puis on <em>refactorise</em>, on améliore le code de production et le code des tests. La boucle est bouclée, alors on recommence. On itère jusqu’à ce qu’on ait répondu au besoin et qu’on soit satisfait du code.</p>
]]></description></item><item><title>Fixing thousands of SwiftLint violations over time</title><link>https://jordanchapuy.com/posts/2019/11/fixing-thousands-of-swiftlint-violations-over-time/</link><pubDate>Mon, 18 Nov 2019 09:00:00 +0200</pubDate><author>Auteur</author><guid>https://jordanchapuy.com/posts/2019/11/fixing-thousands-of-swiftlint-violations-over-time/</guid><description><![CDATA[<p>What would happen if SwiftLint were added to a project with a lot of existing code? You could have many violations, and much more when SwiftLint is deeply configured.</p>
<p>Having too many warnings can be discouraging, and there is also a bigger problem: <strong>too many warnings kill the warning</strong>. If you start to write code before resolving SwiftLint issues, you may miss some new important problems. So, let’s see how you can handle that.</p>
<figure>
</figure>

<hr>
<h1 id="quarantine-strategy-">Quarantine strategy ☣️</h1>
<p>Most of the violations can be fixed without problem, but there are many. Then there are more complex issues. Some violations will need refactoring.</p>
<p>You will need time to handle every warning, and you have to take time. Do not go fast, do it well. As you may not fix everything at once, you will have to do it progressively. But how? How can we take time and live with so many warnings?</p>
<p>Our strategy will be to isolate <em>infected</em> files and exclude them, then to fix violations and files over time. This strategy also plans to visualize progress and prevent regressions.</p>
<h2 id="autocorrect-is-our-magic-wand">Autocorrect is our magic wand</h2>
<p>Before you start the quarantine, you can run the <code>swiftlint autocorrect</code> command. Only a handful of rules can be automatically corrected, but it is pretty efficient and it can save you a lot of time and effort.</p>
<p>Autocorrecting is the easiest part. It is automatic, and it is mainly dealing with spaces and indentations. Be sure to check changes after running the command.</p>
<h2 id="exclude-infected-files">Exclude infected files</h2>
<p>More than a thousand of warnings on dozens of files. That’s what you can have. The goal of this step will be to fall to zero violation, as if there were nothing, but without fixing.</p>
<p>The idea of quarantine is to <strong>exclude all infected files from the analysis</strong>. An infected file is a file containing at least one violation. Only healthy files and new files will be linted.</p>
<p>In order to make the job easier, I wrote a script to list all infected files in a project. It will run SwiftLint, extract paths, and even format the output list.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/bin/bash
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="nv">current_pwd</span><span class="o">=</span><span class="sb">`</span><span class="nb">pwd</span><span class="sb">`</span>
</span></span><span class="line"><span class="cl"><span class="nv">escaped_pwd</span><span class="o">=</span><span class="k">$(</span><span class="nb">echo</span> <span class="s2">&#34;</span><span class="nv">$current_pwd</span><span class="s2">&#34;</span> <span class="p">|</span> sed <span class="s1">&#39;s/\//\\\//g&#39;</span><span class="k">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># run swiftlint, grep to filter only lines with .swift, sed to extract paths, sort to group paths, sed to remove first slash, sed to add</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Pods/SwiftLint/swiftlint <span class="p">|</span> grep .swift: <span class="p">|</span> sed <span class="s1">&#39;s/^\([^:]*\):.*/\1/&#39;</span> <span class="p">|</span> sort -u <span class="p">|</span> sed <span class="s2">&#34;s/</span><span class="nv">$escaped_pwd</span><span class="s2">//&#34;</span> <span class="p">|</span> sed <span class="s1">&#39;s/^\///&#39;</span> <span class="p">|</span> sed <span class="s1">&#39;s/\(.*\)/- \1/&#39;</span>
</span></span></code></pre></div><p>This script assumes that you did install SwiftLint in your project with cocoapods, and that you put the script in the root folder of your project. Feel free to change paths. The output of your terminal will look like that:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-Text" data-lang="Text"><span class="line"><span class="cl">Loading configuration from &#39;.swiftlint.yml&#39;
</span></span><span class="line"><span class="cl">Linting Swift files at paths
</span></span><span class="line"><span class="cl">Linting &#39;ArticleListViewController.swift&#39; (1/464)
</span></span><span class="line"><span class="cl">Linting &#39;ArticleViewController.swift&#39; (2/464)
</span></span><span class="line"><span class="cl">...
</span></span><span class="line"><span class="cl">Linting &#39;Widget.swift&#39; (464/464)
</span></span><span class="line"><span class="cl">Done linting! Found 336 violations, 30 serious in 464 files.
</span></span><span class="line"><span class="cl">- MyApp/Article/ArticleListViewController.swift
</span></span><span class="line"><span class="cl">- MyApp/Article/ArticleCell.swift
</span></span><span class="line"><span class="cl">...
</span></span><span class="line"><span class="cl">- MyWidget/Widget.swift
</span></span></code></pre></div><p>The first part is printed by SwiftLint. It is telling you which files are analyzed. The second part is the list of infected files with the relative path. This list is formatted. You will just have to copy and paste the result in the configuration file <code>.swiftlint.yml</code> under `excluded keyword. You may have to indent it.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yml" data-lang="yml"><span class="line"><span class="cl"><span class="nt">excluded</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="l">— Pods</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span>- <span class="l">MyApp/Article/ArticleListViewController.swift</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span>- <span class="l">MyApp/Article/ArticleCell.swift</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nn">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span>- <span class="l">MyWidget/Widget.swift</span><span class="w">
</span></span></span></code></pre></div><p>From now on, <strong>the number of warnings is zero and we are preventing problems on healthy files</strong>. A warning will appear as soon as a code will violate a rule on these files. And that’s because SwiftLint is still integrated, enabled and fully configured with the rules you choose.</p>
<p><strong>Only infected files at the quarantine creation are excluded</strong>. Their warnings are <em>hidden</em> and you will be able to handle them progressively. This step is performed only once, you may not have to exclude new files. We can imagine doing another quarantine if a change causes a lot of warnings (changing your rules or updating SwiftLint for example).</p>
<h2 id="treat-infected-files">Treat infected files</h2>
<p>Each time you have to edit an infected file, <strong>take the opportunity to correct few violations</strong>. Sometimes, you can also choose to pick a file and to treat all of its problems at once. Do not forget to remove a file from the excluded list when it becomes healthy.</p>
<p>Try to decide how you can take time to reduce warnings over time. Discuss about it with your team, with the other developers and also with your Product Owner or your manager. It can be for example two hours every Monday morning.</p>
<h2 id="visualize-your-progression">Visualize your progression</h2>
<p>When you have hundreds or thousands of violations, it is helpful to know where you are and how numbers are evolving. It will also motivate your team to decrease the total of warnings.</p>
<p>You can create a second SwiftLint configuration file without excluded files in order to lint everything. Give it a different name, and specify it when running the <code>swiftlint</code> command: <code>swiftlint --config .swiftlint-full.yml</code>.</p>
<p>Your basic configuration is used to show you warnings through Xcode, without files in quarantine, and your CI or an other tool can execute SwiftLint with the second configuration in order to have a global vision. This way, you can <strong>make charts or have the current count to follow your progression</strong>.</p>
<figure><figcaption>
            <p><em>SwiftLint warnings’ eradication through time, on Jenkins.</em></p>
        </figcaption>
</figure>

<p>In a <a href="https://jordanchapuy.com/posts/2019/10/unleash-the-power-of-swiftlint/" rel="">dedicated article</a> about SwiftLint, I wrote a part about the power of visualization. You can find how to easily have charts with Jenkins, or with a sheet of paper if you do not have any CI.</p>
<h2 id="forbid-regression">Forbid regression</h2>
<p>While you are healing infected files, and even when the whole project is healthy, you should prevent new violations. Do not add new errors when you are writing code.</p>
<p>For that, set up your CI to <strong>fail a build if there is new lint errors</strong>. You may otherwise want to take a look at pre-commit git hooks, to forbid a commit containing violations, or at <a href="https://github.com/danger/swift" target="_blank" rel="noopener noreffer">Danger</a> to have automatic messages on your pull requests.</p>
<p>It is also helpful to use a second SwiftLint configuration here, linting infected files, to see hidden warnings. Remember that the quarantine disable analysis on infected file. So you need something to warn you if you are adding new violations inside these files.</p>
<hr>
<h1 id="alternative-ideas-">Alternative ideas 🔀</h1>
<h2 id="disabling-rules">Disabling rules</h2>
<p>The principle of this quarantine strategy is to exclude from analysis each files containing at least one warning or error. Another possibility is to disable every of your rules in your configuration file.</p>
<p>This way, you will end up with zero violation. You can then re-enable a rule and fix corresponding warnings. One rule by one rule. It will give you the flexibility to correct problems progressively. The counterpart is that you will disable rules for every files, even healthy files or new ones.</p>
<h2 id="nested-configurations">Nested configurations</h2>
<p>You can also profit nested configurations with SwiftLint. You can put different configurations in subfolders. Thanks to that, you can choose to specifically enable or disable rules in your project hierarchy.</p>
<p>We can even imagine combining both approaches: putting some files in quarantine, and disabling certain rules on specific subfolders.</p>
<hr>
<h2 id="make-your-code-consistent-and-go-further">Make your code consistent, and go further</h2>
<p>If you want to know more about code consistency and how to unleash the power of SwitLint, you can read two of my previous articles:</p>
<ul>
<li><a href="https://jordanchapuy.com/posts/2019/10/make-your-code-consistent/" rel="">Make your code consistent</a></li>
<li><a href="https://jordanchapuy.com/posts/2019/10/unleash-the-power-of-swiftlint/" rel="">Unleash the power of SwiftLint</a></li>
</ul>
<hr>
<h1 id="and-thats-all-for-now-">And that’s all for now 👋</h1>
<p>Thanks for reading. Feel free to make any feedback and to open discussion. Let’s finish with you. How are you using SwiftLint? Do you have any tips to share when you have too much warnings? What did you learn?</p>
]]></description></item><item><title>Unleash the power of SwiftLint</title><link>https://jordanchapuy.com/posts/2019/10/unleash-the-power-of-swiftlint/</link><pubDate>Thu, 10 Oct 2019 09:00:00 +0200</pubDate><author>Auteur</author><guid>https://jordanchapuy.com/posts/2019/10/unleash-the-power-of-swiftlint/</guid><description><![CDATA[<p>One of the things I really like with the Swift language is that Apple designed it for safety. Features like <em>optionals</em> or the different operators for downcasting prevent us from causing runtime crashes in our apps. In fact, we are now dealing with <strong>compile-time errors</strong>, and it changes everything. It is less prone to mistakes because the Swift compiler will stop us before. We can neither ship an application which cannot be built, nor run it in debug.</p>
<p>So, you can see me coming: why not consider doing the <strong>same control for our code style</strong>? Guess what, there is a tool doing exactly what we want: SwiftLint.</p>
<h1 id="hello-swiftlint">Hello, SwiftLint!</h1>
<p>SwiftLint is a lint tool dedicated to Swift language. Lint means that the tool can analyze your source code and check it for programmatic and stylistic errors. It will help you make it consistent and better.</p>
<p>By running it, SwiftLint will flag every part of your code that does not respect the configured rules.</p>
<p>Today, SwiftLint is composed of *<em>more than 150 rules</em> of different categories. The project is <strong>open source</strong>, has a good community, many users, a lot of contributors, and regular releases.</p>
<p>What can you find ? Here are some examples. Stylistic rules that are about jumping lines, spaces, place of arguments, alignments, or a lot of other preferences. Smell code rules that are enforcing the compiler to detect bad things, complex code or optimized way. Also opt-in rules, that can be adopted depending on context.</p>
<p>There is a default configuration, but you can <strong>choose which rules you want</strong> to enable or disable. Moreover, particular rules have an advanced configuration like setting a trigger level, excluding a couple of strings, or choosing a severity.
If you want to know more about installation and basic configuration, you can go to the GitHub page of the project.</p>
<p><a href="https://github.com/realm/SwiftLint" target="_blank" rel="noopener noreffer">https://github.com/realm/SwiftLint</a></p>
<h2 id="how-it-works">How it works</h2>
<p>As you can see, there are multiple ways to install SwiftLint. I recommend you to install it with <a href="https://github.com/realm/SwiftLint#using-cocoapods" target="_blank" rel="noopener noreffer">Cocoapods</a>, you will <strong>share the same version</strong> of the tool across your team machines, and updating on all machines will be easier. Otherwise, <a href="https://github.com/realm/SwiftLint#using-homebrew" target="_blank" rel="noopener noreffer">Homebrew</a> is a good alternative.</p>
<p>SwiftLint is a command line tool, so you can execute it in any console. It can output several formats like JSON, XML, or Xcode. Yes, there is an Xcode format allowing you to integrate SwiftLint into Xcode. Useful to get real-time feedback. Other formats can be used by your CI.</p>
<p>You should <a href="https://github.com/realm/SwiftLint#xcode" target="_blank" rel="noopener noreffer">add a build phase in Xcode with SwiftLint</a> to analyze your code at each build. The benefit is that you will <strong>be alerted almost instantly</strong> when you do not respect a rule. Moreover, SwiftLint is well integrated with Xcode: reported problems look like compilation warnings and errors.</p>
<figure><figcaption>
            <p><em>Example of warnings after building. Yell SwiftLint, yell!</em></p>
        </figcaption>
</figure>

<p>To configure SwiftLint, you can add a <code>.swiftlint.yml</code> file inside the root directory of your project. You can find the file structure <a href="https://github.com/realm/SwiftLint#configuration" target="_blank" rel="noopener noreffer">here</a>, and a listing of all rules <a href="https://github.com/realm/SwiftLint/blob/master/Rules.md" target="_blank" rel="noopener noreffer">here</a>. You will be able to choose which rules you want to enable, and parameters for these rules. For example, setting a maximum function body length to 10.</p>
<p>SwiftLint is flexible, you can disable rules, folders or files through the configuration file, and you can even disable specific lines directly in your swift file! Simply by putting a comment like <code>// swiftlint:disable:mode &lt;rule name&gt;</code>. <a href="https://github.com/realm/SwiftLint#disable-rules-in-code" target="_blank" rel="noopener noreffer">Here</a> are some variants for disabling the current line, the next line, or until you re-enable the rule.</p>
<p>One more thing. You saw that SwiftLint can report you violations. Guess what, there is a command to automatically correct certain rules: <code>swiftlint autocorrect</code>. Only a handful of rules can be corrected by this command, but it is working great.</p>
<p>Now that you are used to SwiftLint, I can share some of my personal experiences with you and some ideas to go further. Feel free to use it.</p>
<hr>
<h1 id="unleash-the-potential-of-swiftlint-">Unleash the potential of SwiftLint 🚀</h1>
<h2 id="guide-swiftlint-to-guide-you">Guide SwiftLint to guide you</h2>
<p>Debate about your code convention, read every SwiftLint rules and determine which ones you want to enable. You will take control of SwiftLint, and SwiftLint will control your code.</p>
<p>We saw that SwiftLint is about enforcing your code style and convention. A first step can be to create your code convention if you don’t have one, or to ensure it is still up-to-date with your team. You can find inspiration in existing ones like <a href="https://swift.org/documentation/api-design-guidelines/" target="_blank" rel="noopener noreffer">Swift.org API Design Guidelines</a> or <a href="https://github.com/raywenderlich/swift-style-guide" target="_blank" rel="noopener noreffer">Raywenderlich Style Guide</a>, and choose to use a little part or almost all of it. The most important is to <strong>make your rules explicit</strong>.</p>
<p>Then the important step is to fully configure SwiftLint. The default configuration is a good start, but if you want to match your convention, you will have to read <a href="https://github.com/realm/SwiftLint/blob/master/Rules.md" target="_blank" rel="noopener noreffer">all available rules</a>. A lot of rules are not enabled by default.</p>
<p>For each SwiftLint rule, you should <strong>decide if you want to enable it</strong> or not, and <strong>configure it</strong>. This is an interesting part because you may discover new rules to make your code better.</p>
<p>Remember to get your whole team involved. The best is to do it together. Or at least get the approval of your team if you are doing it alone, and ask for feedback.</p>
<h2 id="mastering-rules">Mastering rules</h2>
<p>A lot of rules exist, and you should check the <a href="https://github.com/realm/SwiftLint/blob/master/Rules.md" target="_blank" rel="noopener noreffer">complete list</a> with details and examples to learn more about them. If you want to be up-to-date and see precisely what’s new, you can check the <a href="https://github.com/realm/SwiftLint/releases" target="_blank" rel="noopener noreffer">release page on GitHub</a>. This is useful when you are updating SwiftLint to discover how rules changed and how it can impact your project.</p>
<p>You can also go deeper. SwiftLint is open source, so you can look <a href="https://github.com/realm/SwiftLint/tree/master/Source/SwiftLintFramework/Rules" target="_blank" rel="noopener noreffer">how a rule is implemented</a> if you want. I did it when I wanted to know more about how a rule works or which parameters have to be used to configure it. Sometimes, it was just curiosity :)</p>
<h2 id="visualize-your-progression">Visualize your progression</h2>
<p>Visualization is something very powerful. If you are looking on agile culture, many elements are visible. Metrics, charts, stories, sketches, … All of these are easily accessible, sometimes physically, by everyone. Teams know where they are, and where they go.</p>
<p>We can do the same for SwiftLint. When you have a lot of warnings (typically when you are adding a strict configuration on an existing project), it helps and <strong>motivates</strong> to <strong>know where you are</strong> and <strong>how numbers are evolving</strong>. You can have a metric for the main branch, the number of current warnings, and a chart gathering warnings through time. Put this on a dashboard, always visible, and you will see a super team improving the project.</p>
<p>If you have Jenkins, there is a simple way to get a graphic by using a plugin. For example, I chose androidLint. I added this plugin and I created a python script to convert the output of SwiftLint into the corresponding format. Then, I added a step in the <code>Jenkinsfile</code>: for each commit, SwiftLint is executed, the output is converted, and the plugin is called. This way, you can have a graph for each branch. You can analyze your feature branch, short-term, and also develop and master branch, long-term.</p>
<figure><figcaption>
            <p><em>SwiftLint warnings’ eradication through time, on Jenkins.</em></p>
        </figcaption>
</figure>

<p>You do not have a dashboard, a CI, or any tools? Let’s return to the future! Pick a pen, a sheet of paper and a post-it. We can write the current amount of warnings on the post-it and draw a chart on the sheet. Time on x-axis, and warnings on y-axis. Every day (or week or whenever you decide), put a new post-it with the updated number, and add a new point on the chart. Quick and efficient.</p>
<h2 id="limit-regression">Limit regression</h2>
<p>When you are putting effort to decrease the number of warnings, I think that you prefer to not add new violations. For that, you can add a safeguard.</p>
<p>You can set up your CI to <strong>fail a build if there is new lint errors</strong>. It can be done with the androidLint plugin on Jenkins for example, by configuring <code>failedTotalHigh</code> and <code>failedTotalNormal</code> arguments.</p>
<p>You may otherwise want to take a look at pre-commit git hooks, to forbid a commit containing violations, or at <a href="https://github.com/danger/swift" target="_blank" rel="noopener noreffer">Danger</a> to have automatic messages on your pull requests.</p>
<h2 id="nested-configurations">Nested configurations</h2>
<p>Thanks to the YML file, you can configure every parts of SwiftLint for your project and your team. You are choosing which rules you want. And you can do more.</p>
<p>If you put an other configuration file deeper in the arborescence, it will be used instead of the main configuration at the root folder. Meaning, you can have specific rules for a specific folder including its children.</p>
<p>When linting a file, SwiftLint use the configuration in the current file folder, if any. Otherwise, it will recursively look in parent folders if there is one. If none, it will use the configuration file in the folder where the command was executed. And by default, SwiftLint uses its hardcoded default.</p>
<p>A possible use case is to have different rules for your unit tests target. You may want to have certain rules disabled or configured with different parameters. Be careful to not disable too many rules, your unit tests code is important and should be readable too.</p>
<h2 id="disabling-a-rule-through-code-should-be-use-sparingly">Disabling a rule through code should be use sparingly</h2>
<p>Do not abuse of disabling a rule inside a swift file with a comment. It can be tempting but it can hide another problem. Ask yourself why are you disabling the rule here.</p>
<p>Is it the first time I disable this rule? If not, you may need to reconsider this rule, or to configure it more accurately. Is it a real exception, or is it laziness ? You should have a good reason to disable it.</p>
<hr>
<p>Let’s finish with you. How are you using SwiftLint? Do you have any tips to share? What did you learn?</p>
]]></description></item><item><title>Make your code consistent</title><link>https://jordanchapuy.com/posts/2019/10/make-your-code-consistent/</link><pubDate>Wed, 09 Oct 2019 09:00:00 +0200</pubDate><author>Auteur</author><guid>https://jordanchapuy.com/posts/2019/10/make-your-code-consistent/</guid><description><![CDATA[<figure><figcaption>
            <p><em>They are all different, but they all look alike.</em></p>
        </figcaption>
</figure>

<p>We all have our rules, our preferences. Even beliefs. Sometimes, you can talk with people who have the same principles. Sometimes, they can have thoughts that diverge from yours, completely.</p>
<p>Discussing different points of view is often interesting. You can learn a lot, and it opens your minds to new ideas. So, do not close the door to constructive debates. Moreover, you can use these discussions to improve group cohesion and build a shared vision.</p>
<h2 id="write-readable-and-consistent-code">Write readable and consistent code</h2>
<p>Sometimes, I see myself as a writer. Not as a code writer, but as a story writer. I try to tell a story with my code in order to make it easier to understand. I do my best to make it as readable as possible, and to make it consistent. I think that <strong>a well-written story is a story that reads well</strong>. The sentence may seem funny, but as a writer, you will be read.</p>
<p>Your code can be read by a coworker during a code review, or when adding a new feature. It can also be read by you, later. Oh, I just said coworker. Your code may be a part of someone else’s code, or even several people. Different people writing the same story? Will it be easy to read? It can be, and one of the way is to make it consistent.</p>
<blockquote>
<p>By having consistent code, you can focus on the functionality and not on the style.</p>
</blockquote>
<p>You will not be distracted by a different syntax of a coworker or an old code. Furthermore, it will be easier for a new member to join your team. The story reads as if it was written by only one author.</p>
<p>Writing consistent code can be more than just having the same style. It can also be sharing good practices. Consider for example force unwrapping, function body length, or the preference to use <code>first(where:)</code> or <code>filter{}.first</code>. All this works, but, depending on your thought, they can be improved. If the same way is adopted by the team and used everywhere, it will be easier to write, and to read.</p>
<p>About that, if you want to share some rules, it can be interesting to put it down in a code convention.</p>
<h2 id="make-your-code-convention">Make your code convention</h2>
<p>A code convention can be helpful for a team to ensure the code quality and the readability by listing various rules, good practices and code style. <strong>Making things explicit</strong> will reduce doubt, misunderstanding, and lack of knowledge. Collaboration will be easier.</p>
<p>If your team follows the same convention, it will make your project more consistent. It can help you to write code, and to review others’ code. For a new developer joining your team, this is a quick way to learn your practices.</p>
<p>When doing a code review, you can <strong>focus on important changes and structure</strong>. You will avoid having to debate again about the use or not use of whatever thing. You already did it, and the team agreed at the end. You will discuss and put effort into new things. But this is not a problem if there is any violation, it can happen, and there will be less with time.</p>
<p>While we are on this subject, some people can felt hurt during code review. They can take it personally. It can be helpful to refer to your code convention when you are discussing about their code. You are not attacking the person. You are underlining a piece of code that does not respect a code convention. Your team convention. And you are helping this person to improve that.</p>
<p>The code convention concerns the whole team. You should write it together to get everyone involved. Discuss, listen, and be open.</p>
<blockquote>
<p>This code convention may not be the best, nor yours, but it will be the one for your team.</p>
</blockquote>
<p>This convention will be adapted to your context, your project and your team. Build the convention together, and make it live with time. You may not need to be exhaustive immediately, and you may want to change it later, don’t be stuck.</p>
]]></description></item></channel></rss>