
Comment se déroule généralement une révision de code? Vous envoyez une demande de pool, obtenez des commentaires, apportez des corrections, envoyez des correctifs pour un deuxiÚme examen, puis obtenez l'approbation et la fusion se produit. Cela semble simple, mais en réalité, le processus d'examen peut prendre beaucoup de temps.
Imaginez que vous ayez une demande de pool avec des centaines de lignes de changement. Le rĂ©viseur doit consacrer beaucoup de temps Ă lire entiĂšrement le code et Ă comprendre les modifications proposĂ©es. Par consĂ©quent, l'ensemble du processus, de la crĂ©ation d'une demande de pool Ă son approbation, peut prendre plusieurs jours - ce qui n'est pas trĂšs agrĂ©able pour le rĂ©viseur et l'auteur des modifications. Et les chances sont bonnes qu'en fin de compte, le critique manque encore quelque chose. Ou le contrĂŽle peut ĂȘtre trop superficiel et, dans le pire des cas, la demande de pool peut ĂȘtre rejetĂ©e immĂ©diatement.
Il s'avÚre que plus la demande de pool est grande, moins il sera avantageux de la vérifier.
Comment éviter de telles situations? Comment rendre la demande de pool plus facile et plus compréhensible pour le réviseur et optimiser l'ensemble du processus?
Nous traduisons un article de notre développeur principal Sergey Zhuk sur le fonctionnement du processus de révision du code de l'équipe de l'application mobile Skyeng.
Modifier les catégories
Imaginons que vous ayez une tĂąche: implĂ©menter de nouvelles fonctionnalitĂ©s dans le projet. La demande de pool sur laquelle vous travaillez peut contenir diffĂ©rentes catĂ©gories de modifications. Bien sĂ»r, il y aura du nouveau code dedans. Mais au cours du travail, vous remarquerez peut-ĂȘtre que certains codes doivent ĂȘtre refactorisĂ©s au prĂ©alable afin de contribuer Ă l'ajout de nouvelles fonctionnalitĂ©s. Ou avec cette nouvelle fonctionnalitĂ©, la duplication est apparue dans le code que vous souhaitez Ă©liminer. Ou vous avez soudainement trouvĂ© une erreur et souhaitez la corriger. Ă quoi devrait ressembler la demande de pool finale?
Voyons d'abord quelles catégories de modifications peuvent se produire avec le code.
- Changements fonctionnels.
- Refactoring structurel - changements de classes, interfaces, méthodes, mouvement entre classes.
- Refactorisation simple - peut ĂȘtre effectuĂ©e Ă l'aide de l'EDI (par exemple, extraction de variables / mĂ©thodes / constantes, simplification des conditions).
- Renommer et déplacer des classes - réorganiser l'espace de noms.
- Suppression du code inutilisé (mort).
- Corrections de style de code.
Examen de la stratégie
Il est trÚs important de comprendre que chacune de ces catégories est examinée différemment et lorsque vous les examinez, l'examinateur doit se concentrer sur des choses différentes. On peut dire que chaque catégorie de changement implique sa propre stratégie d'examen.
- Changement fonctionnel: résolution de problÚmes commerciaux et conception de systÚmes.
- Refactoring structurel: rétrocompatibilité et amélioration de la conception.
- Refactoring primitif: lisibilitĂ© amĂ©liorĂ©e. Ces modifications peuvent ĂȘtre principalement effectuĂ©es Ă l'aide de l'EDI (par exemple, extraire des variables / mĂ©thodes / constantes, etc.).
- Renommer / déplacer des classes: la structure de l' espace de noms s'est-elle améliorée?
- Suppression du code inutilisé: rétrocompatible.
- Corrections de style de code: le plus souvent, la demande de fusion de pool se produit immédiatement.
Différentes approches sont utilisées pour vérifier les changements dans différentes catégories, par conséquent, le temps et les efforts consacrés à leur examen varient également.
Changements fonctionnels. Il s'agit du processus le plus long car il implique de modifier la logique du domaine. Le rĂ©viseur cherche Ă voir si le problĂšme est rĂ©solu et vĂ©rifie si la solution proposĂ©e est la plus appropriĂ©e ou peut ĂȘtre amĂ©liorĂ©e.
Refactoring structurel. Ce processus nécessite beaucoup moins de temps que les changements fonctionnels. Mais il peut y avoir des suggestions et des désaccords sur l'organisation exacte du code.
Lors de la vérification des catégories restantes dans 99% des cas, la fusion se produit immédiatement.
- Refactoring simple. Le code est-il devenu plus lisible? - merzhim.
- Renommer / déplacer des classes. La classe a-t-elle été déplacée vers un meilleur espace de noms? - Merzh.
- La suppression du code inutilisé (mort) est merzhim.
- Corrections du style de code ou de la mise en forme - merzh. Vos collÚgues ne devraient pas vérifier cela pendant la révision du code, c'est la tùche du linter.
Pourquoi les changements devraient-ils ĂȘtre classĂ©s?
Nous avons dĂ©jĂ expliquĂ© que diffĂ©rentes catĂ©gories de changements sont rĂ©visĂ©es diffĂ©remment. Par exemple, nous vĂ©rifions les changements fonctionnels en fonction des besoins de l'entreprise, et dans le refactoring structurel, nous vĂ©rifions la compatibilitĂ© descendante. Et si nous mĂ©langeons plusieurs catĂ©gories, il sera difficile pour le rĂ©viseur de garder Ă l'esprit plusieurs stratĂ©gies de rĂ©vision en mĂȘme temps. Et, trĂšs probablement, le rĂ©viseur passera plus de temps sur la demande de pool que nĂ©cessaire, et Ă cause de cela, il peut manquer quelque chose. De plus, si la demande de pool contient diffĂ©rents types de changements, avec toute correction, le rĂ©viseur devra rĂ©viser Ă nouveau toutes ces catĂ©gories. Par exemple, vous avez mĂ©langĂ© le refactoring structurel et les changements fonctionnels. MĂȘme si le refactoring est bien effectuĂ©, mais qu'il y a un problĂšme avec la mise en Ćuvre de la fonctionnalitĂ©, aprĂšs les corrections, le rĂ©viseur devra examiner la demande de pool entiĂšre dĂšs le dĂ©but. Autrement dit, revĂ©rifiez Ă la fois le refactoring et les modifications fonctionnelles. Le rĂ©viseur passe donc plus de temps sur la demande de pool. Au lieu d'envisager immĂ©diatement une demande de pool sĂ©parĂ©e avec refactoring, le rĂ©viseur devrait Ă nouveau revoir le code entier.
Ce qui ne vaut pas la peine d'ĂȘtre mĂ©langĂ©
Renommer / supprimer une classe et sa refactorisation. Nous rencontrons ici Git, qui ne comprend pas toujours correctement ces changements. Je veux dire des changements à grande échelle lorsque de nombreuses lignes changent. Lorsque vous refactorisez une classe et que vous la déplacez quelque part, Git ne la perçoit pas comme se déplaçant. Au lieu de cela, Git interprÚte ces changements comme supprimant une classe et en créant une autre. Cela conduit à un tas de questions lors de la révision du code. Et on demande à l'auteur du code pourquoi il a écrit ce code laid, bien qu'en fait ce code ait été simplement déplacé d'un endroit à un autre avec des changements mineurs.
Tout changement fonctionnel + tout refactoring. Nous avons dĂ©jĂ discutĂ© de ce cas ci-dessus. Cela permet au rĂ©viseur de garder Ă l'esprit deux stratĂ©gies de rĂ©vision Ă la fois. MĂȘme si le refactoring est bien fait, nous ne pourrons pas retarder ces modifications tant que les modifications fonctionnelles ne seront pas approuvĂ©es.
Toute modification mĂ©canique + toute modification apportĂ©e par l'homme. Par «changements mĂ©caniques», j'entends tout formatage effectuĂ© Ă l'aide de l'IDE ou de la gĂ©nĂ©ration de code. Par exemple, nous appliquons le nouveau style de code et obtenons 3000 modifications de ligne. Et si nous mĂ©langeons ces modifications avec toute modification fonctionnelle ou toute autre modification apportĂ©e par une personne, nous obligerons le rĂ©viseur Ă classer mentalement ces modifications et la raison: il s'agit d'une modification effectuĂ©e par un ordinateur - elle peut ĂȘtre ignorĂ©e, et cette modification apportĂ©e par une personne est nĂ©cessaire vĂ©rifier. L'Ă©valuateur passe donc beaucoup de temps Ă vĂ©rifier.
Exemple
Voici une demande de pool avec une fonction de méthode qui ferme doucement la connexion client à Memcached:

MĂȘme si la demande de pool est petite et ne contient qu'une centaine de lignes de code, elle est toujours difficile Ă vĂ©rifier. Comme vous pouvez le voir dans les commits, il contient diffĂ©rentes catĂ©gories de modifications:
- fonctionnel (nouveau code),
- refactoring (création / déplacement de classes),
- corrections de style de code (suppression des blocs de quai en excĂšs).
En mĂȘme temps, la nouvelle fonctionnalitĂ© elle-mĂȘme n'est que de 10 lignes:

Par conséquent, le réviseur doit revoir l'intégralité du code et
- Vérifiez que le refactoring est OK.
- vérifier si la nouvelle fonctionnalité est correctement implémentée;
- déterminer si cette modification a été générée automatiquement par l'IDE ou par la personne.
Par conséquent, une telle demande de pool est difficile à examiner. Pour corriger la situation, vous pouvez diviser ces validations en branches distinctes et créer un pool de demandes pour chacune d'entre elles.
1. Refactoring: extraction de classe

Il n'y a que deux fichiers. Le réviseur ne doit vérifier que le nouveau design. Si tout est en ordre - merzhim.
2. L'étape suivante consiste également à refactoriser, nous déplaçons simplement les deux classes vers un nouvel espace de noms

Une telle demande de pool est assez simple Ă vĂ©rifier, elle peut ĂȘtre instanciĂ©e immĂ©diatement.
3. Retrait des blocs de quai en excĂšs

Rien d'intéressant ici. Merzhim.
4. La fonctionnelle elle-mĂȘme

Et maintenant, la demande de pool avec des modifications fonctionnelles ne contient que le code souhaité. Votre réviseur ne peut donc se concentrer que sur cette tùche. La demande de piscine est petite et facile à vérifier.
Conclusion
RÚgle générale:Ne créez pas d'énormes demandes de pool avec des catégories mixtes de modifications.
Plus la demande de pool est grande, plus il est difficile pour le rĂ©viseur de comprendre les changements que vous avez proposĂ©s. TrĂšs probablement, une Ă©norme demande de pool avec des centaines de lignes de code sera rejetĂ©e. Au lieu de cela, divisez-le en petites parties logiques. Si votre refactoring est en ordre, mais que les modifications fonctionnelles contiennent des erreurs, le refactoring peut ĂȘtre facilement retenu, et vous et votre rĂ©viseur pouvez donc vous concentrer sur la fonctionnalitĂ© sans regarder tout le code depuis le tout dĂ©but.
Et suivez toujours ces étapes avant d'envoyer la demande de pool:
- Optimisez votre code pour la lecture. Le code est beaucoup plus lisible qu'écrit;
- Décrire les changements proposés afin de fournir le contexte nécessaire à leur compréhension;
- vérifiez toujours votre code avant de créer une demande de pool. Et faites-le comme si c'était le code de quelqu'un d'autre. Parfois, il est utile de trouver quelque chose que vous avez manqué. Cela réduira la probabilité de rejet de votre demande de pool et le nombre de corrections.
Mon collĂšgue
Oleg Antonevich m'a parlé de l'idée de
diviser les changements en catégories.
De l'éditeur: Sergey écrit beaucoup de choses intéressantes sur la programmation et PHP, et parfois nous traduisons quelque chose: un serveur vidéo en streaming , rendant des fichiers HTML . N'hésitez pas à lui poser des questions dans les commentaires de cet article - il vous répondra!
Eh bien, rappelez-vous également que nous avons toujours beaucoup de postes vacants intéressants pour les développeurs!