Les dépendances de code sont le diable.

Vos dépendances vous brûleront à chaque fois.
«Le changement est la seule constante…» - Héraclite (philosophe)

Les outils, bibliothèques et frameworks que nous utilisons aujourd'hui pour créer nos applications Web sont radicalement différents de ceux que nous utilisions il y a quelques années à peine.

Dans quelques années, la plupart de ces technologies auront de nouveau radicalement changé. Pourtant, beaucoup d'entre nous en font une partie centrale et inextricable de nos applications.

Nous importons, utilisons et héritons des frameworks de la saveur du mois comme s'ils allaient tous être présents et inchangés pour toujours. Eh bien… ils ne le sont pas. Et c'est un problème.

Après plus de 20 ans de développement, de conception et d'architecture d'applications Web, j'en suis venu à apprécier deux vérités importantes:

  1. Les dépendances externes constituent une grande menace pour la stabilité et la viabilité à long terme de toute application.
  2. Il est de plus en plus difficile, voire impossible, de créer tout type d'application non triviale sans tirer parti des dépendances externes.

Cet article vise à concilier ces deux vérités afin que nos applications aient les meilleures chances de survie à long terme.

Le trou du lapin est vraiment très profond.

Si nous commençons à penser à tout ce dont nos applications Web dépendent, il est facile d'en penser à une douzaine ou plus avant même de passer au code:

  • Puissance
  • Connectivité
  • Pare-feu
  • DNS
  • Matériel serveur (CPU, disque, Ram,…)
  • Refroidissement
  • Plateforme de virtualisation
  • Plateforme de conteneurs
  • Système opérateur
  • Plateforme de serveur Web
  • Plateforme App Server
  • Navigateur Web

En tant que développeurs, il est bon d'être conscient de ces choses, mais nous ne pouvons souvent pas faire grand-chose à leur sujet. Alors, ignorons-les pour l'instant et ne parlons que du code.

Dans le code, il existe trois types de dépendances:

1. Dépendances que nous contrôlons

Ce code est écrit et appartient à nous ou à notre organisation.

2. Dépendances que nous ne contrôlons pas

Il s'agit de code écrit par un fournisseur tiers ou une communauté de logiciels open source.

3. Dépendances une fois supprimées

Ce sont les dépendances de code dont dépendent nos dépendances de code tiers. (Dis ça trois fois vite!)

Nous allons parler principalement des dépendances que nous ne contrôlons pas.

Les dépendances que nous contrôlons et les dépendances une fois supprimées peuvent toujours causer des maux de tête, mais dans le cas des dépendances que nous contrôlons, nous devrions être en mesure d'intervenir directement et d'atténuer les problèmes.

Dans le cas de dépendances une fois supprimées, nous pouvons généralement compter sur un tiers pour s'en occuper à notre place, car elles en dépendent également.

Pourquoi les dépendances de code tiers sont bonnes

Une grande partie de votre application Web existe pour résoudre les problèmes courants: authentification, autorisation, accès aux données, gestion des erreurs, navigation, journalisation, chiffrement, affichage d'une liste d'éléments, validation des entrées de formulaire, etc.

Quelle que soit la pile technologique que vous utilisez, il existe de bonnes chances que des solutions communes à ces problèmes existent et soient disponibles sous forme de bibliothèques que vous pouvez facilement acquérir et connecter à votre base de code. L'écriture de tout cela complètement à partir de zéro est généralement une perte de temps.

Vous souhaitez vous concentrer sur du code qui résout un problème inhabituel ou résout un problème commun d'une manière inhabituelle. C'est ce qui rend votre application précieuse: le code qui met en œuvre les règles métier uniques à votre application seule - la «sauce secrète».

L'algorithme de recherche et de classement des pages de Google, le filtrage de la chronologie de Facebook, la section «recommandé pour vous» de Netflix et les algorithmes de compression de données - le code derrière toutes ces fonctionnalités est «sauce secrète».

Le code tiers - sous forme de bibliothèques - vous permet d'implémenter rapidement ces fonctionnalités standardisées de votre application, afin que vous puissiez rester concentré sur votre «sauce secrète».

Pourquoi les dépendances de code tiers sont mauvaises

Jetez un œil à n'importe quelle application Web non triviale construite au cours des deux dernières années et vous serez absolument stupéfait par la quantité de code qui provient réellement d'une bibliothèque tierce. Que se passe-t-il si une ou plusieurs de ces bibliothèques tierces changent radicalement, disparaissent ou se cassent?

Si c'est open-source, vous pouvez peut-être le réparer vous-même. Mais dans quelle mesure comprenez-vous tout le code de cette bibliothèque que vous ne possédez pas? Une grande raison pour laquelle vous utilisez une bibliothèque en premier lieu est d'obtenir les avantages du code sans avoir à vous soucier de tous les détails. Mais maintenant tu es coincé. Vous avez complètement lié votre fortune à ces dépendances que vous ne possédez pas et ne contrôlez pas.

Ne vous inquiétez pas, à la fin de cet article, vous trouverez un nouvel espoir.

Vous pensez peut-être que j'exagère ou que je parle d'un point de vue purement académique. Permettez-moi de vous assurer que j'ai des dizaines d'exemples de clients qui se sont complètement snookés en incorporant trop étroitement du code tiers dans leur application. Voici un exemple récent…

Un ancien client à moi a créé son application en utilisant un fournisseur de backend en tant que service appartenant à Facebook, appelé Parse. Ils ont utilisé une bibliothèque client JavaScript fournie par Parse pour consommer le service Parse. Dans le processus, ils ont étroitement couplé tout leur code - y compris le code «secret sauce» - à cette bibliothèque.

Trois mois après le lancement initial du produit de mon client - tout comme ils ont commencé à obtenir une bonne traction avec de vrais clients payants - Parse a annoncé sa fermeture.

Maintenant, au lieu de se concentrer sur l'itération de leur produit et d'élargir leur base de clients, mon client a dû trouver comment migrer vers une version open source auto-hébergée de Parse ou remplacer complètement Parse.

La perturbation que cela a causée à une jeune application naissante était si énorme que mon client a finalement abandonné l'application.

Équilibrer le bien et le mal

Il y a plusieurs années, ma solution de choix pour surmonter les risques tout en conservant les avantages des bibliothèques tierces était de les encapsuler à l'aide du modèle d'adaptateur.

Essentiellement, vous encapsulez le code tiers dans une classe d'adaptateur ou un module que vous avez écrit. Cela fonctionne ensuite pour exposer les fonctions des bibliothèques tierces d'une manière que vous contrôlez.

En utilisant ce modèle, si une bibliothèque ou un framework tiers change ou disparaît, vous n'avez qu'à corriger un peu de code d'adaptateur. Le reste de votre application reste intact.

Schéma de configuration de l'adaptateur sur Dofactory.com

Cela sonne bien sur le papier. Lorsque vous avez des dépendances autonomes qui ne fournissent que quelques fonctions, cela fera l'affaire. Mais les choses peuvent mal tourner rapidement.

Pouvez-vous imaginer avoir à envelopper la bibliothèque React entière (y compris JSX) avant de l'utiliser? Que diriez-vous d'encapsuler jQuery, ou Angular, ou le framework Spring en Java? Cela devient rapidement un cauchemar.

Ces jours-ci, je recommande une approche plus nuancée…

Pour chaque dépendance que vous souhaitez ajouter à votre base de code, évaluez le niveau de risque qu'elle entraînera en multipliant deux facteurs:

  1. La probabilité que la dépendance change de manière matérielle.
  2. Le montant des dommages qu'un changement matériel à la dépendance causerait à votre application.

Une bibliothèque ou un framework tiers est moins susceptible de changer lorsque certaines ou toutes les choses suivantes sont vraies:

  • Il existe depuis plusieurs années et a connu plusieurs versions majeures.
  • Il est largement utilisé par de nombreuses applications commerciales.
  • Il bénéficie du soutien actif d'une grande organisation - de préférence une entreprise ou une institution de renom.

Une bibliothèque ou un framework tiers fera moins de dégâts à votre application lorsque certaines ou toutes les choses suivantes sont vraies:

  • Il n'est utilisé que par une petite partie de votre application, plutôt que d'être utilisé partout.
  • Le code qui en dépend ne fait pas partie de cette «sauce secrète» dont j'ai parlé plus tôt.
  • Le supprimer nécessite des modifications minimes de votre base de code.
  • Votre application entière est très petite et peut être réécrite rapidement. (Soyez prudent avec celui-ci - c'est rarement vrai pendant très longtemps.)

Plus quelque chose est risqué, plus vous devriez être susceptible de l'envelopper ou de l'éviter complètement.

En ce qui concerne le code qui est vraiment au cœur de la proposition de valeur de votre application - votre «sauce secrète» - vous devez en être extrêmement protecteur. Rendez ce code aussi indépendant que possible. Si vous devez absolument utiliser une dépendance, envisagez de l'injecter plutôt que de la référencer directement. Même alors, soyez prudent.

Parfois, cela signifie dire «non» à une bibliothèque tierce qui vous semble vraiment cool ou que vous souhaitez vraiment utiliser pour une raison ou une autre. Être fort. Croyez-moi, ça va payer. Demandez à toutes ces personnes qui ont investi massivement dans la toute première version d'Angular, ou à mon ancien client qui a utilisé Parse partout. Ce n'est pas amusant. Crois moi.

En parlant de plaisir, jetez un œil à ceci…

Graphique de dépendance pour TinyTag explorer

L'image ci-dessus est le graphique des dépendances pour une application appelée TinyTag Explorer.

La génération d'un graphique de dépendance pour vos applications existantes est un excellent moyen de comprendre le niveau de risque introduit par vos dépendances. J'ai rassemblé une liste d'outils gratuits pour générer des graphiques similaires à ceux ci-dessus dans une variété de langages, notamment JavaScript, C #, Java, PHP et Python. Vous pouvez l'obtenir ici.

Aidez-moi à aider les autres

Je veux aider autant de développeurs que possible en partageant mes connaissances et mon expérience avec eux. Aidez-moi en cliquant sur le bouton ❤ recommander (coeur vert) ci-dessous.

Enfin, n'oubliez pas de récupérer votre liste de générateurs de graphiques de dépendance gratuits ici.