Principes de développement d'applications modernes à partir de NGINX. Partie 1

Bonjour mes amis. En prévision du lancement du cours «Développeur PHP Backend» , nous partageons traditionnellement avec vous la traduction de matériel utile.

Le logiciel résout de plus en plus de tâches quotidiennes, tout en devenant de plus en plus difficile. Comme l'a dit Mark Andressen, cela engloutit le monde.



En conséquence, les approches de développement et de livraison d'applications ont radicalement changé au cours des dernières années. Ce sont des changements d'échelle tectonique qui ont conduit à l'émergence d'un ensemble de principes. Ces principes se sont révélés utiles pour la constitution d'équipe, la conception, le développement et la livraison de votre application aux utilisateurs finaux.

Les principes peuvent être résumés comme suit: l' application doit être petite, en réseau et avoir une architecture orientée développeur . Sur la base de ces trois principes, vous pouvez créer une application fiable et complète qui peut être livrée rapidement et en toute sécurité à l'utilisateur final, et peut être facilement mise à l'échelle et étendue.



Chacun des principes proposés comporte un certain nombre d'aspects dont nous discuterons pour montrer comment chaque principe contribue à la réalisation de l'objectif ultime, à savoir la livraison rapide d'applications fiables, faciles à maintenir et à utiliser. Nous examinerons les principes par rapport à leurs opposés afin de clarifier ce que cela signifie, par exemple: «Assurez-vous d'utiliser le principe de petitesse ».

Nous espérons que cet article vous encouragera à utiliser les principes proposés pour créer des applications modernes qui fourniront une approche unifiée de la conception dans le contexte d'une pile technologique en constante évolution.

En appliquant ces principes, vous vous retrouverez à tirer parti des dernières tendances de développement de logiciels, y compris l'approche DevOps pour développer et fournir des applications, en utilisant des conteneurs (comme Docker ) et des cadres pour l'orchestration de conteneurs (comme Kubernetes ), en utilisant des microservices (y compris NGINX Microservice Architecture) et architecture de communications réseau pour les applications de microservices.

Qu'est-ce qu'une application moderne?

Des applications modernes? Pile moderne? Que signifie exactement «moderne»?

La plupart des développeurs n'ont qu'une idée générale de la composition d'une application moderne, vous devez donc donner une définition claire de ce concept.

Une application moderne prend en charge plusieurs clients, que ce soit une interface utilisateur sur la bibliothèque JavaScript React, une application mobile pour Android ou iOS, ou une application qui se connecte à une autre via l'API. Une application moderne implique la présence d'un nombre indéfini de clients pour lesquels elle fournit des données ou des services.

Une application moderne fournit une API pour accéder aux données et services demandés. L'API doit être immuable et constante, et non écrite spécifiquement pour une demande spécifique d'un client particulier. L'API est accessible via HTTP (S) et donne accès à toutes les fonctionnalités de l'interface graphique ou de la CLI.

Les données doivent être accessibles dans un format compatible généralement accepté, tel que JSON. L'API fournit des objets et des services d'une manière claire et organisée, par exemple, l'API RESTful ou GraphQL fournissent une interface décente.

Les applications modernes sont construites sur une pile moderne, et une pile moderne est la pile qui prend en charge de telles applications, respectivement. Une telle pile permet au développeur de créer facilement une application avec une interface HTTP et d'effacer les points de terminaison de l'API. L'approche choisie permettra à votre application de recevoir et d'envoyer facilement des données au format JSON. En d'autres termes, la pile moderne correspond aux éléments de l'application à douze facteurs pour les microservices .

Les versions populaires de ce type de pile sont basées sur Java , Python , Node , Ruby , PHP et Go . L' architecture NGINX Microservice représente un exemple de pile moderne implémentée dans chacun des langages mentionnés.

Veuillez noter que nous ne préconisons pas exclusivement une approche de microservice. Beaucoup d'entre vous travaillent avec des monolithes qui doivent évoluer, tandis que d'autres traitent des applications SOA qui se développent et évoluent pour devenir des applications de microservices. D'autres encore s'orientent vers des applications sans serveur, et certains introduisent des combinaisons de ce qui précède. Les principes énoncés dans l'article sont applicables à chacun de ces systèmes avec seulement quelques changements mineurs.

Principes

Maintenant que nous avons une compréhension commune de ce qu'est une application moderne et une pile moderne, il est temps de vous immerger dans les principes d'architecture et de développement, qui vous seront utiles dans le développement, la mise en œuvre et le support d'une application moderne.

L'un des principes est de «créer de petites applications», appelons-le simplement le principe de petitesse . Il existe des applications incroyablement complexes qui se composent d'un grand nombre de composants mobiles. À son tour, la création d'une application à partir de petits composants discrets simplifie sa conception, sa maintenance et son utilisation avec elle dans son ensemble. (Remarque, nous avons dit «simplifie» et non «simplifie les choses».)

Le deuxième principe est que nous pouvons augmenter la productivité des développeurs en les aidant à se concentrer sur les fonctionnalités qu'ils développent, tout en les libérant des soucis concernant l'infrastructure et les CI / CD lors de la mise en œuvre. Donc, en résumé, notre approche se concentre sur les développeurs .

Enfin, tout ce qui concerne votre application doit être connecté au réseau. Au cours des 20 dernières années, nous avons fait de grands progrès vers un avenir en réseau, car les réseaux sont plus rapides et les applications plus complexes. Comme nous l'avons déjà découvert, une application moderne devrait être utilisée sur le réseau par de nombreux clients différents. L'utilisation de la pensée réseau en architecture présente des avantages significatifs qui vont bien avec le principe de petitesse et le concept d'une approche orientée développeur .

Si, lors du développement et de la mise en œuvre de l'application, vous respectez ces principes, vous bénéficierez d'un avantage indéniable dans le développement et la livraison de votre produit.

Examinons ces trois principes plus en détail.

Principe de petitesse

Il est difficile pour le cerveau humain de percevoir simultanément une grande quantité d'informations. En psychologie, le terme charge cognitive désigne la quantité totale d'effort mental nécessaire pour stocker des informations en mémoire. La réduction de la charge cognitive sur les développeurs est une priorité, car dans ce cas, ils peuvent se concentrer sur la résolution du problème, au lieu de garder à l'esprit le modèle complexe actuel de l'application entière et les fonctions en cours de développement.



Les demandes sont décomposées pour les raisons suivantes:

  • Diminution de la charge cognitive sur les développeurs;
  • Accélérez et simplifiez les tests;
  • Livraison rapide des modifications dans l'application.

Il existe plusieurs façons de réduire la charge cognitive des développeurs, et c'est là que le principe de petitesse entre en jeu.

Il existe donc trois façons de réduire la charge cognitive:

  1. Réduisez le délai dont ils devraient tenir compte lors du développement d'une nouvelle fonction - plus le délai est court, plus la charge cognitive est faible.
  2. Réduisez la quantité de code sur laquelle un travail ponctuel est effectué - moins de code - moins de charge.
  3. Simplifiez le processus de modification incrémentielle de l'application.

Réduisez les délais de développement

Revenons à l'époque où la méthodologie de la waterfall était la norme pour le processus de développement, et le délai de six mois à deux ans pour développer ou mettre à jour l'application était une pratique courante. En règle générale, les ingénieurs ont d'abord lu les documents pertinents, tels que les exigences du produit (PRD), le document de référence du système (SRD), le plan d'architecture, et ont commencé à combiner toutes ces choses ensemble dans un modèle cognitif, selon lequel ils ont écrit le code. Au fur et à mesure que les exigences et, par conséquent, l'architecture changeaient, de sérieux efforts devaient être faits pour informer toute l'équipe des mises à jour du modèle cognitif. Dans le pire des cas, une telle approche pourrait simplement paralyser le travail.

Le plus grand changement dans le processus de développement d'applications a été l'introduction de la méthodologie agile. L'une des principales caractéristiques de la méthodologie agile est le développement itératif. À son tour, cela conduit à une diminution de la charge cognitive des ingénieurs. Au lieu d'exiger que l'équipe de développement implémente l'application en un long cycle, l'approche agile vous permet de vous concentrer sur de petites quantités de code qui peuvent être rapidement testées et déployées, tout en recevant également des commentaires. La charge cognitive de l'application est passée de la période de six mois à deux ans, en tenant compte du grand nombre de spécifications pour un ajout de deux semaines ou des changements de fonctionnalités, visant à une compréhension plus vague d'une grande application.

Passer d'une application massive à de petites fonctions spécifiques qui peuvent être accomplies en un sprint de deux semaines, dans la perspective d'une seule fonction du prochain sprint dans la tête, est un changement significatif. Cela nous a permis d'augmenter la productivité du développement tout en réduisant la charge cognitive, qui fluctuait constamment.

La méthodologie agile suppose que l'application finale sera une version légèrement modifiée du concept d'origine, de sorte que le point de développement final est nécessairement ambigu. Seuls les résultats de chaque sprint particulier peuvent être clairs et précis.

Petites bases de code

L'étape suivante pour réduire la charge cognitive consiste à réduire la base de code. En règle générale, les applications modernes sont massives - une application d'entreprise fiable peut comprendre des milliers de fichiers et des centaines de milliers de lignes de code. Selon l'organisation des fichiers de communication et les dépendances du code et des fichiers, ils peuvent être évidents ou inversement. Même le débogage du code lui-même peut causer des problèmes, selon les bibliothèques utilisées et la façon dont les outils de débogage distinguent les bibliothèques / packages / modules et le code utilisateur.

La construction d'un modèle mental fonctionnel du code d'application peut prendre un temps impressionnant, et encore une fois placer une grande charge cognitive sur le développeur. Cela est particulièrement vrai pour les bases de code monolithiques, où il y a une grande quantité de code, dont l'interaction entre les composants fonctionnels n'est pas clairement définie, et la séparation des objets d'attention est souvent floue, car les limites fonctionnelles ne sont pas respectées.

L'un des moyens efficaces de réduire la charge cognitive des ingénieurs est la transition vers une architecture de microservices. Dans l'approche microservice, chaque service se concentre sur un ensemble de fonctions; la signification du service est généralement définie et compréhensible. Les limites du service sont également claires - n'oubliez pas que la communication avec le service est effectuée à l'aide de l'API, de sorte que les données générées par un service peuvent facilement être transférées à un autre.

L'interaction avec d'autres services est généralement limitée à plusieurs services utilisateur et plusieurs services fournisseur qui utilisent des appels API simples et propres, par exemple à l'aide de REST. Cela signifie que la charge cognitive sur l'ingénieur est sérieusement réduite. La tâche la plus difficile est de comprendre le modèle d'interaction entre les services et comment des choses comme les transactions se produisent dans plusieurs services. En conséquence, l'utilisation de microservices réduit la charge cognitive, réduisant la quantité de code, indiquant des limites claires du service et fournissant une compréhension de la relation entre les utilisateurs et les fournisseurs.

Petits changements incrémentiels

Le dernier élément du principe de petitesse est la gestion du changement. C'est une tentation particulière pour les développeurs de regarder la base de code (même, peut-être, par eux-mêmes, un code plus ancien) et de dire: "C'est de la merde, nous devons tout réécrire." Parfois, c'est la bonne décision, et parfois non. Cela place le fardeau du changement de modèle global sur l'équipe de développement, ce qui entraîne à son tour une charge cognitive massive. Il est préférable pour les ingénieurs de se concentrer sur les changements qu'ils peuvent apporter pendant le sprint, afin de déployer plus tard les fonctionnalités nécessaires en temps opportun, quoique progressivement. Le produit final devrait rappeler un produit pré-planifié, mais avec quelques modifications et tests pour répondre aux besoins des clients.

Lors de la réécriture de grandes parties du code, il est parfois impossible de fournir rapidement des modifications, car d'autres dépendances système entrent en jeu ici. Afin de contrôler le flux des modifications, vous pouvez utiliser la fonction de masquage. En principe, cela signifie que la fonctionnalité est en production, mais elle n'est pas disponible en utilisant les paramètres des variables d'environnement (env-var) ou un autre mécanisme de configuration. Si le code a réussi tous les processus de contrôle qualité, il peut être en cours de production dans un état caché. Cependant, cette stratégie ne fonctionne que si la fonctionnalité est finalement activée. Sinon, il ne fera qu'encombrer le code et ajouter une charge cognitive, que le développeur devra faire face pour un travail productif. La gestion du changement et les changements incrémentiels en eux-mêmes aident à maintenir la charge cognitive des développeurs à un niveau abordable.

Les ingénieurs doivent surmonter de nombreuses difficultés, même avec la simple mise en œuvre de fonctionnalités supplémentaires. De la part de la direction, il serait raisonnable de réduire la charge supplémentaire de l'équipe pour qu'elle puisse se concentrer sur les éléments clés de la fonctionnalité. Vous pouvez faire trois choses pour aider votre équipe de développement:

  1. Utilisez une méthodologie agile pour limiter le délai dans lequel une équipe doit se concentrer sur les fonctions clés.
  2. Implémentez votre application en tant que microservices. Cela limitera le nombre de fonctionnalités mises en œuvre et renforcera les limites qui maintiennent la charge cognitive pendant le travail.
  3. Préférez les modifications incrémentielles à grandes et volumineuses, modifiez de petits morceaux de code. Utilisez le masquage des fonctionnalités pour implémenter les modifications, même si elles ne sont pas visibles immédiatement après l'ajout.

Si vous appliquez le principe de petitesse dans votre travail, votre équipe deviendra beaucoup plus heureuse, mieux concentrée sur la mise en œuvre des fonctions nécessaires et plus susceptible de déployer des changements qualitatifs plus rapidement. Mais cela ne signifie pas que le travail ne peut pas être compliqué, parfois au contraire, l'introduction de nouvelles fonctionnalités nécessite la modification de plusieurs services et ce processus peut être plus compliqué que le similaire dans une architecture monolithique. Dans tous les cas, les avantages d'une petite approche en valent la peine.

La fin de la première partie.

Bientôt, nous publierons la deuxième partie de la traduction, et maintenant nous attendons vos commentaires et nous vous invitons à ouvrir la journée , qui se tiendra aujourd'hui à 20h00.

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


All Articles