snap & flatpack - tragédie des communautés

Avertissement Longrid: Vous avez été averti, de nombreuses lettres.


Il développe depuis longtemps un format de distribution pour les applications qui étaient "exemptes" de dépendances à l'échelle du système. Ubuntu est très, très actif dans la promotion de son snap, gnome - flatpack. Les deux promettent le paradis et la liberté de rpm / deb. Réfléchissons au problème qu'ils veulent résoudre et au prix qu'ils demandent pour la solution à ce problème.


Bibliothèques


Personne dans le monde moderne ne peut écrire une application sans utiliser le code de quelqu'un d'autre. Il y a plusieurs raisons:


  • De nombreuses bibliothèques sont si sérieuses que l'écriture de leurs fonctionnalités à partir de zéro est une tâche ardue. Exemples - prise en charge de l'unicode, rendu des polices, mathématiques.
  • D'autres bibliothèques offrent un ensemble de fonctions plutôt modeste, mais elles sont si bien écrites qu'il est presque impossible d'écrire au moins si bien. Bibliothèques standard de langages de programmation, diverses implémentations de libc, etc.
  • Le coût de travail avec le code de quelqu'un d'autre (auquel cette section est consacrée) est souvent inférieur au coût de maintenance de votre code. La densité de "bogues par ligne de code" est susceptible d'être comparable, et vous devez intercepter vous-même vos propres bogues. Les bibliothèques étrangères (populaires) sont susceptibles d'être déboguées et corrigées par de mauvaises mains.

La clé est que même si nous pouvons écrire nous-mêmes les fonctionnalités d'une seule bibliothèque à partir du principe, le nombre total de fonctions nécessaires (et les dépendances) donne une augmentation presque exponentielle du nombre de tâches qui doivent être résolues, reportant le temps nécessaire pour commencer à travailler sur le code du programme lui-même dans la distance inaccessible.


Un exemple pour réaliser l'échelle du drame: disons que votre application prend deux lignes d'entrée comme arguments optionnels et les affiche ensemble après normalisation. Si vous écrivez une application industrielle (une application qui ressemble à une "vraie" application), alors:


  • Vous avez besoin d'un analyseur de ligne de commande
  • Qui devrait accepter unicode
  • Et peut-être donner à l'utilisateur un indice qu'il a scellé le nom de l'argument
  • Ce qui nécessite une comparaison phonétique
  • Et peut-être des expressions régulières
  • En général, vous devrez prendre en charge non seulement Unicode, mais également d'autres paramètres régionaux, ce qui nécessite une bibliothèque de prise en charge des paramètres régionaux et TOUT ce que les utilisateurs proposent dans le contexte des paramètres régionaux.
  • La concaténation de chaînes avec normalisation est une autre utilisation d'une bibliothèque Unicode distincte; vous-même ne l'implémentez pas.
  • La sortie à l'écran (aide sur la ligne de commande, votre résultat) nécessitera probablement la prise en charge de ncurses - une bibliothèque qui prend en charge différents terminaux (vous pouvez le faire en mode texte, mais les applications utilisent souvent des capacités de couleur).
  • Les tests impliquent l'utilisation d'un framework de test, éventuellement une bibliothèque pour moks.

Il est clair qu'une telle difficulté pour la tâche «à deux lignes» est une ingénierie excessive, mais dès que vous commencez à faire quelque chose de plus, l'idée de «tout par vous-même» commence à dépasser les limites de l'observable et du réalisé.


Selon vous, combien de bibliothèques sont nécessaires pour garantir que curl http (s): // ... fonctionnera? Beaucoup. Vous en utiliserez un, mais les dépendances de vos dépendances sont vos dépendances.


Copypaste et vente VS liaison dynamique


Bien que l'utilisation des bibliothèques soit inévitable, l'utilisation elle-même peut varier dans la mise en œuvre. Veuillez noter que nous avons deux mots importants: «utiliser» et «mise en œuvre de l'utilisation». Que signifie utiliser? Dans sa forme la plus grossière - la possibilité d'appeler le code de la bibliothèque si nécessaire. Et voici les implémentations de ceci:


  • Nous pouvons copier le code qui effectue les opérations dont nous avons besoin. Sous la forme d'un morceau de code (copier-coller), en tant que module séparé dans un langage de programmation (fichier objet pour les langages compilés), ou en tant que module séparé (pour les langages interprétés). Quelque part juste à côté, "copiez le fichier source de la bibliothèque dans votre répertoire avec l'application". Quels problèmes cela crée-t-il? Le principal problème principal est que nous perdons (pour toujours) la connexion avec l'original. Même si l'auteur de la bibliothèque d'origine corrige l'erreur, nous ne le saurons pas. De plus, si nous venons de copier le code, la prochaine personne travaillant sur le programme ne pourra même pas découvrir que ce code est «étranger». En fait, nous avons coupé le chemin de la question "écrire à partir de zéro" et pris celle de quelqu'un d'autre. Cependant, nous ne coupons qu'un morceau, car s'il y a des erreurs dans ce code (mais elles ne seront pas , elles sont ), alors leur correction nécessitera la correction pour aller comprendre l'essence du problème jusqu'au fond. Même si l'essai nécessite la lecture de plusieurs centaines de milliers de lignes de code source et de centaines de RFC (ainsi que des commentaires selon lesquels les implémentations sont différentes des RFC), nous n'avons pas d'autre moyen. L'erreur principale à cet endroit est que nous avons perdu des informations selon lesquelles ce code est étranger. Avoir des commentaires dans un fichier peut aider, mais cela nécessite une implication active et profonde d'une personne, car si nous écrivons dans un commentaire "extrait de libfoobar, src / lib / foo.c version 364a51577f3782dbf8e5d2482ab941980357c492", alors quelqu'un devra voir où se trouve libfoobar, de quelle version s'agit-il et de ce qui a changé par rapport à la version précédente. "Pour simplifier ce processus, nous avons besoin de méta-informations lisibles par machine.
  • Si nous accompagnons «le code de quelqu'un d'autre» avec des méta-informations et utilisons des programmes pour gérer ce code (au lieu de copier-coller), alors cela s'appelle la vente , c'est-à-dire inclusion contrôlée du code de quelqu'un d'autre dans votre code. Techniquement, la vente peut se produire au stade du texte source, en liant des objets au fichier exécutable, en important des modules (dans des interprètes) à partir de l'application, ou même en établissant une liaison dynamique avec "votre" version de la bibliothèque (plus de détails plus loin).
  • Enfin, nous pouvons effectuer une liaison dynamique au stade du lancement de l'application. Pour les langues compilées, il s'agit de so'shks ordinaires; pour les langues interprétées, il existe un module dans l'importation à l'échelle du système. Si plusieurs applications peuvent l'importer, il s'agit d'une bibliothèque partagée. Si l'application "a apporté son module", alors la bibliothèque est "propre", même si son interface implique une "bibliothèque partagée". Par exemple, si une application utilise sa «propre» version de so, qu'elle diffère de la version générale ou non, alors c'est une vente. Et si le système est importé, il s'agit d'une bibliothèque partagée.

Quelle est la différence entre ces méthodes? Je vais brièvement donner des arguments, ils ont été discutés à plusieurs reprises dans de nombreux articles. Chacun de ces arguments reste valable malgré la présence de contre-arguments voisins:


  • Économie de mémoire (RAM et disque) pour so'sh, réduisant la taille du système installé. Plus il y a d'applications qui utilisent les mêmes, plus les économies de mémoire sont importantes. En conséquence, au contraire, plus «votre» bibliothèque apporte une application, plus elle est «grasse».
  • Le débat sur qui surveille les vulnérabilités est le système (fournissant les mises à jour de la bibliothèque) ou l'auteur de l'application (la mettant à jour à temps).
  • Résolution des conflits de dépendances (la vente résout ce problème car les bibliothèques partagées nécessitent l'attention et la précision de tous les participants au processus, créant parfois des difficultés insurmontables), le même enfer de DLL légendaire.
  • Nouvelles versions des bibliothèques - soit elles apparaissent à la demande des auteurs de la demande, soit par décision des auteurs de la distribution. Dans un cas, l'auteur peut apporter la nouvelle fonctionnalité dont il a besoin, dans un autre cas, la distribution peut apporter une amélioration à l'application existante en prenant en charge quelque chose de nouveau dans la bibliothèque (par exemple, les écrans hidpi ont commencé à fonctionner correctement dans toutes les applications liées dynamiquement aux bibliothèques qt / gtk) .

Toutes ces questions ont été traitées à plusieurs reprises auparavant. Je veux plutôt me concentrer sur les aspects sociaux du bassin versant «tout à moi» et «tout à fait commun».


Contrat social et mainteneurs de pouvoir


Les bibliothèques partagées sont coopération, pouvoir et responsabilité. Les personnes qui déterminent quelles bibliothèques partagées sont disponibles dans le système d'exploitation dictent aux fabricants de logiciels quelles bibliothèques partagées ils peuvent utiliser. De nombreux logiciels peuvent utiliser différentes bibliothèques, et l'indication de la version exacte à utiliser est laissée à la discrétion de l'éditeur de liens (pour les langues compilées) ou du gestionnaire de fichiers de dépendance (pip, bundler, etc.). Si toutes les applications de la distribution sont construites avec les mêmes exigences, alors la grâce vient: s'il y a une erreur dans une bibliothèque, le responsable de cette bibliothèque met à jour la version et le correctif est automatiquement appliqué à toutes les applications. Même si l'application est publiée tous les deux ans, le correctif dans le openssl conditionnel sera appliqué dans une semaine. Si, dans un système d'exploitation particulier, il est décidé d'abandonner l'ancien protocole, certaines modifications (par exemple, l'interface utilisateur), ces modifications s'appliqueront également à tout le monde. Look & feel dans un style général qui (peut-être) peut être changé par l'utilisateur une fois pour toutes. N'est-ce pas de la grâce?


Le pouvoir et sa lutte


... Cette grâce nécessite que toutes les applications puissent fonctionner avec la version sélectionnée de la bibliothèque. Mais que se passe-t-il si une application veut une fonction très, très nouvelle de la bibliothèque, et toutes les autres applications ne veulent pas l'utiliser, parce que, par exemple, ce n'est pas une version LTS de la bibliothèque, c'est-à-dire n'est-il pas assez stable? Mais le kit de distribution peut refuser de passer à de nouvelles versions «par principe», car nous avons promis aux utilisateurs uniquement des corrections de bugs, et de nouvelles versions uniquement dans la prochaine version de l'OS, qui (comme) sortira dans six mois. Et cela provoque une résistance de la part des auteurs de l'application. Qui êtes-vous pour me dire avec quelles versions je dois travailler? Je suis auteur, je le vois comme ça. J'ai besoin de libfoobar 3.14-pre2 ou plus ancien, pas de votre ancien libfoobar terne 3.10.


... À ce stade, l'auteur écrit simplement dans les exigences de l'application libfoobar>=3.14-pre2 . Le responsable prend et corrige la demande, puis supprime le code qui dépendait de cette bibliothèque. Peut-être. Ou refuse simplement d'accepter une nouvelle version avec une telle dépendance jusqu'à ce que cette dépendance (libfoobar 3.16) soit dans la nouvelle version de la distribution.


Si l'auteur a vraiment besoin que les utilisateurs utilisent la nouvelle version (par exemple, parce que l'auteur ne veut pas prendre en charge l'ancienne version), il recherche des solutions de contournement pour envoyer l'application à l'utilisateur.


La même chose se produit lorsqu'il existe plusieurs distributions, certaines plus récentes, d'autres plus anciennes. Maintenir des distributions plus anciennes, tester avec différentes bibliothèques est difficile. L'option "expédier avec vos bibliothèques" apparaît donc presque immédiatement.


Tragédie communautaire


Cela crée les conditions préalables à l'émergence d'une tragédie communautaire:


  • Chaque fabricant (auteur de logiciels) souhaite expédier selon ses besoins. L'adaptation aux règles (versions) des autres est une perte de temps et d'efforts, d'autant plus qu'il existe de nombreuses distributions différentes dans le monde
  • Les utilisateurs veulent de nouvelles versions.

Dans le même temps, plus les applications sont livrées avec leurs bibliothèques, moins l'utilisation des bibliothèques système est importante. Tu te souviens de Grace? Moins elle est «universelle», moins la grâce est. Si une bibliothèque partagée est utilisée par 5 applications différentes sur 995 autres, l'avantage de cette bibliothèque est de 0,5%. C'est dommage, oui. De plus, cela nuit à tous les utilisateurs, même à ceux qui, en principe, n'ont pas un besoin aigu d'une nouvelle fonctionnalité - mais si l'application n'est disponible que sous forme de vente, l'utilisateur n'a pas d'options.


Il s'avère que nous avons un extremum global: toutes les applications utilisent uniquement des bibliothèques partagées (grâce commune maximale, inconvénient pour les auteurs d'applications individuelles) ou "chacune d'elle-même" (une distribution épaisse avec un tas d'applications qui peuvent avoir des vulnérabilités non détectées mais largement utilisées, manger un tas de mémoire, mais l'auteur de chaque application est pratique).


C'est là que nous arrivons au différend rpm / deb VS snap / flatpack


Liberté ou esclavage?


Ubuntu préconise très, très fortement le snap'y. GNOME est convaincu que l'avenir est dans les flatpacks. Chacun d'eux est un cadre pour des applications profondément individualistes. Toutes sortes d'électrons, qui ont avec eux non seulement le capot du compartiment moteur, mais aussi le système d'exploitation du compartiment moteur. Propre libc, propre libssl, propre regexp, propres ncurses, etc. Seul le noyau agit comme commun, c'est-à-dire en fait, c'est la même application conteneurisée, mais pour le bureau. Donnez à chacun votre propre noyau et vous obtenez l'appliance sous la forme d'une machine virtuelle. Ajoutez les métadonnées - et vous obtenez un conteneur Docker.


L'individualisme des applications (auteurs des applications) est compréhensible, mais qui représente alors le bien commun? Une amélioration locale majeure est compensée par une légère dégradation générale de la distribution multipliée par des applications purement. Si tout le monde fait des améliorations locales pour lui-même, le montant de la déficience devient supérieur au bénéfice du montant de l'amélioration.


Il semblerait qu'à cet endroit, les créateurs de distributions devraient agir en tant que gardiens d'intérêt commun. Mais ...


La politique


Ubuntu dépend beaucoup plus de Debian que ne le souhaiterait Canonical (la société Ubuntu). La valeur d'Ubuntu n'est pas dans les efforts des mainteneurs d'Ubuntu, mais dans un énorme référentiel de logiciels provenant de Debian sous une forme où toutes les applications fonctionnent bien ensemble grâce aux efforts de milliers de mainteneurs des paquets individuels qui possèdent la distribution Debian. Canonical ajoute à cela ses efforts pour peaufiner le résultat - et pour cela il est aimé de certains. Ajoutez un peu de marketing et un cycle de vie fixe, ce qui est au goût de l'entreprise, et nous obtenons un excellent produit.


... Ce qui dépend de la volonté de milliers de volontaires quelque part.


Ce qui ne convient pas à presque toutes les entreprises commerciales. Comment briser cette addiction? C'est vrai en créant votre propre bundle d'applications. Plus il y a d'applications, moins les avantages en amont nuiront à l'entreprise. Il suffit de rappeler l'histoire lorsqu'un vote dans Debian sur systemd a enterré le parvenu, développé par Canonical.


Mais maintenez plusieurs dizaines de milliers d'applications, dont certaines sont leur propre espace (erlang, go, perl, python, R, julia, etc.), et certaines sont des monstres dans le domaine correspondant (navigateurs, emacs, tex, stimulateur cardiaque, etc.) - ce sont travaux lourds. Pas étonnant que ce soient des milliers de mainteneurs.


... Et il y a une idée. Et, laissez, les auteurs d'applications eux-mêmes Gérer les applications. Donnons à chacun un bac à sable, laissez-les creuser. Les auteurs obtiennent la liberté, Canonical - des applications qui ne dépendent pas de Debian et qu'au moins quelqu'un gère gratuitement. Les utilisateurs obtiennent ...


... des applications lourdes, lourdes, dont les mises à jour sont irrégulières et qui peuvent facilement garder les vulnérabilités non corrigées pendant des années ... Mais certaines d'entre elles sont neuves.


Et maintenant?


Imaginez un monde dans lequel chacun emporte tout avec lui ... Savez-vous à quoi il ressemble? Jetez un œil à chefsdk. Il expédie avec lui-même à l'intérieur de son postgresql (avec ses dépendances), son rabbitmq (qui dépend de son erlang), plus le chef-serveur est également sur erlang, donc il a aussi son propre erlang. Soudain, nous avons deux erlangs et des dizaines de copies des mêmes bibliothèques dans la même application, légèrement différentes en version. Ce n'est pas la dernière option, car à l'intérieur, il existe encore des bibliothèques communes entre les composants. Si nous les coupons plus loin, nous obtenons plusieurs dizaines de copies d'openssl et de libc pour une application. Pas même dans sa forme finale, il ressemble à 600 Mo par application.


... Ce qui, bien sûr, est un multiple de la moyenne des applications électroniques ... Et 12 fois plus grand que l'ensemble du serveur mariadb (l'ensemble du SGBD!), Ou krita ou gimp (d'énormes applications graphiques).


Et si tout le monde sera comme ça? J'ai 2000 packages installés sur mon ordinateur (sans compter -dev et lib) ... 2000 * 300 = 600GB (Pour la taille moyenne du résultat, j'ai pris la moitié de chefsdk, car tout le monde n'est pas si terrible par les dépendances). Maintenant, ils occupent environ 7 Go (y compris les ressources, telles que la documentation, les éditeurs de texture, les modèles de CAO, etc.).


Si cela se transforme en 600 Go, n'est-ce pas une pure tragédie des communautés? À chaque instant pris, nous observons l'optimisation locale (et la solution des inconvénients de quelqu'un d'autre), mais ensemble, la somme de ces optimisations locales réduit l'optimalité globale du système. À mon avis, plus que le gain local de chacun des participants.


Je comprends pourquoi Canonical pousse instantanément. Je comprends cela et je n'approuve pas.

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


All Articles