À propos de la vie dans un monde où les exigences évoluent et les avantages des petites fonctionnalités

Depuis plus d'un an maintenant, dans MyStore, nous créons des fonctionnalités qui aident nos utilisateurs à acheter et vendre des produits étiquetés. L'actualité de l'étiquetage a glissé à plusieurs reprises sur Habré, si brièvement: depuis 2019, les marchandises sont marquées nécessairement. Pas tout à la fois, mais maintenant vous devez étiqueter les cigarettes, les chaussures, les parfums et les pneus de voiture. Dans le même temps, nous travaillons dans une situation d'incertitude lorsque l'API des systèmes gouvernementaux est en constante évolution.


Par conséquent, nous n'avons que deux façons de nous intégrer aux agences gouvernementales: attendre que tout se calme et manquer le leadership du marché ou développer un système dans un monde où les exigences évoluent.


Nous avons choisi la seconde - juste dans l'esprit des méthodologies flexibles. Je pense qu'Agile peut vraiment aider à résoudre des problèmes appliqués. Et la vie dans un monde de demandes en constante évolution est le domaine dans lequel vous pouvez vous tourner.



Je m'appelle Maxim Sukharenko, je suis chef d'équipe de la plateforme de service MySklad. Et aujourd'hui, je vais vous dire comment nous travaillons avec des exigences changeantes.


Du classique à la mêlée


La date limite initiale pour le développement du système par les autorités réglementaires était prévue pour avril 2019, mais vous comprenez tout. En conséquence, les délais ont été reportés à octobre. Et là où il y a de nouveaux délais, il y a de nouvelles exigences et de nouveaux formats. Nous ne pouvions pas attendre la correction de l'API - alors nous n'aurions pas le temps de mettre en œuvre l'intégration. Par conséquent, ils ont décidé "d'hésiter avec la ligne du parti".


Nous avons pensé à l'approche classique qui nous propose de faire un adaptateur pour un système externe. Complétez-le avec une prise avec un interrupteur et tirez de temps en temps la fonctionnalité de la prise et de l'adaptateur à l'état actuel du système externe.



La logique suggère que pour développer un système avec une interface en constante évolution, vous devez fixer les exigences à un moment donné. Mais seulement sur quoi? Jusqu'à ce que nous développions une partie de la fonctionnalité?


Vous devez admettre qu'il est désagréable de laisser des fonctionnalités inachevées sur lesquelles les tests ne passent pas, et également commencer à les casser sur un nouveau. Vous pouvez fixer les exigences pour la période de développement des fonctionnalités. Mais que faire des grandes fonctionnalités qui peuvent vivre en développement pendant plusieurs mois? Il est tout simplement impossible de fixer des exigences pour une période aussi longue.


Nous nous sommes donc tournés vers Scrum. Il nous dit qu'à la fin du sprint, nous devons fournir un produit fonctionnel avec de nouvelles fonctionnalités. Mais comment cela fonctionne-t-il avec les exigences de fixation et les grandes fonctionnalités? Il y a une bonne blague à ce sujet:


"Docteur, quand je le fais comme ça, ça me fait mal."
"Et tu ne le fais pas comme ça."


Qui ne comprend pas, ne fait pas de gros traits . Vous pouvez fixer les exigences pour une ou deux semaines afin de coïncider avec le sprint, et définir la mise en œuvre de la fonction en fonction des exigences du sprint. Et la fonctionnalité doit être battue en de telles pièces pour qu'elles s'insèrent dans un ou deux sprints. Vous pensez trop délicat? Et puis! Vous ne savez tout simplement pas comment couper les billets. Saw, Shura, saw, ils sont dorés.


Bien sûr, ce n'est pas si simple, nous devons avancer délibérément vers cela - afin de laisser le développement de "nous le ferons pendant six mois, puis nous déploierons une nouvelle version pour le test".


Le secret est d'avoir une version stable à la fin de chaque sprint . Bien sûr, il peut sembler que cela augmentera le temps de développement en raison de la croissance des frais généraux pour la stabilisation de la branche et que le développement sera sous-optimal. Mais ici, la situation est presque la même qu'avec les tests, parlons-en ci-dessous.


Pour combattre les missions


Et maintenant pour des situations réelles. Notre tâche consistait à configurer le chiffrement entre notre système et l'API afin que l'utilisateur signe toutes les demandes avec une clé. Je pense que beaucoup d'entre vous ont rencontré CryptoPro, nous avons donc dû le faire.


Si vous utilisez l'approche standard, une tâche isolée sera formée - la configuration de la cryptographie pour le service. Nous allons l'accrocher à une seule personne et pendant un mois, nous supprimerons le statut et ne comprendrons pas pourquoi cela ne se terminera en aucune façon. Et le développeur deviendra progressivement une créature sauvage de l'autre monde, avec de la mousse dans la bouche et des yeux sauvages.


Nous l'avons découpé en petites tâches et dispersé dans toute l'équipe. Je compare la cryptographie à l'alcool: en entreprise et à dose modérée, c'est beaucoup mieux que beaucoup et seul.
Comme nous développons un service cloud, il nous a été plus facile d'utiliser le plug-in CryptoPro EDS Browser (ce n'est pas de la publicité, c'est du désespoir). Il permet à CryptoPro CSP d'étendre les clés et les méthodes de cryptage à une page Web.


Tout d'abord, l'utilisateur choisit la clé qu'il utilisera pour travailler avec le service, puis l'authentification a lieu pour obtenir un jeton. Et ce n'est qu'alors qu'avec l'aide du chiffrement et des appels d'API de jeton sont effectués. Il semble que tout soit simple (non).


Tout d'abord, nous avons fait MVP indépendamment de notre service - pour configurer l'interaction du plugin avec l'API. Savez-vous combien de documentation le plugin du navigateur cryptoPro contient? Pas du tout! Seuls des exemples d'ingénierie inverse, uniquement hardcore. Nuits sans sommeil et tente de déterminer l'influence de ces paramètres ou d'autres.


Et c'est seulement alors que nous avons pu essayer de l'intégrer dans notre écosystème. Une personne apporte l'apparence du composant prototype sous une forme humaine, la seconde le connecte à la logique métier, la troisième écrit des instructions à la postérité pour le configurer. Chaque tâche a un objectif spécifique et est relativement isolée des autres. Et les gens ont quelque chose à discuter et avec qui partager la douleur.


La situation est donc devenue assez stable. En petites itérations, nous ajoutons de nouvelles fonctionnalités, de temps en temps nous mettons à jour l'interface externe et diffusons les changements profondément dans notre système. Mais la question se pose: vivre dans une branche distincte jusqu'à la dernière, ou essayer de garder constamment de petites fonctionnalités dans le maître?


Tester la fonctionnalité


Je propose de comprendre quoi faire avec les tests et quoi faire si nous ajoutons l'intégration à un projet en direct.


Commençons par les tests. Pour commencer, nous déterminerons ce que nous pouvons appeler la fonctionnalité testée. Je propose de nommer la fonctionnelle qui a réussi les tests d'acceptation, y compris ceux de régression. Nous convenons seulement que nous ne recourrons pas au piratage de la vie "pas de tests - cela signifie que tout est testé". Nous devons conserver notre code dans le produit, et plus il y a de couverture de test, mieux c'est. Plus le pourcentage d'automatisation de ces tests est élevé, moins chaque itération de test de la fonctionnalité est coûteuse et plus elle peut être effectuée.


Nous avons un certain ensemble de tests d'acceptation et de régression, certains d'entre eux sont automatisés, certains sont tenus à la main.


Si nous nous approchons formellement, nous devons effectuer des tests après chaque changement de code. Par exemple, ils ont divisé votre fonctionnalité en six tickets et ont trouvé dix erreurs au cours du processus de test. Et laissez chaque test prendre quatre heures: l'automatique ne compte pas, mais le manuel ne prend que quatre heures. Il s'avère qu'avec la méthode de travail de base et formelle, nous passerons 64 heures.
Essayons maintenant de tester non pas après chaque changement de code, mais après un. La logique suggère que nous ne passons que 32 heures. Et si vous effectuez des tests uniquement après avoir développé la fonctionnalité et après avoir corrigé tous les défauts. Mais à condition que tous les défauts soient isolés les uns des autres, ce qui ne se produit pas dans la vie.


Dans la vie, il s'avère qu'après le développement de la fonctionnalité, des tests sont effectués et la première vague de bugs est effectuée. Ensuite, les bugs sont réparés, la fonctionnalité est cassée, ils sont testés par le bug bug. Ils effectuent un deuxième test global et une nouvelle vague de bugs apparaît. Ces bogues ont été cachés et sont apparus lorsqu'ils ont corrigé la première vague et changé la fonctionnalité. Et donc plusieurs fois.


Habituellement, vous obtenez trois à cinq séries complètes de tests - en fonction de la complexité de la fonctionnalité et de la directivité des mains. Mais le processus peut être accéléré encore plus - si vous battez sur de petites fonctionnalités.


Par exemple, si vous cassez une fonctionnalité avec des tests à quatre heures en deux avec des tests à trois heures et demie et demie, vous obtenez cinq heures au lieu de quatre. Il ne semble y avoir aucun profit. Mais il se manifeste par une diminution de la complexité de la fonctionnalité libérée et une diminution de la probabilité de chaînes de défauts associés. En conséquence, les itérations de tests complets deviennent moins nombreuses.



Ajouter au projet


Nous allons maintenant analyser la situation lorsque vous créez une fonctionnalité dans un projet sur lequel les développeurs travaillent toujours. Supposons que nous utilisons le concept de code source relativement standard Branch Per Feature (Branch Per Ticket).


De toute évidence, le montant des coûts pour maintenir la pertinence du brunch est proportionnel à sa durée de vie. Moins il y a d'intersections de code dans les tickets actuels, moins il y a de problèmes lors de leur fusion. Cela dépend indirectement de la durée de vie: plus le temps s'est écoulé, plus les chances que les tickets associés apparaissent apparaissent. En conséquence, moins le brunch vit, moins d'efforts sont consacrés à sa pertinence.


Il reste à comprendre comment déployer des fonctionnalités partiellement fonctionnelles sur le prod. La réponse est assez simple: elle ne doit pas être accessible à l'utilisateur. Si vous voulez demander pourquoi vous devriez le faire, vous pouvez retourner quelques paragraphes ci-dessus.


Il semble que conserver le code mort dans l'assistant n'est pas très bon. C'est vrai, mais il n'est pas mort. Vous pouvez créer une page secrète avec des stylos qui comprendra une telle fonctionnalité. Ou une séquence spéciale d'actions, qui, comme les œufs de Pâques dans les jeux, vous amènera à cette fonctionnalité. De plus, vous pouvez le tester immédiatement.


Bien sûr, il existe d'autres façons de gérer la variabilité des exigences. Et cette approche a ses limites et ses conditions d'utilisation. Comme vous le savez, il n'y a toujours pas de solution miracle.

Source: https://habr.com/ru/post/fr460883/


All Articles