Chemin du développeur

salut! Je m'appelle Alexey Skorobogaty. En 2015, j'ai rejoint Lamoda en tant que développeur. Maintenant, je suis architecte système d'une plateforme de commerce électronique et également responsable technique de l'équipe CORE. Dans cet article, je souhaite partager les idées que j'ai reçues au cours de ces 5 années - au format à emporter, avec des histoires, des mèmes et des liens vers la littérature.



image



Je serais heureux d'avoir toute discussion dans les commentaires sous l'article: questions, opinions, réfutations!



Il y a des connus



Chez Lamoda, j'ai rejoint l'équipe travaillant sur le support et le développement du système de traitement des commandes. Rien n'est clair, mais terriblement intéressant.



Après un studio web petit mais ambitieux où j'ai travaillé auparavant, j'ai été impressionné par le sens du sérieux au sein d'une grande entreprise. Les processus de développement arrangés semblaient être un mécanisme parfaitement poli. Des revues de code rigoureuses mais encadrées par le leader et les membres de l'équipe sont essentielles pour un système aussi complexe et clé. Pour moi, les tâches ponctuelles volaient, affectant littéralement un ou deux fichiers, pas plus. La plupart du code de base et du comportement du système m'ont été cachés par le brouillard de la guerre.



Après environ un mois, j'ai terminé l'une des premières tâches liées à la réalisation de véritables changements dans un système opérationnel. Son essence se résumait à l'ajout d'un champ au rapport sur le retour des fonds au client. Revue de code, tests unitaires, ingénieur QA testant la version - tout semblait correct. Le système étant vaste et complexe, nous avons été libérés deux fois par semaine, conformément aux règlements - et jeudi, ma tâche est passée à la production. La majeure partie de la journée, l'ingénieur de publication était occupé à construire et à déployer le code, suivi d'un basculement compulsif entre les onglets avec des graphiques de surveillance, des erreurs, des files d'attente, des journaux - tout ce qui pouvait indiquer un problème. Mais tout avait l'air super. Le code a été fusionné dans la branche principale et dispersé pour traiter d'autres tâches.



Le silence dans les logs et la surveillance cache un terrible bug: la requête de base de données a renvoyé un nombre incorrect de lignes. Le montant total à restituer était plusieurs fois supérieur au montant réel ... Mais nous ne l'avons appris que lundi. Je me souviens encore à quel point le responsable technique m'a regardé fatigué et reproché alors que nous prenions l'ascenseur du bureau le lendemain matin. Il a attrapé le bogue jusqu'à trois heures du matin et a préparé un correctif pour la publication. Et l'entreprise a souffert de mon erreur. C'était mon premier bug critique, mais loin d'être le dernier. Les gens font des erreurs, et ils le font tout le temps.



À emporter # 1:Les processus commerciaux et les données passent en premier. Il est important de porter une attention particulière aux données avec lesquelles le système fonctionne. Déterminez ce à quoi vous avez affaire avant d'apporter des modifications. Comprenez le contexte dans lequel les ajustements sont effectués. Considérez toujours le problème résolu du point de vue du contexte au-dessus du niveau. En d'autres termes, comprenez clairement ce qui se passe en termes de processus métier et qui est le consommateur des modèles concernés. La structure d'une application peut avoir autant de couches d'abstraction que vous le souhaitez et divers degrés de qualité des abstractions elles-mêmes, mais cela ne signifie rien du tout si le modèle ou le processus métier dans son ensemble est rompu.



J'ai continué à travailler dans la même équipe, j'ai acquis de l'expérience, et six mois plus tard, au stand-up de l'équipe, j'ai lancé une phrase disant qu'en général je comprenais comment fonctionne notre système de traitement des commandes.



Bien sûr, j'avais tort.



La complexité des grands systèmes ne doit jamais être sous-estimée. Le politicien américain Donald Rumsfeld a très bien dit à ce sujet:

image... comme nous le savons, il existe des célèbres connus; Il y a des choses que nous savons, que nous les connaissons. Nous savons également qu'il existe des inconnues connues; c'est-à-dire que nous savons qu'il y a des choses que nous ne savons pas. Mais il y a aussi des inconnues inconnues - celles que nous ne connaissons pas, que nous ne connaissons pas. Et si vous regardez l'histoire de notre pays et d'autres pays libres, la dernière catégorie est généralement difficile.



À retenir n ° 2: lorsque vous travaillez avec des systèmes complexes, il est important de comprendre ce que nous savons d’eux, ce que nous ne savons pas et ce que leur comportement n’est même pas deviner. Et il ne s'agit pas seulement de la boîte à outils et du suivi de la tendance «Suivi vers l'observabilité» , mais aussi de la gestion des dépendances et de l'évaluation des risques dans la conception. Par exemple, avant de décider d'utiliser une base de données de tendances cool pour un système critique, je vous conseille vivement de vous en tenir à ce site boringtechnology.club



Tout est cassé



Après deux ans de travail avec le système de traitement des commandes, je pourrais dire que je connais environ 80% de l'application en toute confiance. Autrement dit, à propos de chaque module du système, je comprends son fonctionnement et je peux apporter des modifications. Je sais quels processus métier se reflètent dans un modèle particulier, comment ils sont interconnectés et s’influencent mutuellement. J'ai effectué l'intégration avec le système de traitement des paiements, qui a été conçu par l'équipe voisine. En plus de l'intégration, il était nécessaire de se débarrasser de l'héritage de l'ancien code, puisque les paiements faisaient auparavant partie de notre système - cette tâche était ma dernière et la plus ambitieuse refactorisation d'un grand module. Tout s'est si bien passé que ce n'était même pas intéressant.



Au même moment, un conflit se préparait en moi, en tant que développeur. Honnêtement, je ne comprenais pas pourquoi notre système de traitement des commandes, qui est si essentiel au fonctionnement de toute notre entreprise, était si fragile. Les grands systèmes voisins étaient tout aussi fragiles. De toute l'expérience que j'ai acquise en deux ans de travail, il semblait qu'une certaine fiabilité des systèmes complexes ne pouvait être attendue que lors de l'exécution de cas testés standard. Et lorsque vous essayez d'apporter les changements dont votre entreprise a besoin, les choses s'effondrent lors de la première manœuvre drastique d'un développeur malchanceux.



En réfléchissant à tout cela, je suis tombé sur l'article Tout est cassé , dans lequel l'auteur écrit sur le même problème, mais à une échelle encore plus grande (et aussi à peu près la même, mais sous un angle différent - Désenchantement logiciel). Chaque fois que je suis excité quand je trouve de l'extérieur la confirmation de mes sentiments intérieurs - de sorte que cette fois, après avoir lu l'article, j'ai finalement ressenti comment mon vague mécontentement s'est transformé en une vision vive et évidente:

Le logiciel est si mauvais parce qu'il est si complexe.



Nous n'avons pas eu à aller loin pour un exemple dans notre travail: juste à ce moment-là, en ajoutant juste quelques pôles, nous avons complètement rompu la création d'une commande pendant un certain temps.



Nos grands et importants systèmes sont si mauvais parce qu'ils ne rentrent pas dans nos têtes! Et tous les processus métier qui sont fermés dans les systèmes ne rentrent pas dans la tête des gestionnaires et des analystes - et en général, il n'y a pas de telle personne qui comprendrait comment tout cela fonctionne ensemble.



À retenir n ° 3: Lors de la conception de systèmes, il est important de tenir compte de leur charge cognitive. Il se compose de la complexité des solutions techniques, ainsi que des modèles et des processus du domaine. Les systèmes bien conçus ont une charge cognitive élevée sur le sujet et peu de solutions techniques.Idéalement, un seul système devrait avoir une charge cognitive qu'une seule personne peut gérer.



D'accord, le problème est clair. Mais supposons que nous ayons l'opportunité de réécrire un système trop complexe et donc mauvais en le simplifiant. À quoi d'autre devez-vous faire attention? En cybernétique, il y a le théorème de Conant-Ashby:



un bon régulateur d'un système doit avoir un modèle de ce système. Bon régulateur



La signification de ce théorème est que si nous voulons contrôler un objet, nous avons besoin d'un bon modèle (précis et compréhensible) de cet objet. Et plus un objet est complexe ou moins d'informations à son sujet, plus il est difficile d'en obtenir un bon modèle - et cela affecte négativement la gestion.



Je pense que très peu de gens seraient en désaccord avec le fait que tous nos services sont des modèles. Mais que modélisons-nous? Il est très important de prêter attention aux processus métier, de modéliser non seulement l'état, mais aussi le comportement.



Fin 2017, j'ai rejoint la nouvelle équipe CORE. Cette équipe s'est formée alors spécifiquement pour mener à bien les tâches de la stratégie informatique de décomposition des systèmes monolithiques. Notre objectif principal était de couper ce système de traitement des commandes très volumineux mais fragile (voix off: alors les samouraïs ne savaient pas que ce chemin avait un début, mais pas de fin!).

C'était une nouvelle expérience pour moi. Une équipe avec des principes et une façon de penser complètement différents. Les décisions ont été prises rapidement, il y a eu des expériences et le droit de se tromper. L'équilibre est parfait: nous avons essayé et reculé là où l'impact était minime, mais nous avons prescrit chaque étape en détail pour les moments critiques.



Nous avons écrit un nouveau service pour créer des commandes à partir de zéro dans un autre langage (étant des développeurs php, nous sommes passés à golang). Nous avons évalué le premier résultat et l'avons réécrit. L'accent était mis sur la simplicité et la fiabilité. Ils ont mis le modèle de données au centre et ont construit toute l'architecture autour. Le résultat est un service fiable et résilient. Nous avons réussi à le mettre en service sans échec, en utilisant le mécanisme expérimental. Au fil du temps, le système construit a montré sa valeur plus d'une fois.



image



À emporter # 4:Tous les modèles sont faux mais certains sont utiles. La modélisation des états ne suffit pas pour construire des systèmes corrects et stables. Il faut regarder le comportement: les modes de communication, les flux d'événements, qui est responsable de telle ou telle donnée. Vous devez rechercher des relations entre les données et prêter attention aux raisons de ces relations.



Tout tourne autour du dum dum da da dum dum



Dans mon université, il y avait un cours d'analyse mathématique, qui était enseigné par un professeur agrégé et un doctorat. Elena Nikolaevna. Elle était très stricte, mais juste. Lors des tests, de temps en temps, des problèmes se posaient, pour la solution desquels il était nécessaire de «tordre» un peu les conférences - de faire un pas indépendant vers la compréhension du matériel. Et à l'examen final, que j'ai d'ailleurs réussi la deuxième fois, j'ai dû faire preuve de souplesse de réflexion et utiliser mon intuition pour résoudre le problème comme «bon». Voici la règle selon laquelle E.N. elle nous a raconté tout le cours, et que j'utilise dix ans plus tard:

Lorsque vous ne savez pas quoi faire, faites ce que vous savez.



C'est pourquoi j'étais fier de bien connaître matan. Parce que selon les normes de E.N. il ne suffit pas de connaître le matériau, mais il est également important de le comprendre, de pouvoir synthétiser quelque chose de nouveau.



À retenir n ° 5: Plus vous avancez, plus vous devez prendre de responsabilités et plus vous devez prendre de décisions. A un certain moment, la confiance absolue disparaît en tant que catégorie, mais vient à la place l'art de l'équilibre après le courage de faire un pas.



Il arrive un moment où il n'y a pas de bonne personne autour de vous qui pourrait éliminer l'incertitude existante. Vous devez évaluer vous-même les risques et prendre la responsabilité de vous-même. Prenez des décisions face à l'incertitude.



Au second semestre 2018, notre équipe a mené le projet Chèques Cadeaux. Au départ, j'étais responsable du développement dans et autour du traitement. Plus tard, à la fin de l'année, la direction technique de l'ensemble du projet m'a pris le relais avec la tâche de rétablir l'équilibre des forces après le départ d'une partie de l'équipe.



Les règles qui existaient dans la tête et l'ordre mondial du développeur éclataient aux coutures, puis se sont finalement effondrées. La responsabilité d'un projet vaste et complexe m'a fait tomber les idées idéalistes sur le monde du développement avec des concepts et un arc-en-ciel. Le monde cruel des restrictions et juste assez de solutions exigeait une compréhension et une révision de toutes les approches et règles que j'ai suivies.



image



À emporter n ° 6:Syndrome de l'imposteur. Et si je suis exposé? Bien sûr, ils exposeront si rien n'est fait. Si vous faites quelque chose d'important, vous remarquez après un certain temps qu'il n'y a personne pour vous exposer.



Divergence et convergence



Conformément à la chronologie de mon "Developer's Path", il devrait y avoir une histoire intéressante du point de vue technique sur le projet de politiques personnelles. Dans ce projet, nous avons mis en œuvre le traitement des données en temps réel et «à la volée», nous avons changé les principes mêmes de l'architecture du système, passant à l'architecture pilotée par les événements. Mais à ce sujet, j'ai déjà un rapport séparé de la conférence Highload '19 (et un article ici sur Habré). Par conséquent, je préfère vous parler des «hautes questions» de la technique et pas très de la gestion.



Lorsqu'un développeur accède au poste de senior, qui doit être lu comme «prêt à assumer ses responsabilités et à savoir prendre des décisions de manière autonome», alors l'étape classique suivante est le chef d'équipe. Un chef d'équipe est une personne qui est principalement responsable de l'équipe, c.-à-d. pour les personnes et les processus de développement. Le client ne vient pas chez le développeur, il vient vers le chef d'équipe et demande également des obligations au chef d'équipe.



Cela s'avère une chose paradoxale - dès qu'un développeur a grandi pour travailler de manière indépendante en tant qu'ingénieur, il est plongé dans une tempête appelée gestion.

Non, peut-être pour quelqu'un, ce chemin semble assez confortable, et la transition d'algorithmes et de protocoles extrêmement clairs pour l'interaction des systèmes informatiques à la coordination d'un groupe de personnes semble logique. Mais il me semble que ce n'est pas pour rien que la plupart des conversations dans les chats de profil et lors des conférences pour les chefs d'équipe tournent autour du concept de «douleur».



Quelle est la douleur d'un chef d'équipe? N'est-ce pas parce qu'un ingénieur est en charge de la gestion?! Non, pourquoi cela se produit est compréhensible - nous n'avons pas d'école de gestion technique en tant que telle, et on suppose qu'un ingénieur informatique est un surhomme qui peut tout comprendre, y compris une chose aussi «simple» que la gestion.



Mais j'ai décidé d'aller dans l'autre sens et j'ai choisi le poste de responsable technique comme prochaine étape de ma carrière. En tant qu'architecte, je travaille avec des équipes de développement, et maintenant j'entends des gars ce que j'ai moi-même dit aux managers il y a un an:

Pourquoi les exigences sont-elles si mal développées? Solutions de béquilles! Que deux semaines?! Ici, travaillez pendant un mois.



Mais ehehei, maintenant c'est ma tâche de résoudre de tels problèmes. Mais dès que vous traduisez votre réflexion dans le paradigme des coûts et des bénéfices, vous vous rendez compte que tous ces problèmes ne peuvent pas être résolus - vous avez la vie!



À retenir n ° 7: Ouverture! Les gestionnaires ne s'occupent pas de la résolution de problèmes, ils gèrent le désordre.



En tant que responsable technique, mon travail consiste à lever l'incertitude pour l'équipe de développement. Les exigences ne sont pas définies? Solutions de béquilles? L'architecture ne fournit-elle pas? Ce sont tous des signaux de fragilité et de divergence du système.



Supposons que le paramètre de tâche dans le service de création de commande ressemble à ceci: Vous

devez ajouter le champ X et le champ Y. Il est nécessaire que la valeur du champ Y 'en sortie soit égale à la valeur Z si X est 1.



Le problème réside dans l'énoncé même des besoins. L'erreur ici est que l'état du système que vous souhaitez atteindre n'est pas du tout clair. Des étapes entièrement définies dans la déclaration entraînent une incertitude pendant la mise en œuvre et l'exploitation.

Après plusieurs tâches similaires, le service de création de commande sera dans un état plutôt fragile - et des cas comme celui où nous avons ajouté quelques champs et que tout s'est cassé commenceront à se produire.



Objectif: assurer la convergence des états des systèmes, la cohérence de l'énoncé des tâches et la réduction de l'incertitude pour atteindre la stabilité.



image



Les personnes travaillant sur la ligne de représentation construisent et mettent constamment à jour leurs modèles de ce qui se trouve au-delà de la ligne. Ces activités sont essentielles à la résilience des systèmes Internet et constituent une source majeure de capacité d'adaptation. Au-dessus de la ligne, au-dessous de la ligne



L'architecte doit comprendre l'unité du système socio-technique. Être capable de coordonner les processus au-dessus de la ligne de présentation afin que les systèmes situés en dessous de la ligne de présentation répondent aux contraintes d'exactitude, de stabilité et d'adaptabilité.



image



À retenir n ° 8: Si les règles cessent de fonctionner, félicitations, vous avez atteint les conditions limites dans lesquelles le modèle actuel cesse de fonctionner. Il est temps de revoir vos idées et de trouver un nouveau modèle qui répondra aux contraintes actuelles et vous permettra de construire des processus et des règles adéquats.



Soft est simple, les gens sont durs!



Pas vraiment. C'est ce qui a été écrit dans un livre sur l'architecture. Et j'ai l'impression que plus j'avance, plus je répète souvent ce livre.



Les concepts techniques, les algorithmes et les normes sont clairs - il vous suffit de les prendre et de les comprendre de manière cohérente. Je n'essaie pas de minimiser le travail des ingénieurs - les algorithmes pour les systèmes distribués sont extrêmement complexes si vous ne construisez pas de tels systèmes quotidiennement. Mais le plus souvent, la principale difficulté à laquelle nous sommes confrontés dans le processus de travail survient lorsque nous devons comprendre pourquoi un service particulier nécessite un tel niveau d'abstraction pour le domaine. Et le problème est souvent aggravé par le fait que la personne qui a rédigé le service n'est pas là.



Les algorithmes faciles à mettre en œuvre sont plus efficaces que les algorithmes mathématiquement précis. Paxos est mathématiquement précis, mais seulement avec la description du protocole Raft, qui est plus facile à mettre en œuvre, l'application pratique des algorithmes de consensus a été développée.

La langue Golang est critiquée pour être trop limitée. Mais c'est là-dessus que sont écrits Docker, Kubernetes et de nombreux autres systèmes distribués. Un système de contraintes bien conçu sert de base à des systèmes efficaces.



Tout serait beaucoup plus facile si la technologie n'avait pas à prendre en compte le facteur humain. Mais ils doivent le faire. Tout système informatique, dans la construction et la maintenance dont plusieurs personnes sont impliquées, doit prendre en compte le facteur humain.



Et ici, les technologies émergent à l'intersection des logiciels et des personnes, conçues pour structurer le chaos et décrire des interactions complexes. Domain Driven Design, Microservices, Agile - tous créent des contraintes qui décrivent les principes et les règles d'interaction. Des structures apparaissent avec lesquelles il est clair comment travailler. Mais cela ne s'améliore pas toujours avec l'avènement de telles technologies. Assez souvent, il s'avère l'inverse - ce que l'argent ne peut pas acheter .



À retenir n ° 9: Les programmes peuvent et doivent être simples. Pour ce faire, vous devez appliquer la force à la formation d'une culture d'ingénierie. C'est elle qui détermine en fin de compte la performance des services.



image



Liste de lecture



Livres



The Manager's Path: A Guide for Tech Leaders Navigating Growth and Change, Camille Fournier - link



The Elegant Puzzle: Systems of Engineering Management, Will Larson - Link



Team Topologies: Organizing Business and Technology Teams for Fast Flow, Manuel Pais et Matthew Skelton - lien



redressant Software, Juval Lowy - lien



Penser en systèmes: Notions, Donella Meadows - référence



articles



modèles mentaux, Street Fernam - lien



complexité Bias: Pourquoi nous préférons Complicated à simple. Fernam Street - lien



Ce que l'argent ne peut pas acheter, moins mal - lien



Devenir inhabituellement orienté vers la vérité, moins mal -lien



Lois de programmation et réalité: savons-nous ce que nous pensons savoir? - lien



No Silver Bullet Essence and Accidents of Software Engineering - lien



The Art of Troubleshooting - lien



From Fragile to Antifragile Software - lien Les



ordinateurs peuvent être compris - lien



Tuckman Was Wrong! ( A propos des équipes) - référence



Comment échouer à presque tout et encore gagner gros - lien



Simplicité Avant Généralité, utilisation Avant réutilisation - lien

Simplicité, S'il vous plaît - Un Manifeste pour le logiciel de développement - Lien



Logiciel de conception est les relations humaines - Lien



All Articles