Ces jours-ci, nous devrions réfléchir de manière critique à la façon dont nous faisons les choses dans la programmation. Nous devons appliquer l'approche d'ingénierie à nos processus. Nous, les ingénieurs logiciels, sommes confiants dans les discussions sur les classes abstraites et les fonctions pures. Par contre, on s'enfuit quand il faut discuter de choses "managériales".
Mon processus de programmation largement répandu préféré qui a une énorme quantité de défauts est la revue de code. Cette histoire l'abordera sous différents angles et proposera des améliorations.
Le premier fait significatif que j'ai lu sur les inspections de logiciels était dans le livre "Facts and Fallacies of Software Engineering" de Robert Glass. Il revendique ce qui suit :
Des inspections rigoureuses peuvent supprimer jusqu'à 90 % des erreurs d'un produit logiciel avant l'exécution du premier scénario de test.
Je n'ai pas pu déterminer si ces mots concernaient uniquement la révision du code. Je les traite comme faisant référence à différents types d'inspections, que je décrirai plus tard.
Oncle Bob Martin m'a aidé à découvrir les racines de nos revues modernes . Michael Fagan a formulé l'idée des inspections en 1976 dans son article "Concevoir et coder des inspections pour réduire les erreurs dans le développement de programmes".
J'y ai découvert trois types d'inspections suivants :
Le travail de Fagan ne propose pas une nouvelle approche du code mais documente les phénomènes déjà existants et les défend. Cependant, l'article est le premier signe écrit d'inspections que j'ai trouvé.
Les inspections de code ressemblent à nos revues de code modernes. Pourquoi manquons-nous d'autres types d'inspections aujourd'hui?
La popularité des inspections de code et la quasi-inexistence d'autres types d'inspections aujourd'hui vient de nos outils. GitHub, BitBucket ou GitLab ont tous des instruments de révision de code intégrés, et ils s'intègrent naturellement dans le flux Git, le flux GitHub et d'autres approches.
Quel outil utilisez-vous pour les activités de conception ? Il ne s'agit pas de l'UI/UX. Il s'agit de la structure du code que vous allez construire. Vous avez peut-être entendu parler des outils CASE ou UML. Je ne les ai vus sérieusement utilisés dans aucune entreprise pour laquelle j'ai travaillé, et j'ai travaillé pendant sept ans.
Sur HackerNoon, la requête de recherche « UML » donne seulement deux résultats pertinents. Il n'y a donc pas lieu d'introduire l'inspection de conception lorsqu'il n'y a pas de processus de conception de solution tangible. Dans l'équipe que je dirige, nous avons utilisé Miro pour la conception des interfaces. Le processus aurait pu être plus satisfaisant : comme avec d'autres outils de création de diagrammes, vous commencez rapidement à dessiner au lieu de résoudre vos problèmes. Nous pouvons être indépendants de nos outils. Voici une petite citation à l'appui de cela tirée du livre "Investments Unlimited":
... si nous faisons juste ce que les outils peuvent faire — alors nous serons toujours limités aux capacités de nos outils.
Regardons le processus dans sa forme classique sous différentes perspectives. Chacun d'eux présente des problèmes importants.
BPMN est une notation de modélisation de processus métier. Il décrit les processus avec des actions, des événements, des passerelles logiques, des messages et d'autres moyens. Je recommande même de l'utiliser si vous souhaitez développer un algorithme, car il est plus descriptif qu'un organigramme. Représentons le processus de révision de code pour un seul réviseur avec cette notation et analysons-le. J'ai utilisé un outil textuel pour générer le diagramme à venir . Il y a un petit problème dessus avec de nombreuses lettres qui reviennent.
Tout commence par une création de relations publiques, et rien n'est notable ici. L'étape suivante consiste à notifier un examinateur, qui est une simplification de tous les différents moyens disponibles pour dire : "Hey, mon PR vous attend ! 👋" Ce qui est important ici, c'est la libération des activités en cours. Ici, le PR attend pendant une durée inconnue. Ensuite, l'examinateur plonge dans la tâche et procède à l'examen. Il y a une chance qu'un PR soit fusionné tout de suite. Cependant, l'inverse pourrait se produire : quelques commentaires nécessitant des corrections apparaîtraient.
L'auteur du code est peut-être déjà dans la tâche suivante et il y a encore un temps d'attente d'une durée inconnue. De plus, revenir nécessite une restauration du contexte, l'interprétation des commentaires et leur correction.
L'étape suivante est la notification de l'examinateur.
N'y sommes-nous pas déjà allés ? Oui, tu as raison. Nous venons de terminer notre première itération de la boucle potentiellement infinie. Oui, infini. Il y a toujours une chance que de nouveaux commentaires apparaissent. Ou que l'une des périodes d'attente durerait éternellement.
Voulons-nous que la boucle potentiellement infinie fasse partie de nos opérations quotidiennes ? Je ne suis pas sûr, car avoir une livraison plus rapide est généralement préférable.
Parfois, nous avons des développeurs ou des architectes seniors dans nos équipes en tant que réviseurs. Ils souhaitent avoir une base de code cohérente, s'en tenir à certaines méthodes et modèles et en éviter d'autres. Ils ont une vision. Les développeurs ont aussi leur idée. Habituellement, ils ne sont pas conscients de l'intention de leurs aînés. Cela nécessite une diffusion cohérente ou un environnement auxiliaire, ce qui arrive rarement. Regardons l'image suivante.
Vous pouvez voir en quoi les deux visions des participants à la revue de code diffèrent. Après la première itération, ils commencent l'alignement, mais il reste encore du chemin à parcourir. Le relecteur ajuste sa vision, et l'auteur du code se déplace en fonction de l'interprétation des propositions.
Nous pouvons utiliser la métaphore "imaginez que vous avez demandé une maison et puis surprise ! Ce n'est pas celle à laquelle vous vous attendiez". Ou nous pouvons regarder son noyau. Imaginez que vous avez demandé à une personne de réaliser quelque chose. Ensuite, vous revenez et voyez les résultats, mais vous êtes surpris par l'ensemble des décisions que le réalisateur a prises. Ne soyez pas surpris, car vous n'aviez pas besoin d'un cadre décisionnel particulier.
L'image parle d'elle-même. Demanderiez-vous à votre collègue ingénieur de résoudre le problème de conception après avoir passé plusieurs jours sur la tâche ? Imaginez que votre sprint se termine, et que le ticket soit à l'origine d'une certaine tension sur un stand-up. Vous aiderez votre collègue à le fusionner le plus rapidement possible. D'un autre côté, il pourrait y avoir un ingénieur senior examinant le code du junior. Il pourrait lui demander d'aller loin pour corriger la décision prise au début. Cependant, est-ce le bon moment pour donner de tels conseils ? Tant de décisions reposent déjà sur le mauvais choix.
La fabrication au plus juste n'a pas encore influencé la programmation. Cependant, nous avons déjà un outil du livre "Lean Software Development" de Mary Poppendieck et Tom Poppendieck. Cet outil représente les sept déchets de développement logiciel :
Travaux en partie terminés,
Fonctionnalités supplémentaires,
Réapprentissage,
Transferts,
Retards,
Le changement de tâche,
Défauts.
La revue de code classique remporte 6 sur 7 !🎉
Nous avons couvert les problèmes des révisions de code de plusieurs côtés. Que pouvons-nous faire pour résoudre ce processus ?
Dans cette section, nous aborderons les mêmes sujets que la précédente mais du point de vue de la fixation.
Ici, nous avons un auteur de code qui attend la fin d'une révision et une session de programmation en binôme après la vue d'ensemble d'un réviseur.
Dans le processus proposé, on peut voir plusieurs changements significatifs par rapport au précédent :
Plus de boucle de révision potentiellement infinie ;
Temps d'attente unique de durée inconnue, nous nous en occupons également ;
Pas besoin de restaurer le contexte ou d'interpréter les commentaires pour l'auteur du code. Les commentaires servent désormais de rappels pour la paire.
Quelles sont les conditions préalables essentielles pour que ce processus se produise ? Maintenant, une équipe a besoin d'un rôle supplémentaire. Cela implique que quelqu'un effectue les activités auxiliaires, par exemple, gère la dette technique ou corrige les bogues de moindre priorité. Lorsque la revue de code apparaît sur le radar, cette personne abandonne immédiatement la tâche en cours et saute dans le PR arrivé. Si vous vous êtes déjà demandé pourquoi vous avez besoin d'un peu de mou dans la structure de votre travail, voici un exemple. Si tout le monde est occupé par les fonctionnalités prioritaires, vous les recevrez plus tard.
De quoi parlons-nous lors des revues de code ? Les décisions prises au cours du développement. Nous en avons fait certains il y a une heure et d'autres il y a une semaine. Nos choix se superposent et ne sont pas indépendants.
Dans quelle mesure trouvez-vous agréable l'occasion de remettre en question l'une des premières décisions sur lesquelles les centaines de personnes suivantes se tiennent ? Vous pourriez être mécontent de cette opportunité.
Le moment le plus approprié pour discuter des décisions de conception est lorsqu'elles apparaissent. Nous avons besoin d'un type d'examen supplémentaire : l'examen de la conception. Parfois, lorsque le problème est difficile, il est bon de passer du temps sur le plan et d'en discuter avec vos collègues compétents.
Il existe un célèbre adage militaire :
Aucun plan de bataille ne survit au contact avec l'ennemi.
Si nous le traduisons dans le langage des systèmes, nous obtiendrons quelque chose comme : "Le système devra certainement ajuster son comportement lorsque les premiers retours arriveront". Dans le cas de la programmation, les commentaires seraient les problèmes auxquels nous sommes confrontés lorsque nous essayons de mettre en œuvre la conception dans notre système. Certaines décisions doivent être révisées. Nous aurions besoin de les changer et de nouveau diverger dans nos visions avec un critique.
Adam Thornhill, dans son écrasant livre "Software Design X-Rays", a proposé une méthode :
C'est pourquoi je vous recommande de faire votre première procédure pas à pas de code beaucoup plus tôt. Au lieu d'attendre l'achèvement d'une fonctionnalité, prenez l'habitude de présenter et de discuter de chaque implémentation au tiers de l'achèvement. Concentrez-vous moins sur les détails et davantage sur la structure globale, les dépendances et la façon dont la conception s'aligne sur le domaine du problème. Bien sûr, l'achèvement d'un tiers est subjectif, mais il doit s'agir d'un point où la structure de base est en place, le problème est bien compris et la suite de tests initiale existe. À ce stade précoce, une refonte de la conception est toujours une alternative viable et la détection des problèmes potentiels ici est très rentable.
J'ai inventé un terme pour que mon équipe ait un langage pratique : la revue squelette. J'espère que cela aide à refléter l'idée derrière l'activité.
Le procédé proposé élimine ou traite de manière significative les déchets découverts.
Nous avons revu l'approche de revue de code pour un seul auteur et un seul relecteur. Lorsque plus d'examinateurs apparaissent, les problèmes se multiplient. Donc, malheureusement, tous les bogues ne deviennent pas superficiels si vous ajoutez des personnes récemment pour examiner toutes les décisions que vous avez prises. Vous feriez plutôt fusionner votre code plus tard.
Deux des problèmes les plus difficiles auxquels j'ai été confronté lorsque j'ai essayé d'introduire le processus proposé étaient les suivants :
Les développeurs traitent l'étape de révision comme un travail accompli. Les managers sont horrifiés lorsqu'ils proposent d'introduire des licenciements dans le travail quotidien. C'est bien qu'ils ne gèrent pas les équipes de pompiers.
Le remède au premier problème est la répétition et la vitesse.
Le deuxième problème est plus compliqué. Ici, je veux citer le livre "Actionable Agile Metrics for Predictability" de Daniel Vacanti :
FedEx utilise de nombreuses stratégies, mais celle qui est probablement la plus importante est qu'à tout moment, FedEx a des avions vides dans les airs. Oui, j'ai dit des avions vides. De cette façon, si un emplacement est débordé ou si des colis sont laissés pour compte parce qu'un avion régulièrement programmé était plein, un avion vide est redirigé (juste à temps, il faut le dire) vers le point problématique. À tout moment, FedEx a des "pièces de rechange dans l'air" !
Si vous êtes un gestionnaire, considérez cela la prochaine fois lors de la planification de la maximisation de l'utilisation.
Sommes-nous satisfaits de la mise à jour ? Oui, ça a l'air mieux que ce que nous avons maintenant.
Peut-on faire mieux ? Oui nous pouvons.
L'objectif est d'éliminer la revue de code à un moment où nous pouvons garantir que toute la qualité nécessaire est déjà dans le code. Pour y parvenir, nous devons créer un cadre décisionnel auxiliaire pour aider les développeurs à appliquer ce qui est considéré comme une bonne pratique et à éviter la mauvaise. Je n'ai jamais entendu parler d'un tel framework, mais les linters in-IDE sont un pas vers cela.
Merci pour la lecture! Écrivez un commentaire si vous souhaitez discuter des idées décrites.