Programmation aux masses

Comprendre même les bases de la programmation peut simplifier les activités humaines. En plus des choses évidentes, telles que le développement de la pensée abstraite ou la capacité de diviser la tâche en parties plus petites, je propose d'aller encore plus loin et d'utiliser les approches de base du développement. En utilisant l'exemple de la création d'un jeu logique classique, en faisant une analogie entre la programmation visuelle et la programmation traditionnelle, je veux montrer comment les compétences en développement peuvent aider à résoudre un problème appliqué. Ceux qui souhaitent débattre sur le sujet ou jouer "Bulls and Cows" et gagner un prix - un appel au chat.



Je m'appelle Zhenya et je suis développeur backend chez ManyChat. Il y a quelque temps, l'équipe RH m'a approché avec une demande pour implémenter le jeu «Bulls and Cows», familier à beaucoup d'enfance, sur la base de notre produit. Permettez-moi d'ajouter un peu de contexte. ManyChat est un outil pour automatiser l'interaction entre les entreprises et leurs clients, vous permettant de répondre aux questions courantes via Facebook, et plus récemment SMS et e-mail. "Bulls and Cows" est un jeu logique, au cours duquel, pour plusieurs tentatives, il faut deviner le nombre deviné. Beaucoup peuvent le savoir grâce au jeu Fallout, où vous devez pirater un terminal informatique. Plus de détails sur les règles peuvent être trouvés à la fin de l'article.

Visualisation


Que faisons-nous avant d'écrire du code pour une tâche complexe? Nous allons au tableau noir avec un marqueur ou prenons un crayon et du papier et dessinons un diagramme ou un diagramme UML, car la visualisation est le moyen le plus naturel pour les gens de présenter et de percevoir des informations. Flow Builder est le cœur de notre système, basé sur divers objets, éléments graphiques et les règles par lesquelles ils interagissent les uns avec les autres. Je dirais que c'est une continuation logique de la programmation orientée objet. J'ai donc jeté les outils habituels et j'ai immédiatement procédé à la conception de la logique de communication entre le bot et le joueur.

Jeu Flow of the Bulls and Cows

C'est très pratique, car le diagramme UML et Flow Builder sont presque identiques. À cette étape, la conception et la programmation sont déjà combinées. Pendant plusieurs itérations, j'ai jeté un flux et désigné les lieux d'interaction avec l'utilisateur et avec l'API. Le résultat obtenu était quelque peu différent de la représentation originale dans ma tête - la visualisation a fourni l'occasion de regarder la tâche sous un angle différent. C'est bien, car les modifications apportées au diagramme sont plus faciles et moins chères que le code. Il me semble que le sens de cette approche est enraciné dans le proverbe «mesure sept fois, coupe une». Les ingénieurs doivent être particulièrement familiers et compréhensibles.

Répartition des responsabilités


Qu'est-ce qui devrait être implémenté du côté de ManyChat, et quoi du côté du code? La réponse à cette question au premier abord ne m'a pas paru évidente. Il existe deux outils d'interaction sur notre plateforme: Dynamic Block et External Request. Ils sont presque identiques, sauf que le premier exécute la demande au serveur distant et passe à l'instruction suivante, et le second vous permet de comparer d'abord les données de réponse avec les variables du bot. Dans l'une des premières versions, j'ai utilisé le bloc dynamique et implémenté l'envoi des classements de la méthode API directement à Facebook. Il semblerait qu'il n'y ait rien de mal à cette approche. Mais si vous regardez un peu plus loin et supposez que le joueur veut jouer avec SMS, le code devra connaître le canal de communication d'un joueur spécifique. Cela ne semble pas nécessaire. Dans la version suivante, j'ai changé de flux pour travailler avec une demande externe,ajouté un enregistrement de réponse aux variables utilisateur et supprimé toute mention du canal du code. Désormais, le code du jeu peut être utilisé dans une autre application et implémenter n'importe quelle interface d'interaction souhaitée: de la console à l'application mobile. Que ce soit pour séparer la vue de la logique de contrôle selon le modèle MVC ou mettre en évidence les contextes limités selon l'approche DDD - décidez par vous-même. L'essentiel ici est que malgré le manque d'exigences, à un niveau subconscient, j'ai identifié un goulot d'étranglement potentiel dans le système qui pourrait créer des problèmes à l'avenir.Que ce soit pour séparer la vue de la logique de contrôle selon le modèle MVC ou mettre en évidence les contextes limités selon l'approche DDD - décidez par vous-même. L'essentiel ici est que malgré le manque d'exigences, à un niveau subconscient, j'ai identifié un goulot d'étranglement potentiel dans le système qui pourrait créer des problèmes à l'avenir.Que ce soit pour séparer la vue de la logique de contrôle selon le modèle MVC ou mettre en évidence les contextes limités selon l'approche DDD - décidez par vous-même. L'essentiel ici est que malgré le manque d'exigences, à un niveau subconscient, j'ai identifié un goulot d'étranglement potentiel dans le système qui pourrait créer des problèmes à l'avenir.

Dénomination variable


La dénomination des variables est l'un des deux principaux problèmes de programmation. En plus des variables, la dénomination des blocs est tout aussi importante. De nombreux utilisateurs n'y attachent pas d'importance, n'ont pas le temps de regarder autour de eux car le flux se transforme en un ensemble de Copie 1, Copie 2, etc. Cela complique grandement la compréhension. Tout est comme avec une mauvaise classe - il est impossible de comprendre ce qu'il fait sans entrer à l'intérieur. Plus en détail, cette pensée a été révélée par mon collègue. Si vous êtes intéressé, je vous suggère de lire son post .

Steve McConnell dans son livre "Perfect Code" a écrit que le nom devrait décrire complètement et précisément l'entité représentée. Je pense qu'il est difficile de contester cela. Par exemple, pour les variables booléennes, je préfère utiliser le préfixe is. Dans ce cas, le lecteur peut déjà comprendre à quoi il a affaire par les deux premières lettres. Quant à la longueur, il est souhaitable qu'elle ne dépasse pas 20 caractères (Gorla, Benander et Benander, 1990). Plus la portée d'une variable est petite, plus son nom peut être court. Mais comme toutes les variables de ManyChat ont une portée globale, cela vaut la peine d'utiliser l'espace de noms. Pour Bulls and Cows, j'ai utilisé le segment de départ sous la forme de deux lettres majuscules BC dérivées de Bulls and Cows. Compte tenu de ce qui précède, j'ai obtenu le nom de variable BC Is Victory - tout à fait unique et complet, à mon avis.

SEC, BAISER


Le jeu fonctionne et, semble-t-il, vous pouvez expirer avec un sentiment d'accomplissement. Mais nous savons que la prochaine étape est l'auto-évaluation et la refactorisation. Avec une analyse plus détaillée, vous pouvez voir comment l'arrêt du traitement de texte et la victoire conduisent à des blocs similaires - le joueur appelle à certaines actions. En même temps, la perte, pour une raison inconnue, vit sa propre vie. La combinaison de ces emplacements en un seul semble être une étape logique pour éviter les doublons, ce qui conduit à son tour à une cohérence accrue du comportement et à une facilité de maintenance. Maintenant, si des changements sont nécessaires, vous devez les faire dans la seule unité du système sans changements dans les autres, ce qui indique que le principe de ne pas se répéter est appliqué avec succès.


Débit avec DRY

Mais ne vous arrêtez pas là. Les solutions complexes sont difficiles à maintenir. Lorsqu'une erreur se produit, il ne sera pas facile de la localiser, surtout après un moment où vous tombez hors contexte. Une nouvelle personne prendra beaucoup d'énergie pour comprendre ce qui est quoi. Et vous devrez vous familiariser avec chaque nœud, afin de ne rien manquer d'important. Par conséquent, il vaut la peine d'utiliser le principe de garder les choses simples, stupides et de diffuser toutes les actions possibles dans des endroits séparés. Après décomposition, j'ai eu 5 flux assez faciles à comprendre. En prime, ce refactoring satisfait à une seule responsabilitéprincipe. Chaque flux a une responsabilité et cette responsabilité y est complètement encapsulée. L'appel est une boîte noire, et par la nature du problème, il peut être localisé plus rapidement.


Débit conforme KISS

YAGNI


Dans l'une des premières versions de l'automatisation, il y a eu des succès dans l'envoi de rappels d'un jeu abandonné et des instructions pour recevoir des cadeaux par les gagnants. La mise en œuvre de la première idée a été compliquée par des restrictions de la part de Facebook - récemment, les conditions d'envoi de messages hors fenêtre à 24 heures sont devenues plus dures. Le second s'est avéré insuffisamment trivial pour l'implémentation par le code. Les deux problèmes sont résolus, mais la quantité d'efforts nécessaires n'était pas justifiée par les besoins d'une campagne unique. De plus, les tâches de sprint se sont succédées, il a donc été décidé de ne pas implémenter cette fonctionnalité. Et voici venu à la rescousse Tu n'en auras pas besoinun principe dont le but est de s'abstenir d'une fonctionnalité excessive. Il s'agit d'une situation normale lorsque les conditions changent et sont mortes, plus de pièces inutiles apparaissent dans le produit. La suppression des blocs correspondants a facilité la compréhension de l'objectif du flux et a rappelé une fois de plus l'importance du refus en temps opportun d'ajouter de nouvelles fonctionnalités, ce qui n'est pas directement nécessaire.

Les développeurs expérimentés savent que toute fonctionnalité nécessite un support constant, de la refactorisation du code à la mise à jour de la documentation et à l'utilisation des commentaires des utilisateurs. Par conséquent, l'ajout de nouvelles fonctionnalités doit toujours être considéré avec suspicion, posant la question, est-ce vraiment nécessaire? En fin de compte, à ce stade, vous pouvez économiser beaucoup de ressources.

jouons


Les étapes de l'auto-évaluation et de la refactorisation sont passées, il n'y a pas de fonctionnalité inutile et la signification de tous les flux est transparente pour la compréhension. Cela signifie que le jeu est prêt et qu'il est temps de concourir pour des prix. Selon les termes de la compétition, les 10 meilleurs joueurs qui marquent le plus de points avant le 22 mai 2020 recevront des prix de l'équipe ManyChat.

Un peu sur les règles. Dans notre implémentation, le jeu est conçu pour une seule personne. Le bot fait une séquence de 4 chiffres avec des nombres non répétitifs. Le joueur tente de deviner le nombre. Le bot indique en réponse combien de nombres ont été devinés sans coïncidence avec leur position, c'est-à-dire le nombre de vaches, et combien ont été devinés jusqu'à la position, c'est-à-dire le nombre de taureaux. En conséquence, le scénario de jeu peut ressembler à ceci:

Le nombre 1234 est deviné. Le
participant fait la première hypothèse: 4321
Obtient la réponse: 0 taureau et 4 vaches Le
participant fait la deuxième hypothèse: 1678
Et reçoit la réponse: 1 taureau et 0 vache.

Pour essayer, suivez le lien et suivez les invites. Permettez-moi de vous rappeler que le jeu passe par Facebook Messenger. Nous proposons 2 niveaux de difficulté: un jeu pour un nombre limité et illimité de coups. Gagner dans un match difficile vous rapportera 3 points, dans un simple - 2. Perdre, quel que soit le niveau, prendra 1 point.

Le jeu a été implémenté sur une pile technologique standard: Nginx 1.17, PHP 7.4, PostgreSQL 12.1. Si vous le souhaitez, vous pouvez cloner le référentiel sur votre serveur, installer le modèle sur votre page ManyChat et organiser votre propre tournoi.

résultats


"Tout le monde dans ce pays doit apprendre à programmer sur un ordinateur car il vous apprend à penser." Je pense que la pertinence de cette déclaration dépasse depuis longtemps les frontières d'un seul pays. La programmation n'est pas un personnage secret dans le terminal, difficile à percevoir par une personne non initiée, et un programmeur n'est pas un élu. Tout d'abord, c'est une façon de penser et un ensemble de compétences pour résoudre des problèmes.

Passant au titre de l'article et au slogan original, je veux le reformuler: «La programmation appartient au peuple. Elle doit avoir ses racines les plus profondes dans les profondeurs mêmes des larges masses ouvrières. Il doit être compris par ces masses et aimé par elles. »

Je n'aurais jamais pensé que dans un article je citerais Steve Jobs et Lénine.

Je suis sûr que les pensées présentées ici me sont venues à l'esprit non seulement pour moi. Certains les considéreront même comme des capitaines. Mais je sais par moi-même que parfois vous devez entendre plusieurs fois la même information pour commencer à l'utiliser. Le principe banal est de simplifier les choses aussi simples qu'elles le paraissent. Chaque programmeur sait que le code du projet devient rapidement et facilement incontrôlable s'il ne reçoit pas l'attention qu'il mérite. Mais parfois, vous devez vous en souvenir à nouveau.

Quelque chose n'était pas allumé du tout. Par exemple, les techniques de programmation extrêmes telles que la programmation par paires, les petites versions fréquentes et le jeu de la planification n'ont pas été abordés dans cet article. Bien que les méthodologies flexibles aient des racines communes avec les systèmes d'organisation de la production physique hors ligne, elles sont encore souvent utilisées pour le développement de logiciels. Bien que leur potentiel ne se limite pas à l'industrie.

Il y a probablement quelque chose auquel je n'ai jamais pensé. Chacun de nous a sa propre expérience et sa propre vision. Je vous invite donc à partager vos réflexions à ce sujet dans les commentaires.

All Articles