Le bordel du back-end

-

Préface

Il n’y a pas si longtemps, les débats internes les plus courants des équipes de développeurs portaient sur le langage de programmation frontend, le backend étant le plus souvent une pile Java. Aujourd’hui, non seulement nous disposons de plusieurs bonnes alternatives (Php, Python, Java, Node.js, Kotlin, Rust, Go, etc.), mais nous avons également de nombreux cas dans lesquels différentes alternatives sont mises en œuvre par la même organisation, et dans certains cas même dans la même application où chaque microservice est construit en utilisant un langage de programmation différent. C’est ce que j’appelle le « bordel du backend ».

Il y a une différence entre les petites startups et les grandes organisations. Dans une petite startup, le « chaos » n’est pas un problème et est très facile à gérer, parfois même bienvenu, alors que lorsque la taille d’une organisation augmente, le défi devient plus grand.

Dans cet article, je vais analyser les avantages et les inconvénients de l’utilisation de plusieurs langages de programmation backend dans la même organisation, et comment nous pouvons atténuer certains des défis que cela crée.

Nous pouvons avoir la même discussion sur les bases de données, les langages de programmation frontend, et d’autres sujets, où beaucoup des avantages et des inconvénients seront identiques, mais nous les couvrirons dans un autre article.

Pourquoi utiliser plusieurs langages de programmation backend ?

L’utilisation de plusieurs langages de programmation dans une même organisation et même dans une même application (chaque microservice ayant son propre langage) présente de nombreux avantages. Ces avantages sont répartis en plusieurs catégories : optimisation, rétention et attraction des développeurs, positionnement de l’organisation et ceinture de sécurité.

Optimisation

  • Utiliser le langage le plus efficace pour chaque tâche, par exemple : Go ou Rust pour le temps réel, Python pour le Machine Learning et l’IA, etc.
  • Utilisation des compétences de l’équipe existante.
  • Les connaissances et l’expérience acquises en utilisant différents langages nous aident à prendre les bonnes décisions lors de la création de nouvelles applications. Nous connaissons de première main les avantages et les inconvénients de chaque langage pour nous, et nous pouvons lancer l’application avec n’importe lequel de ces langages.

Fidélisation et attraction des développeurs

  • Permettez aux développeurs d’apprendre et d’expérimenter de nouvelles technologies.
  • Permettre aux développeurs de faire partie d’une technologie de pointe.
  • Attirer des candidats potentiels et faciliter le recrutement des employés (la langue choisie peut être celle avec laquelle tout le monde veut développer AUJOURD’HUI).

Positionnement de l’organisation

  • Marquer l’organisation comme un leader technologique – utilisation d’un large éventail de technologies, utilisation de technologies de pointe à la mode, etc.

Ceinture de sécurité

  • Le paysage change, ce qui nous oblige à remplacer les technologies existantes. Les langages deviennent impopulaires, ou ne sont pas optimisés pour les nouvelles plates-formes que nous voulons utiliser, des changements de licence influencent nos coûts, etc. Lorsque nous décidons de remplacer un langage, le moyen le plus sûr et le plus rapide est de passer à un langage pour lequel nous avons déjà des compétences, un savoir-faire et une infrastructure.

Si nous utilisons plusieurs langages, après avoir passé du temps à créer l’infrastructure pour un langage de programmation spécifique et à préparer le CI/CD pour celui-ci – nous serons plus intelligents lorsqu’une autre équipe choisira le même langage car nous conserverons (idéalement) le même processus, ou du moins les sections mutuelles de celui-ci.

Pourquoi ne pas utiliser plusieurs langages de programmation backend

L’utilisation de plusieurs langages de programmation présente également des inconvénients importants dont il faut être conscient si l’on souhaite s’engager dans cette voie. Ces inconvénients sont principalement l’inefficacité des ressources, la redondance des logiciels, le manque d’agilité et la négativité potentielle des employés.

Inefficacité des ressources

  • Pour chaque technologie, nous devons avoir un spécialiste ou un expert en la matière à bord et nous devons fournir un plan de formation et de développement dédié.
  • Pour chaque technologie, nous devons élaborer des normes de codage dédiées basées sur les meilleures pratiques de la langue (certaines peuvent évidemment être partagées entre les langues).
  • Nous devons élaborer plusieurs modèles de pipeline CI/CD (un modèle pour chaque pile).
  • Nous pouvons avoir besoin d’utiliser plusieurs outils de soutien tels que les tests de charge et de stress, les simulations, l’analyse de code sécurisée, les SDK.
  • Les vulnérabilités de sécurité, les correctifs et les mises à niveau de version doivent être gérés, suivis et effectués plusieurs fois.
  • Nous devons construire et maintenir plusieurs environnements d’exécution.

Redondance des logiciels : spécificités linguistiques, infrastructure

  • Nous pourrions avoir un scénario dans lequel nous résoudrions le même problème ou relèverions le même défi plusieurs fois, en raison des exigences de chaque langue.
  • Il se peut que nous devions construire plusieurs fois les mêmes composants d’infrastructure (par exemple, l’autorisation, l’authentification, la mise en cache, la messagerie, les coupe-circuits, le basculement des fonctionnalités).

Agilité

  • La possibilité de déplacer les développeurs entre les projets est limitée à la technologie spécifique utilisée par le développeur.

Négativité des employés

  • Le fait de disposer de plusieurs langages, certains plus récents et plus tendance, peut créer un problème de classe sociale susceptible d’affecter l’atmosphère de travail. « Pourquoi est-ce que j’utilise une vieille technologie alors qu’ils en utilisent une nouvelle ? ».

Atténuer les défis liés aux langages de programmation multiples

Je m’excuse de vous décevoir, mais la plupart des défis ne peuvent pas être atténués. L’utilisation de plusieurs langages de programmation en arrière-plan coûtera beaucoup plus cher. Le seul et unique problème que nous pouvons résoudre est la redondance de l’infrastructure logicielle.

Dans cet article, j’aimerais suggérer une façon d’atténuer le problème de la redondance de l’infrastructure logicielle, et je l’appelle la méthodologie « open source interne + ».

La méthode

La méthode de l’open source interne +, que je vais décrire ci-dessous, vise à résoudre deux problèmes :

  • Construire et gérer des composants d’infrastructure logicielle partagée sans avoir une équipe d’infrastructure dans l’organisation.
  • Construire des composants partagés qui peuvent être construits une fois et utilisés dans plusieurs langages de développement.

La probabilité d’avoir une équipe d’infrastructure lorsque nous utilisons de multiples langages de programmation backend est faible, donc les deux problèmes devraient être abordés en utilisant une seule méthodologie.

Implémentation

La mise en œuvre comprend les éléments suivants :

  • Lorsqu’il est nécessaire de construire une nouvelle fonctionnalité, l’architecte et/ou le chef d’équipe (TL) doivent se demander : l’organisation aura-t-elle besoin d’un élément similaire ? Si la réponse est « oui », il doit être construit comme un composant/bibliothèque externe autonome, comme toute bibliothèque open source « normale ».
  • Lorsque le composant est construit, il doit être aussi configurable et flexible que possible, et implémenter non seulement les fonctionnalités requises mais aussi d’autres fonctionnalités qui seront très probablement nécessaires.
  • Le composant sera emballé en tant que source ouverte et téléchargé dans un dépôt central tel que JFrog artifactory et sera documenté dans un portail de composants (nom du composant, description, version, propriétaire, dépendances, instructions d’intégration, etc.)
  • Le constructeur du composant est considéré comme le propriétaire du composant.
  • Chaque composant doit être fourni avec des tests unitaires automatisés.
  • Lorsqu’un développeur souhaite utiliser un composant existant, mais qu’il lui manque certaines fonctionnalités, il peut utiliser une demande de modification (pull request) et effectuer les changements lui-même (y compris la mise à jour des tests automatisés), et le propriétaire devra l’approuver.

Pour que cette méthode réussisse, nous devons avoir :

  • Un gestionnaire qui est propriétaire de la mise en œuvre. Il peut s’agir d’un one-man show, ou d’une petite équipe d’infrastructure dirigée par un architecte/développeur senior (ils ne construiront ni ne maintiendront les composants).
  • Un temps pré-alloué et budgétisé pour les équipes de développement afin de le mettre en œuvre.
  • Une obligation pour toutes les équipes de se conformer et de participer sans exception.
  • Un référentiel central/un magasin de composants.
  • Un portail de composants.

Le « + »

Jusqu’à présent, nous avons fourni une solution pour construire des composants partagés. Le « + » est le moyen d’utiliser les composants dans un microservice construit à l’aide d’un langage de programmation différent de celui du composant.

Dans ce cas, les composants peuvent être utilisés de quatre manières différentes : API, fonctions sans serveur, SDK et conteneur POD.

Notez que lorsque le langage de programmation est le même que celui du composant, il peut être référencé comme n’importe quelle bibliothèque/composant open-source sans avoir besoin du « + ».

En fonction des langages populaires au sein de l’organisation, un langage pour le composant peut être choisi pour permettre son utilisation avec différents langages de programmation de manière native. Par exemple :

  • Go fonctionne aussi en C/C++, donc un composant peut être construit en C/C++ et utilisé soit en C/C++ soit en Go.
  • Kotlin et Scala fonctionnent sur JVM, donc un composant peut être construit en Java et utilisé en Java, Kotlin et Scala.

API

L’API est la meilleure approche pour utiliser des composants dans plusieurs langues. Du côté du constructeur, c’est la plus simple à construire, et du côté de l’implémenteur, elle n’a pas de dépendances, elle est agnostique, sans contrat (devrait l’être), indépendante de la version (devrait être compatible en amont et en aval) et, dans la plupart des cas, les performances sont suffisamment bonnes. En fonction du scénario spécifique, il convient de décider si l’API est synchrone ou asynchrone – un composant de haute qualité peut prendre en charge les deux options, donc la décision sera du côté de l’implémenteur.

Afin d’utiliser cette approche, le composant doit être déployé comme un microservice ou une fonction autonome.

Fonctions sans serveur (FaaS)

Serverless est très similaire à API. Lorsque je parle d’une API, mon intention est d’avoir le composant dans la portée du microservice ou au moins de l’application. De cette façon, les performances sont optimales et j’ai un contrôle total. Une approche similaire consiste à utiliser le composant comme une fonction serverless, avec les mêmes avantages qu’un composant API, mais avec moins de contrôle, moins de performances et, dans de nombreux cas, des coûts plus élevés (l’impact sur le dimensionnement lorsqu’il s’agit d’un composant est nul, alors que pour une fonction, nous devons payer séparément).

SDK

Les SDK constituent une approche plus intégrée, mais aussi plus complexe et plus coûteuse. Cette approche nécessite la création de SDK pour chaque langage de programmation utilisé dans l’organisation. Le SDK lui-même est un pont entre l’application backend et le composant. Le SDK peut « dialoguer » avec le composant de plusieurs façons : binaire, tunneling, interop, API de messages et API RESTful.

Pour utiliser cette approche, les pipelines CI/CD doivent déployer le composant et les dépendances nécessaires.

Conteneur POD

Lorsque l’infrastructure de l’application est Kubernetes et que le rôle du composant est exécuté avant l’accès au microservice (par exemple, autorisation, authentification, etc.), nous pouvons utiliser la même approche que celle utilisée pour le maillage de services. Avec le maillage de services, nous avons un conteneur de proxy et un conteneur de microservice dans chaque POD, et une connexion est établi vers le conteneur de proxy et du proxy vers le conteneur de microservice. La solution proposée ajoute un autre conteneur au POD, donc la connexion se fera vers le proxy, du proxy vers le composant, et du composant vers le microservice.

Afin d’utiliser cette approche, le composant doit être déployé comme un conteneur autonome.

Conclusion

Ma préférence personnelle en tant que développeur sénior est d’avoir quelques solutions dépendamment de l’équipe. Je suppose que si j’étais gestionnaire, ma préférence serait le contraire 😉 . La préférence, c’est bien, mais c’est la réalité qui prime !

Dans cet article, j’ai essayé d’expliquer le pour et le contre, afin que vous puissiez prendre la décision la plus sage pour votre organisation, en considérant tous les aspects.

J’ai également proposé une méthode pour gérer ce que je considère comme le principal défi – l’infrastructure logicielle réutilisable.

Alfredhttps://www.alfreddagenais.com
Je suis un développeur Web Full Stack sénior. Chaque jour est pour moi une journée de plus pour découvrir de nouvelles idées. Le développement web et l'informatique sont omniprésents dans mon quotidien. Pour que la créativité soit à son maximum, il ne faut pas avoir peur d’expérimenter et nous avons tous que le Web est infiniment grand pour expérimenter nos idées.

Buy me a coffee Paypal Patreon Ko-Fi

Share this article

Recent posts

Popular categories

LAISSER UN COMMENTAIRE

S'il vous plaît entrez votre commentaire!
S'il vous plaît entrez votre nom ici

Recent comments