N'acceptez pas de développer quelque chose que vous ne comprenez pas

N'acceptez pas de développer quelque chose que vous ne comprenez pas

Depuis début 2018, j'occupe le poste de lead/boss/lead développeur dans l'équipe - appelez ça comme vous voulez, mais le fait est que je suis entièrement responsable d'un des modules et de tous les développeurs qui travaillent dessus. Ce poste m'offre une nouvelle perspective sur le processus de développement, car je suis impliqué dans davantage de projets et plus activement impliqué dans la prise de décision. Récemment, grâce à ces deux choses, j'ai soudain réalisé à quel point la mesure de la compréhension affecte le code et l'application.

Ce que je veux souligner, c'est que la qualité du code (et du produit final) est étroitement liée au degré de conscience des personnes qui conçoivent et écrivent le code de ce qu'elles font.

Vous pensez peut-être en ce moment : « Merci, Cap. Bien sûr, ce serait bien de comprendre ce que vous écrivez en général. Sinon, vous pourriez tout aussi bien embaucher un groupe de singes pour appuyer sur des touches arbitraires et en rester là. Et vous avez tout à fait raison. En conséquence, je considère comme acquis que vous réalisez qu'il est nécessaire d'avoir une idée générale de ce que vous faites. C’est ce que l’on peut appeler le niveau zéro de compréhension, et nous ne l’analyserons pas en détail. Nous examinerons en détail ce que vous devez comprendre exactement et comment cela affecte les décisions que vous prenez chaque jour. Si j'avais su ces choses à l'avance, cela m'aurait épargné beaucoup de temps perdu et de code douteux.

Même si vous ne verrez pas une seule ligne de code ci-dessous, je crois toujours que tout ce qui est dit ici est d'une grande importance pour écrire du code expressif de haute qualité.

Premier niveau de compréhension : Pourquoi ça ne marche pas ?

Les développeurs atteignent généralement ce niveau très tôt dans leur carrière, parfois même sans l'aide des autres - du moins d'après mon expérience. Imaginez que vous receviez un rapport de bug : une fonction de l'application ne fonctionne pas, elle doit être corrigée. Comment allez-vous procéder ?

Le schéma standard ressemble à ceci :

  1. Recherchez le morceau de code à l'origine du problème (comment procéder est un sujet distinct, j'en parle dans mon livre sur le code existant)
  2. Apporter des modifications à cet extrait
  3. Assurez-vous que le bug est corrigé et qu'aucune erreur de régression ne s'est produite

Concentrons-nous maintenant sur le deuxième point : apporter des modifications au code. Il existe deux approches pour ce processus. La première consiste à approfondir ce qui se passe exactement dans le code actuel, à identifier l'erreur et à la corriger. Deuxièmement : déplacez-vous au ressenti - ajoutez, disons, +1 à une instruction conditionnelle ou une boucle, voyez si la fonction fonctionne dans le scénario souhaité, puis essayez autre chose, et ainsi de suite à l'infini.

La première approche est correcte. Comme l'explique Steve McConnell dans son livre Code Complete (que je recommande vivement d'ailleurs), chaque fois que nous modifions quelque chose dans le code, nous devrions être en mesure de prédire avec certitude comment cela affectera l'application. Je cite de mémoire, mais si une correction de bug ne fonctionne pas comme vous l'espériez, vous devriez être très alarmé et remettre en question l'ensemble de votre plan d'action.

Pour résumer ce qui a été dit, afin d'effectuer une bonne correction de bug qui ne dégrade pas la qualité du code, vous devez comprendre à la fois la structure entière du code et la source du problème spécifique.

Deuxième niveau de compréhension : Pourquoi ça marche ?

Ce niveau est appréhendé beaucoup moins intuitivement que le précédent. Alors qu'il était encore développeur novice, je l'ai appris grâce à mon patron, puis j'ai expliqué à plusieurs reprises l'essence du problème aux nouveaux arrivants.

Cette fois, imaginons que vous receviez deux rapports de bugs à la fois : le premier concerne le scénario A, le second concerne le scénario B. Dans les deux scénarios, quelque chose de mal se produit. En conséquence, vous vous attaquez en premier au premier bug. En utilisant les principes que nous avons développés pour la compréhension du niveau XNUMX, vous approfondirez le code pertinent au problème, comprendrez pourquoi il amène l'application à se comporter comme elle le fait dans le scénario A et effectuerez des ajustements raisonnables qui produiront le résultat souhaité. . Tout va très bien.

Ensuite, vous passez au scénario B. Vous répétez le scénario pour tenter de provoquer une erreur, mais… surprise ! — maintenant tout fonctionne comme il se doit. Pour confirmer votre supposition, vous annulez les modifications que vous avez apportées en travaillant sur le bug A, et le bug B réapparaît. Votre correction de bug a résolu les deux problèmes. Chanceux!

Vous ne comptiez pas du tout là-dessus. Vous avez trouvé un moyen de corriger l'erreur dans le scénario A et vous ne savez pas pourquoi cela a fonctionné pour le scénario B. À ce stade, il est très tentant de penser que les deux tâches ont été accomplies avec succès. C’est assez logique : il s’agissait d’éliminer les erreurs, n’est-ce pas ? Mais le travail n'est pas encore terminé : il vous reste à comprendre pourquoi vos actions ont corrigé l'erreur du scénario B. Pourquoi ? Parce que cela fonctionne peut-être sur de mauvais principes, et vous devrez alors chercher une autre issue. Voici quelques exemples de tels cas :

  • Étant donné que la solution n'a pas été adaptée à l'erreur B, en tenant compte de tous les facteurs, vous avez peut-être interrompu la fonction C sans le savoir.
  • Il est possible qu'il y ait aussi un troisième bug qui se cache quelque part, lié à la même fonction, et votre correction de bug en dépend pour le bon fonctionnement du système dans le scénario B. Tout semble bien maintenant, mais un jour ce troisième bug sera remarqué et corrigé. Ensuite, dans le scénario B, l’erreur se reproduira, et c’est bien si seulement là.

Tout cela ajoute du chaos au code et vous tombera un jour sur la tête - probablement au moment le plus inopportun. Vous devrez rassembler votre volonté pour vous forcer à passer du temps à comprendre pourquoi tout semble fonctionner, mais cela en vaut la peine.

Troisième niveau de compréhension : Pourquoi ça marche ?

Ma réflexion récente porte précisément sur ce niveau, et c'est probablement celui qui m'aurait apporté le plus de bénéfice si j'avais eu cette idée plus tôt.

Pour être plus clair, regardons un exemple : votre module doit être rendu compatible avec la fonction X. Vous n'êtes pas particulièrement familier avec la fonction X, mais on vous a dit que pour être compatible avec elle il fallait utiliser le framework F. Autre les modules qui s'intègrent à X fonctionnent exactement avec lui.

Votre code n'a pas du tout été en contact avec le framework F depuis le premier jour de sa vie, son implémentation ne sera donc pas si simple. Cela aura de graves conséquences sur certaines parties du module. Cependant, vous vous lancez dans le développement : vous passez des semaines à écrire du code, à tester, à déployer des versions pilotes, à obtenir des commentaires, à corriger des erreurs de régression, à découvrir des complications imprévues, à ne pas respecter les délais initialement convenus, à écrire du code supplémentaire, à tester, à obtenir des commentaires, corriger les erreurs de régression - tout cela afin de mettre en œuvre le framework F.

Et à un moment donné, vous réalisez soudainement - ou peut-être entendez-vous parler de quelqu'un - que peut-être que le framework F ne vous offrira pas du tout de compatibilité avec la fonctionnalité X. Peut-être que tout ce temps et tous ces efforts ont été complètement mal consacrés à cela.

Quelque chose de similaire s'est produit une fois alors que je travaillais sur un projet dont j'étais responsable. Pourquoi est-ce arrivé? Parce que je ne comprenais pas vraiment ce qu'était la fonction X et comment elle était liée au framework F. Qu'aurais-je dû faire ? Demandez à la personne qui assigne la tâche de développement d'expliquer clairement comment le plan d'action prévu mène au résultat souhaité, plutôt que de simplement répéter ce qui a été fait pour d'autres modules ou de lui croire sur parole que c'est ce que la fonctionnalité X doit faire.

L'expérience de ce projet m'a appris à refuser de commencer le processus de développement tant que nous n'avons pas compris clairement pourquoi on nous demande de faire certaines choses. Refusez catégoriquement. Lorsque l’on reçoit une tâche, le premier réflexe est de s’en charger immédiatement pour ne pas perdre de temps. Mais la politique consistant à « geler le projet jusqu'à ce que nous entrions dans tous les détails » peut réduire les pertes de temps de plusieurs ordres de grandeur.

Même s'ils essaient de vous faire pression, de vous forcer à commencer à travailler, même si vous n'en comprenez pas la raison, résistez. Tout d’abord, déterminez pourquoi une telle tâche vous est confiée et décidez si c’est la bonne voie vers l’objectif. J'ai dû apprendre tout cela à mes dépens - j'espère que mon exemple facilitera la vie de ceux qui liront ceci.

Quatrième niveau de compréhension : ???

Il y a toujours plus à apprendre en programmation, et je crois n'avoir fait qu'effleurer la surface du sujet de la compréhension. Quels autres niveaux de compréhension avez-vous découverts au fil des années de travail avec le code ? Quelles décisions avez-vous prises qui ont eu un impact positif sur la qualité du code et de l'application ? Quelles décisions se sont avérées erronées et vous ont appris une leçon précieuse ? Partagez votre expérience dans les commentaires.

Source: habr.com

Ajouter un commentaire