Ceci est une ancienne révision du document !
Table des matières
Résumé de « Proprement codeur : code de conduite pour développeurs professionnels »
Un ami et ancien collègue m’a offert ce livre pour Noël (livre qu’il s’est lui-même acheté). J’ai eu l’idée de faire se résumé pendant la lecture car je pense réellement que les conseils présents en valent le coup. L’ISBN du livre est 978-2-3260-0289-0 si vous souhaitez vous le procurer. Si vous bossez dans l’IT ou même si vous êtes étudiant·e·s en IT, n’hésitez pas à le demander à votre CTO ou dans la bibliothèque de votre établissement.
⇒ Avoir une bibliothèque fournie de livres de ce genre permettra aux équipes d’être encore meilleures.
Chapitre 1 : professionnalisme
Chapitre 2 : savoir dire non
Chapitre 3 : savoir dire oui
Chapitre 4 : coder
Préparation
Coder consiste de jongler entre 4 contraintes différentes :
- Le code source doit fonctionner : doit présenter une solution cohérente des contraintes du système réel.
- Le code doit résoudre le problème tel que présenté : la demande business n’est peut-être pas correctement formulée, c’est aux développeur·euse·s d'y apporter une solution adaptée pour satisfaire les besoins réels du client.
- Le code doit s’insérer proprement à la solution actuelle : il ne peut ni fragiliser, ni rigidifier, ni opacifier ce système.
- Le code doit être lisible par les autres développeur·euse·s, c’est-à-dire lisible, maintenable et montrer vos intentions.
Code & problèmes
Quand nous sommes distrait·e·s par un problème, quel qu’il soit, il est préférable de s’attarder à celui-ci ou, du moins, lui allouer un peu de temps. Il vaut toujours mieux prendre une heure pour vous calmer plutôt que persister à écrire du code que vous seriez obligé·e de jeter ou de vivre avec.
Interruptions
On peut parfois être interrompu·e par une ou plusieurs personnes. Il n’est pas professionnel d’être grossier·ère.
- Lorsque nous sommes bloqué·e·s sur un problème, il est préférable de faire appel à un·e partenaire de binôme. En cas d’interruptions, cette personne peut garder le fil de la discussion.
- Lors de TDD, le test actuel incarne le contexte actuel.
- Solution possible : prévoir une plage horaire où vous ne préférez pas être interrompu·e mais prévoyez un moment où votre porte est grande ouverte.
Angoisse de la feuille blanche
Si on reste assis·e devant notre écran, sans savoir quoi faire :
- Se détendre (aller marcher un peu, boire un café, etc)
- Le manque de sommeil est une cause possible
Prendre soin de soi
Le développement n’est pas un sprint ; c’est un marathon. Ménagez vos ressources.
Savoir faire une pause
Lorsque nous insistons alors que nous sommes fatigué·e·s, le seul effet qu’on peut avoir est d’accroître la fatigue. Arrêtez les frais dès que vous êtes fatigué·e·.
Quand on est bloqué·e et fatigué·e·s, faites une pause. Découvrez vos rythmes de créativité et d’éveil ; il vaut mieux travailler avec eux et non contre eux.
Être en retard
On finira tou·te·s par être en retard sur nos estimations.
- Soyez transparent·e : il n’y a rien de pire que de continuer à rassurer quelqu’un qu’on sera dans les temps.
- Montrez régulièrement votre progression.
- Établissez trois dates : au mieux (optimiste), une date nominale (réaliste) et date au pire (pessimiste).
- Soyez honnête avec ces dates.
- Mettez les à jour quotidiennement.
- Ne laissez par les autres commencer à espérer.
Heures supplémentaires
Parfois, on peut être amené·e à faire des heures supplémentaires. Mais lorsque c’est pour résoudre un problème de timing sur le projet, on en peut pas travailler davantage que possible et nous ne tiendrons pas ce régime de surcharge plus de deux ou trois semaines.
Si le management nous demande de faire des heures supplémentaires, n’acceptez que si ces trois conditions sont réunies:
- Si vous pouvez personnellement l’accepter
- Si c’est pour une durée limitée d’environ deux semaines
- Si votre team lead a prévu un plan de secours au cas où ce travail supplémentaire ne donnerait pas les résultats escomptés
Livraisons frauduleuses
Lorsqu'une personne commence à dire « j’ai terminé ce ticket » et qu’il ne l’est pas ; c’est contagieux ! Le management va penser que tout va bien et personne n'aura vu le train du travail non-achevé fonçant sur elleux lors de la livraison du projet.
Aider les autres
En tant que développeur·euse, il faut toujours se tenir prêt·e à aider nos collègues. Il en va de notre honneur d’accepter cette demande (dans les limites du raisonnable ; l’objectif n’est pas d’absorber le sprint de notre collègue mais bien de le débloquer).
Recevoir de l’aide
Aussi, on peut avoir besoin d’aide. Si la personne qui a accepté de vous aider ne le fait pas vraiment, proposez d’en rester là et remerciez-là.
Chapitre 5 : développement dirigé par les tests ou TDD
Trois lois du TDD
- Vous ne vous autorisez pas à écrire du code de production tant que vous n’avez pas écrit d’abord un test unitaire qui doit évidemment échouer.
- Vous ne vous autoriserez pas à écrire plus de code de test unitaire que nécessaire pour provoquer l’échec de compilation.
- Vous ne vous autoriserez pas à écrire plus de code de production que celui qui permet au final de réussir le test unitaire qui échouait.
Bénéfices
Si les tests réussissent, on peut être certain·e·s qui le refactoring du code de production n’a pas généré d’effet indésirables (mal fonctionnement, effets de bord,…).
Un taux de coverage d’au moins 90% est conseillé. La plupart des outils qui calculent ce taux ne prennent pas en compte les cas d’exceptions (try…catch) en compte.
Lorsqu’on ne fait pas de TDD, on peut être frileux·se de refactorer une partie du code de peur de rendre l’ensemble non opérationnel. Un code propre est plus facile à relire, à maintenir et à enrichir.
Documentation
- La lecture des tests permet de savoir comment chaque élément du système fonctionne et comment l’exploiter
- Les test sont la documentation qui décrivent la conception du système
- Les tests sont écrit dans un langage qui quiconque devra comprend
Conception
Il est nécessaire de concevoir les tests avant d’écrire le code. Cela permet de concevoir des fonctions qui ne feront pas appels à d’autres fonctions. Écrire les tests avant de rédiger le code nous oblige à concevoir une bonne approche de conception.
Si on veut écrire les tests après avoir écrit le code, on peut avoir une masse informe et difficile à tester (fonctions faisant appel à d’autres fonctions, etc).
Deux approches différentes :
- Approche offensive : écrire les tests avant de rédiger le code : tests précis, informatifs
- Approche défensive : les tests ne peuvent être écrit que par une personne connaissant le système et sait déjà comment le problème à été résolu. On adapte alors les tests au code et non l'inverse.
Faire du TDD favorise la certitude, le courage (de refactorer), la réduction de cas non-gérés, la qualité de la conception, du code et enfin, de la documentation.
Ce que le TDD n’est pas
Le TDD n’est pas une formule magique. Faire des tests s’apprend : il y a de forte chance qu’avant de faire du code de production incorrect, nous fassions de mauvais tests.
Chapitre 6 : entraînement
Selon l’auteur, l’entraînement fait partie intégrante du métier pour un développeur professionnel. L’objectif est d’être capable de détecter une grande variété de problèmes et de savoir comment y réagir.
Kata
Dans les Arts Martiaux, l’entraînement solitaire s’appelle un kata. Il s’agit du même principe pour le développement ; un problème qu’on répète jusqu'à ce qu’il soit résolu. L’intérêt n’est pas de connaître comment résoudre ce problème en dormant mais bien à prendre des habitudes nous permettant d'être plus productif·e.
La répétition permet d'automatiser les mouvements et les rendre instinctifs pour qu’ils puissent être déclenchés le moment opportun.
- La résolution de l’exercice n’est pas l’objectif
- L’objectif est la mise en pratique des mouvements et des décisions
- Apprendre les raccourcis clavier et à maîtriser nos outils
Quelques sources & katas (tous en anglais) :
Waza
Un Waza est l’équivalent d’un Kata mais en duo.
- Les deux partenaires choississent un kata ou un problème simple à résoudre
- Læ premier·ère rédige le test unitaire, læ second·e rédige le code qui doit réussir le test
- Échange des rôles
Les développeur·euse·s pratiquent et évaluent les capacités de frappe de touche et l’utilisation de la souris ainsi que le degré de perfection du kata.
On peut également s’imposer des contraintes, par exemple :
- Contrainte de performance
- Occupation mémoire
- Etc
Le jeu en devient ainsi enthousiasmant et amusant.
Randori
Le randori est un combat libre. Il se fait en groupe de plusieurs personnes.
- Une première personne écrit un test et puis s’éloigne
- La personne suivante se charge de la réussite du test et écrit le test suivant
Les participants peuvent être assis autour d’une table ou se promener dans la pièce. On élargit ainsi notre horizon technique tout en renforçant nos compétences.
Extension du domaine de l’expérience
Nombreuses sont les professionnels qui manque de diversité dans le genre de problème que nous savons résoudre. Les employeurs obligent souvent à n’utiliser qu'un seul langage, qu’une seule plateforme et qu’un seul domaine métier. Sans entraînement, on risque d'appauvrir notre CV et notre état d’esprit.
Une solution serait de contribuer à l’open source dans un langage que nous ne connaissons pas, par exemple un·e dev Javascript peut participer à un projet Python, un·e dev C# peut participer à un projet Java, etc.
Éthique de l’entraînement
L’employeur n’est pas censé financer le maintien de nos compétences dans un état optimal. Ce n’est pas son rôle ; nous ne sommes pas payés pour nous entraîner.
On s'entraîne alors sur notre temps personnel, potentiellement dans d’autres langages pour rester polyglotte.
Tous les professionnels s’entraînent pour pouvoir fournir la meilleure prestation possible. On s’entraîne pour pouvoir être payé·e et être payé·e correctement.
Chapitre 7 : tests d’acceptation ou recette
Læ développeur·euse professionnel·le veille à ce que nos productions soient toujours exactes et univoques.
Communication et exigences
Le domaine dans lequel les problèmes de communication entre les développeur·euse·s et les clients ont le plus d’impact est celui des exigences ou du cahier des charges.
Précision prématurée
Le client et les personnes du métier veulent définir dans les moindres détails ce qu’iels vont financer avant d’autoriser le lancement du projet. On va chercher alors un degré de précision que nous ignorons à ce stade.
Le principe d’incertitude
Les choses se présentent différent sur le papier que dans un système réel. Ce n’est pas tout à fait voir pas du tout ce que læ client·e avait demandé. Ce n’est que lorqu’iel voit ses exigences traduites à l’écran qu’iel peut se former un eidée plus précise de ce qu’iel a besoin.
Plus les exigences ou spécifications sont détaillées au départ, moins elles seront pertinentes une fois prises en compte dans le système.
Angoisse des estimations
On risque de déployer inutilement des efforts inutiles en recherchant la précision maximale lors de nos estimations. Les exigences évoluent inévitablement, ce qui rend la précision inutile.
Pour combler ce risque, nous pouvons donner une plage d’incertitude de telle manière que læ client·e en soit informé. (voir chapitre 10)
Ambiguïté tardive
Pour éviter les précisions prématurées, on peut ne pas décortiquer précisément chaque élément du cahier de charge.
Le business ainsi que l’IT présument que les autres lecteurs du document savent parfaitement de quoi iels parlent. C’est dans ces ambiguïtés que nous devons travailler. Aussi bien les développeur·euse·s que les parties prenante doivent éliminer toute ambiguïté dans les exigences.
Pour y parvenir, il n’y qu’une seule chose :
Tests d’acceptation
Les tests d’acceptation sont ceux qui sont issus de la collaboration entre le business et l’IT. Cela permet de déclarer que le travail correspondant est réellement achevé… sans ambiguïté.
La définition d’achèvement, « definition of done »
L’achèvement c'est quand le code source est écrit, que tous les tests ont réussi, que le contrôle qualité a accepté le produit et les parties prenantes aussi. L’état d’achèvement est alors total.
Lorsque les tests d’acceptation de la fonction considérée réussissent, c’est que nous avons achevé le travail.
Communication
Les tests d’acceptation servent à communiquer clairement et précisément. C’est la manière exacte de comment le système devrait se comporter.
Automatisation
Læ développeur·euse professionnel·le se sent responsable dans la mesure où iel s’assure que les tests d’acceptation sont automatisés.
Supplément de travail
Les tests automatisés sont une source d’économie énorme en terme de temps et d'argent. Si les tests ne sont pas automatisés, il faut une procédure de test manuelle ce qui consomme énormément de temps (et d’argent), alors que si le test est vert, on sait que ça fonctionne et nous n’avons pas besoin de tester manuellement.
Rédaction des tests : par qui et quand ?
Dans un monde idéal, les tests sont rédigés par les parties prenante et le service qualité puis les développeur·euse·s les vérifient afin de garantir leur cohérence.
Lorsque la rédaction est faites par les devs, il faut s’assurer que ce n'est jamais la personne même qui rédige le test et qui code la fonctionnalité.
- Les premiers tests doivent être prêts lors du premier jour de l’itération.
- À la moitié de l’itération, les tests des prochains milestones doivent être prêt.
- Si ce n’est pas le cas, les devs redoublient d’efforts pour les achever.
- Si ce retard ce produit, c'est qu’il faut sans doute renforcer l’équipe d’analystes métier ou de l’assurance qualité.
Négociation et agression passive
Ceux qui rédigent les tests sont humains et donc susceptibles de faire des erreurs. Le car échéant, læ développeur·euse qui est chargée de faire réussir le test peut vraiment se sentir frustré·e.
Notre travail consiste à aider l’équipe à produire le logiciel de la meilleure qualité possible.
Tests d’acceptation et tests unitaires
- Les tests unitaires sont écrits par des devs our des devs.
- Les tests d’acceptation sont écrits par le client pour le client. Les destinataires de ces tcests sont aussi bien le métier que les devs.
Ces deux types de tests ne sont absolument pas interchangeables.
Les tests unitaires comme les tests d’acceptation sont d’abord des documents, leur rôle est d’obliger à expliciter de façon formelle la conception, la structure et le comportement du système.
Interface graphique et autres complications
- Une UI est mouvante et change constamment
- Il faut pouvoir considérer l’UI comme un système utilisant une interface API et non comme un ensemble de boutons.
si on veut vraiment tester l’UI, il est préférable de déclencher l’action en citant le nom du bouton plutôt que des positions absolues à l’écran.
Tester via la bonne interface
L’idéal est de rédiger les tests de sorte à appliquer les fonctions du système concerné en passant par une interface API réelle et non pas une en attaquant directement l’interface.
L’interface UI pose toujours problème, il faut donc prendre soin de décrire nos tests concernant les règles métier en utilisant une API sous le niveau de l’interface UI.
Intégration continue
Nous devons nous assurer de faire exécuter nos tests unitaires et tests d’acceptation le plus souvent possible (par exemple au commit ou push) si on travaille dans un environnement d’intégration continue.
Arrêtez tout !
Il faut considérer tout blocage de la production en contexte CI comme une urgence absolue !
Conclusion
Il n’est jamais simple de communiquer de façon détaillée et c’est particulièrement le cas lors des échanges entre les développeur·euse·s, le business et la qualité assurance.
La seule technique que connaît l’auteur pour éliminer les erreurs de communication est la rédaction des tests d’acceptation automatisés, supprimant toute ambiguïté. Ils constituent de parfaits documents pour incarner les exigences.
Chapitre 8 : stratégie de test
L’assurance qualité doit être bredouille
Principe important : il faut faire en sorte que l’assurance qualité ne trouve rien. Vu que cela est pratiquement impossible, cela veut dire que l’équipe de développement doit se sentir peinée lorsque la QA trouve quelque chose à redire.
Il est impératif de chercher comment cela a pu se produire et prendre des mesures pour que le défaut ne réapparaisse jamais.
L’assurance qualité fait partie de l’équipe
Les deux départements doivent travailler ensemble, iels travaillent pour le même objectif : garantir un produit de qualité.
L’assurance qualité doit cependant jouer deux rôles:
- Spécifier :
- production de tests d’acceptation automatisés (de manière générale, les analystes écrivent les cas nominaux et la QA les cas d’exception).
- recueillir les exigences de façon itérative
- Caractériser : identifier la façon dont le système se comporte effectivement
Pyramide de l’automatisation des tests
Tests unitaires
Les tests unitaires sont rédigés par les développeurs (mais pas cellui qui développera la feature derrière) juste avant la rédaction du code de production. Le taux de couverture des tests unitaires doit être le plus proche possible des 100%.
La couverture doit être véritable : on ne triche pas et on test véritablement son code.
Tests de composants
Les composants sont des éléments mis ensemble afin d’incarner une règle métier, ils correspondent ainsi à une partie des tests d’acceptation. Les autres composants que celui testé être isolés avec des mocks ou grâce à la technique de double de test.
Ils sont rédigés par la QA en collaboration avec les analystes mais éventuellement des dévelopeur·euse·s. Mais attention : ces tests doivent rester lisible et interprétable par des personnes non technique qui peuvent également en rédiger eux-même.
Tests d’intégration
Ce niveau de test n’est pertinent que pour des systèmes constitués de nombreux composants. Ils ne testent pas les règles métiers mais vérifient qu’un ensemble de composants opère de manière harmonieuse au sein du système. C’est également ici qu’on commence à rencontrer des tests de performance et de débits.
À ce niveau, les tests cessent d’être exécutés dans un contexte d’intégration continue mais doivent l’être de manière période, le plus souvent possible.
Tests système
Les tests systèmes sont des tests appliqués à la totalité du système une fois celui-ci intégré avec les parties tierces, ils servent donc à vérifier que le système a été correctement connectés avec ces parties, à l’instar d’un CRM ou d’un ERP. Ceux-ci peuvent également inclure des tests performances.
En général, la rédaction des tests système se fait par les architectes systèmes et/ou les responsables techniques.
La fréquence d’exécution dépend de leur durée mais doivent, au mieux, se faire le plus fréquemment possible.
⇒ Pour les exécuter, il faut que les éléments inférieurs de la pyramide soient verts.
Tests manuels d’exploration
Ces tests sont fait plus rarement et uniquement par des humains. Il s’agit de test manuels sans aucun protocole (car ces protocoles sont censés être testé dans les niveaux en dessous) mais l’objectif est de trouver des bugs et vérifier que le système se comporte correctement quand c’est un humain qui pilote le système… et les humains peuvent se montrer très surprenant.
Conclusion
Les tests d’acceptation sont indispensables pour qu’on puisse se permettre de dire au business que quelque chose est terminé. Les équipes de développement et de QA doivent collaborer ensemble pour l’objectif commun qu’est de fournir un logiciel fonctionnel et conforme aux exigences.
Less test doivent être exécutés le plus souvent possible.