Longrid Warnung: Sie wurden gewarnt, viele Briefe.
Es wurde lange Zeit ein Verteilungsformat für Anwendungen entwickelt, die "frei" von systemweiten Abhängigkeiten waren. Ubuntu ist sehr, sehr aktiv bei der Förderung seines Snap-Gnome-Flatpacks. Beide versprechen Paradies und Freiheit von U / min / deb. Lassen Sie uns über das Problem nachdenken, das sie lösen möchten, und über den Preis, den sie für die Lösung dieses Problems verlangen.
Bibliotheken
Niemand in der modernen Welt kann eine Anwendung schreiben, ohne den Code eines anderen zu verwenden. Es gibt mehrere Gründe:
- Viele Bibliotheken sind so ernst, dass das Schreiben ihrer Funktionalität von Grund auf eine entmutigende Aufgabe ist. Beispiele - Unterstützung für Unicode, Schriftwiedergabe, Mathematik.
- Andere Bibliotheken bieten eher bescheidene Funktionen, aber sie sind so gut geschrieben, dass es fast unmöglich ist, zumindest so gut zu schreiben. Standardbibliotheken von Programmiersprachen, verschiedene Implementierungen von libc usw.
- Die Kosten für die Arbeit mit dem Code einer anderen Person (dem dieser Abschnitt gewidmet ist) sind häufig niedriger als die Kosten für die Pflege Ihres Codes. Die Dichte der "Fehler pro Codezeile" ist wahrscheinlich vergleichbar, und Sie müssen Ihre eigenen Fehler selbst abfangen. Ausländische (beliebte) Bibliotheken werden wahrscheinlich von falschen Händen debuggt und korrigiert.
Der Schlüssel ist, dass selbst wenn wir die Funktionalität einer einzelnen Bibliothek selbst aus dem Prinzip heraus schreiben können, die Gesamtzahl der erforderlichen Funktionen (und Abhängigkeiten) die Anzahl der zu lösenden Aufgaben fast exponentiell erhöht und die Startzeit für die Arbeit am Code des Programms selbst verschiebt in die unerreichbare Entfernung.
Ein Beispiel für die Realisierung des Ausmaßes des Dramas: Nehmen wir an, Ihre Anwendung verwendet zwei Eingabezeilen als optionale Argumente und zeigt sie nach der Normalisierung zusammen an. Wenn Sie eine industrielle Anwendung schreiben (eine Anwendung, die wie eine "echte" aussieht), dann:
- Sie benötigen einen Befehlszeilenparser
- Welches sollte Unicode akzeptieren
- Und vielleicht geben Sie dem Benutzer einen Hinweis, dass er den Argumentnamen versiegelt hat
- Was erfordert phonetischen Vergleich
- Und vielleicht reguläre Ausdrücke
- Im Allgemeinen müssen Sie nicht nur Unicode unterstützen, sondern auch andere Gebietsschemas, für die eine Gebietsschema-Unterstützungsbibliothek und ALLE erforderlich sind, die im Kontext von Gebietsschemas erstellt werden.
- Die Verkettung von Zeichenfolgen mit der Normalisierung ist eine weitere Verwendung einer separaten Unicode-Bibliothek, die Sie selbst nicht implementieren.
- Die Ausgabe auf dem Bildschirm (Hilfe in der Befehlszeile, Ihr Ergebnis) erfordert wahrscheinlich Unterstützung für ncurses - eine Bibliothek, die verschiedene Terminals unterstützt (Sie können den Textmodus verwenden, aber Anwendungen verwenden häufig Farbfunktionen).
- Tests beinhalten die Verwendung eines Testframeworks, möglicherweise einer Bibliothek für Moks.
Es ist klar, dass eine solche Komplexität für die „zweizeilige“ Aufgabe eine grobe Überentwicklung darstellt, aber sobald Sie anfangen, etwas mehr zu tun, beginnt die Idee von „alles selbst“ über die Grenzen des Beobachtbaren und Realisierten hinauszugehen.
Wie viele Bibliotheken sind Ihrer Meinung nach erforderlich, um sicherzustellen, dass Curl http (s): // ... funktioniert? Viel. Sie werden eine verwenden, aber die Abhängigkeiten Ihrer Abhängigkeiten sind Ihre Abhängigkeiten.
Copypaste & Vendoring VS Dynamic Linking
Während die Verwendung von Bibliotheken unvermeidlich ist, kann die Verwendung selbst in der Implementierung variieren. Bitte beachten Sie, dass wir zwei wichtige Wörter haben: "Verwendung" und "Implementierung der Verwendung". Was bedeutet Verwendung? In seiner unhöflichsten Form - die Möglichkeit, den Bibliothekscode bei Bedarf aufzurufen. Und hier sind die Implementierungen davon:
- Wir können den Code kopieren, der die Operationen ausführt, die wir benötigen. In Form eines Codeteils (Kopieren und Einfügen), als separates Modul in einer Programmiersprache (Objektdatei für kompilierte Sprachen) oder als separates Modul (für interpretierte Sprachen). Irgendwo direkt daneben steht "Kopieren Sie die Quelldatei der Bibliothek mit der Anwendung in Ihr Verzeichnis". Welche Probleme entstehen dadurch? Das Hauptproblem ist, dass wir (für immer) die Verbindung zum Original verlieren. Selbst wenn der Autor der Originalbibliothek den Fehler korrigiert, wissen wir nichts darüber. Wenn wir den Code nur kopiert haben, kann die nächste Person, die an dem Programm arbeitet, nicht einmal feststellen, dass dieser Code „fremd“ ist. Tatsächlich haben wir den Pfad in der Frage "Von Grund auf neu schreiben" abgeschnitten und den eines anderen genommen. Wir schneiden jedoch nur ein Stück, denn wenn es Fehler in diesem Code gibt (aber sie werden nicht da sein , sie sind da ), erfordert ihre Korrektur die Korrektur, um das Wesentliche des Problems ganz nach unten zu verstehen. Selbst wenn für die Testversion mehrere hunderttausend Zeilen Quellcode und Hunderte von RFCs gelesen werden müssen (sowie Kommentare, dass sich Implementierungen von RFCs unterscheiden), haben wir keine andere Möglichkeit. Der Hauptfehler an dieser Stelle ist, dass wir Informationen verloren haben, dass dieser Code fremd ist. Kommentare in einer Datei zu haben kann helfen, erfordert jedoch eine aktive und tiefgreifende Beteiligung einer Person. Wenn wir in einen Kommentar „aus libfoobar, src / lib / foo.c Version 364a51577f3782dbf8e5d2482ab941980357c492“ schreiben, muss jemand sehen, wo sich libfoobar befindet. Welche Version ist das und was hat sich gegenüber der vorherigen Version geändert? "Um diesen Prozess zu vereinfachen, benötigen wir maschinenlesbare Metainformationen.
- Wenn wir den Code eines anderen mit Metainformationen begleiten und Programme zum Verwalten dieses Codes verwenden (anstelle von Kopieren und Einfügen), wird dies als Verkauf bezeichnet , d. H. kontrollierte Aufnahme des Codes einer anderen Person in Ihren Code. Technisch gesehen kann der Verkauf in der Phase des Quelltextes erfolgen, indem Objekte mit einer ausführbaren Datei verknüpft, Module (in Interpreten) aus der Anwendung importiert oder sogar dynamisch mit "Ihrer" Version der Bibliothek verknüpft werden (dazu später mehr).
- Schließlich können wir beim Start der Anwendung eine dynamische Verknüpfung durchführen. Bei kompilierten Sprachen handelt es sich um gewöhnliche Sprachen, bei interpretierten Sprachen gibt es ein Modul für den systemweiten Import. Wenn mehrere Anwendungen es importieren können, handelt es sich um eine gemeinsam genutzte Bibliothek. Wenn die Anwendung "ihr Modul mitgebracht" hat, ist die Bibliothek "eigen", auch wenn ihre Schnittstelle eine "gemeinsam genutzte Bibliothek" impliziert. Wenn eine Anwendung beispielsweise eine "eigene" Version davon verwendet, unabhängig davon, ob sie sich von der allgemeinen unterscheidet oder nicht, handelt es sich um einen Verkaufsautomaten. Wenn das System importiert wird, handelt es sich um eine gemeinsam genutzte Bibliothek.
Was ist der Unterschied zwischen diesen Methoden? Ich werde kurz Argumente vorbringen, die in vielen Artikeln oft diskutiert wurden. Jedes dieser Argumente bleibt trotz des Vorhandenseins benachbarter Gegenargumente gültig:
- Speichern Sie Speicher (RAM und Festplatte), um die Größe des installierten Systems zu verringern. Je mehr Anwendungen dieselben verwenden, desto größer ist die Speichereinsparung. Im Gegenteil, je mehr "Ihre" Bibliotheken eine Anwendung bringt, desto "fetter" ist sie.
- Die Debatte darüber, wer die Sicherheitsanfälligkeiten überwacht, ist das System (Bereitstellung von Bibliotheksaktualisierungen) oder der Autor der Anwendung (rechtzeitige Aktualisierung).
- Die Lösung von Abhängigkeitskonflikten (Vending löst dieses Problem, da gemeinsam genutzte Bibliotheken von allen Teilnehmern des Prozesses Aufmerksamkeit und Genauigkeit erfordern und manchmal unüberwindbare Schwierigkeiten verursachen), dieselbe legendäre DLL-Hölle.
- Neue Versionen von Bibliotheken - entweder auf Anfrage der Autoren der Anwendung oder auf Entscheidung der Autoren der Distribution. In einem Fall kann der Autor die neue Funktion einbringen, die er benötigt, in einem anderen Fall kann die Distribution eine Verbesserung der vorhandenen Anwendung bewirken, indem etwas Neues in der Bibliothek unterstützt wird (z. B. funktionierten HIDPI-Bildschirme in allen Anwendungen, die dynamisch mit qt / gtk-Bibliotheken verknüpft sind, ordnungsgemäß). .
All diese Themen wurden bereits mehrfach behandelt. Stattdessen möchte ich mich auf die sozialen Aspekte der Wasserscheide „All Mine“ und „All Common“ konzentrieren.
Gesellschaftsvertrag und Power Maintainer
Gemeinsame Bibliotheken sind Kooperation, Macht und Verantwortung. Personen, die bestimmen, welche gemeinsam genutzten Bibliotheken im Betriebssystem verfügbar sind, bestimmen den Softwareherstellern, welche gemeinsam genutzten Bibliotheken sie verwenden können. Viele Softwareprogramme können unterschiedliche Bibliotheken verwenden, und die Angabe der zu verwendenden genauen Version liegt im Ermessen des Linkers (für kompilierte Sprachen) oder des Handlers für Abhängigkeitsdateien (pip, bundler usw.). Wenn alle Anwendungen in der Distribution mit denselben Anforderungen kompiliert werden, kommt die Gnade: Wenn in einer Bibliothek ein Fehler auftritt, aktualisiert der Betreuer dieser Bibliothek die Version, und der Fix wird automatisch auf alle Anwendungen angewendet. Selbst wenn die Anwendung alle zwei Jahre veröffentlicht wird, wird der Fix in der bedingten Öffnung innerhalb einer Woche angewendet. Wenn in einem bestimmten Betriebssystem die Entscheidung getroffen wird, das alte Protokoll und einige Änderungen (z. B. die Benutzeroberfläche) aufzugeben, gelten diese Änderungen auch für alle. Look & Feel in einem allgemeinen Stil, der (möglicherweise) vom Benutzer ein für alle Mal geändert werden kann. Ist das nicht Gnade?
Macht und der Kampf darum
... Diese Gnade erfordert, dass alle Anwendungen mit der ausgewählten Version der Bibliothek arbeiten können. Was aber, wenn eine Anwendung eine sehr, sehr neue Funktion aus der Bibliothek wünscht und alle anderen Anwendungen diese nicht verwenden möchten, da dies beispielsweise keine LTS-Version der Bibliothek ist, d. H. ist es nicht stabil genug? Das Distributionskit kann sich jedoch weigern, "aus Prinzip" auf neue Versionen umzusteigen, da wir den Benutzern nur Fehlerbehebungen und neue Versionen nur in der nächsten Version des Betriebssystems versprochen haben, die (wie) in einem halben Jahr veröffentlicht wird. Und dies verursacht Widerstand bei den Autoren der Anwendung. Mit wem sollen Sie mir sagen, mit welchen Versionen ich arbeiten soll? Ich bin Autor, ich sehe das so. Ich brauche libfoobar 3.14-pre2 oder älter, nicht deine alte langweilige libfoobar 3.10.
... An dieser Stelle schreibt der Autor einfach in die Anwendungsanforderungen libfoobar>=3.14-pre2
. Der Betreuer nimmt und patcht die Anforderung und löscht den Code, der von dieser Bibliothek abhängt. Kann sein. Oder lehnt es einfach ab, eine neue Version mit einer solchen Abhängigkeit zu akzeptieren, bis diese Abhängigkeit (libfoobar 3.16) in der neuen Version der Distribution enthalten ist.
Wenn der Autor wirklich Benutzer benötigt, um die neue Version zu verwenden (z. B. weil der Autor die alte Version nicht unterstützen möchte), sucht er nach Problemumgehungen, um die Anwendung an den Benutzer zu senden.
Das gleiche passiert, wenn es mehrere Distributionen gibt, einige neuere, andere ältere. Das Verwalten älterer Distributionen und das Testen mit verschiedenen Bibliotheken ist schwierig. Die Option "Mit Ihren Bibliotheken versenden" wird also fast sofort angezeigt.
Gemeinschaftstragödie
Dies schafft die Voraussetzungen für die Entstehung einer Gemeinschaftstragödie:
- Jeder Hersteller (Software-Autor) möchte nach Bedarf versenden. Die Anpassung an die Regeln (Versionen) anderer Leute ist eine Verschwendung von Zeit und Mühe, zumal es auf der Welt viele verschiedene Distributionen gibt
- Benutzer möchten neue Versionen.
Je mehr Anwendungen mit ihren Bibliotheken geliefert werden, desto weniger werden gleichzeitig Systembibliotheken verwendet. Erinnerst du dich an Grace? Je weniger es „universell“ ist, desto weniger ist Gnade. Wenn eine gemeinsam genutzte Bibliothek von 5 verschiedenen Anwendungen von 995 anderen verwendet wird, beträgt der Nutzen dieser Bibliothek 0,5%. Es ist eine Schande, ja. Darüber hinaus schmerzt es alle Benutzer, auch diejenigen, die im Prinzip keinen akuten Bedarf an einer neuen Funktion haben. Wenn die Anwendung jedoch nur in Verkaufsform verfügbar ist, hat der Benutzer keine Optionen.
Es stellt sich heraus, dass wir ein globales Extrem haben: Alle Anwendungen verwenden nur gemeinsam genutzte Bibliotheken (maximale gemeinsame Gnade, Unannehmlichkeiten für die Autoren einzelner Anwendungen) oder "jede für sich" (dicke Verteilung mit einer Reihe von Anwendungen, die möglicherweise unentdeckte, aber weit verbreitete Schwachstellen aufweisen). eine Menge Speicher essen, aber der Autor jeder Anwendung ist bequem).
Hier kommen wir zum Streit um RPM / Deb VS Snap / Flatpack
Freiheit oder Sklaverei?
Ubuntu setzt sich sehr, sehr stark für Snap'y ein. GNOME ist zuversichtlich, dass die Zukunft in Flatpacks liegt. Jeder von ihnen ist ein Rahmen für tief individualistische Anwendungen. Alle Arten von Elektronen, die nicht nur die Motorraumhaube, sondern auch das Motorraumbetriebssystem mit sich führen. Eigene libc, eigene libssl, eigene reguläre Ausdrücke, eigene ncurses usw. Nur der Kern wirkt gemeinsam, d.h. Tatsächlich ist dies dieselbe containerisierte Anwendung, jedoch für den Desktop. Geben Sie jedem Ihren eigenen Kern, und Sie erhalten eine Appliance in Form einer virtuellen Maschine. Fügen Sie die Metadaten hinzu - und Sie erhalten einen Docker-Container.
Der Individualismus von Anwendungen (Anwendungsautoren) ist verständlich, aber wer steht dann für das Gemeinwohl? Eine wesentliche lokale Verbesserung wird durch eine leichte allgemeine Verteilungsverschlechterung multipliziert mit reinen Anwendungen ausgeglichen. Wenn jeder für sich selbst lokale Verbesserungen vornimmt, wird das Ausmaß der Beeinträchtigung größer als der Nutzen des Ausmaßes der Verbesserung.
Es scheint, dass an dieser Stelle die Urheber von Distributionen als Verwalter von gemeinsamem Interesse auftreten sollten. Jedoch ...
Politik
Ubuntu hängt viel mehr von Debian ab, als Canonical (die Ubuntu-Firma) möchte. Der Wert von Ubuntu liegt nicht in den Bemühungen der Ubuntu-Betreuer, sondern in einem riesigen Software-Repository, das von Debian in einer Form stammt, in der alle Anwendungen durch die Bemühungen Tausender Betreuer der einzelnen Pakete, denen die Debian-Distribution gehört, gut zusammenarbeiten. Canonical fügt darüber hinaus seine Bemühungen hinzu, das Ergebnis zu verbessern - und dafür wird es von einigen geliebt. Fügen Sie ein wenig Marketing und einen festen Lebenszyklus hinzu, der dem Unternehmen gefällt, und wir erhalten ein großartiges Produkt.
... Was vom Willen Tausender Freiwilliger irgendwo da draußen abhängt.
Welches passt nicht zu fast jedem Handelsunternehmen. Wie kann man diese Sucht brechen? Richtig, indem Sie Ihr eigenes App-Bundle erstellen. Je mehr Anwendungen es gibt, desto weniger Vorteile im Upstream werden dem Unternehmen schaden. Es genügt, sich an die Geschichte zu erinnern, als eine Abstimmung in Debian über systemd den von Canonical entwickelten Emporkömmling begrub.
Aber pflegen Sie mehrere Zehntausende von Anwendungen, von denen einige ihren eigenen Speicherplatz haben (erlang, go, perl, python, R, julia usw.), und einige sind Monster im entsprechenden Themenbereich (Browser, Emacs, Tex, Schrittmacher usw.) - dies sind schwere Arbeit. Kein Wunder, dass dies Tausende von Betreuern sind.
... und da ist eine Idee. Und lassen Sie die Anwendungsautoren selbst Anwendungen pflegen. Geben wir allen einen Sandkasten, lassen wir sie graben. Autoren erhalten Freiheit, Canonical - Anwendungen, die nicht von Debian abhängig sind und die zumindest jemand kostenlos verwaltet. Benutzer erhalten ...
... Anwendungen, die fett und schwer sind, deren Aktualisierungen unregelmäßig sind und die Schwachstellen leicht jahrelang unkorrigiert lassen können ... Aber einige von ihnen sind glänzend neu.
Und was dann?
Stellen Sie sich eine Welt vor, in der jeder alles mit sich trägt ... Wissen Sie, wie es aussieht? Schauen Sie sich chefsdk an. Er versendet mit sich selbst in seinem Postgresql (mit seinen Abhängigkeiten), seinem Rabbitmq (was von seinem Erlang abhängt), und der Chef-Server ist auch auf Erlang, so dass er auch sein eigenes Erlang hat. Plötzlich haben wir zwei Erlangs und Dutzende Kopien derselben Bibliotheken in derselben Anwendung, die sich in der Version geringfügig unterscheiden. Dies ist nicht die letzte Option, da Im Inneren befinden sich noch gemeinsame Bibliotheken zwischen den Komponenten. Wenn wir sie weiter schneiden, erhalten wir mehrere Dutzend Kopien von openssl und libc für eine Anwendung. Nicht einmal in seiner endgültigen Form sieht es aus wie 600 MB pro Anwendung.
... Was natürlich ein Vielfaches der durchschnittlichen Elektronenanwendung ist. ... Und 12-mal größer als der gesamte Mariadb-Server (das gesamte DBMS!) Oder Krita oder Gimp (riesige Grafikanwendungen).
Und wenn alle so sein werden? Ich habe 2000 Pakete auf meinem Computer installiert (ohne -dev und lib) ... 2000 * 300 = 600 GB (Für die durchschnittliche Größe des Ergebnisses habe ich die Hälfte von chefsdk genommen, weil nicht jeder durch Abhängigkeiten so schrecklich ist). Jetzt belegen sie ungefähr 7 GB (einschließlich Ressourcen wie Dokumentation, Textureditoren, CAD-Vorlagen usw.).
Wenn dies zu 600 GB wird, ist das nicht eine reine Tragödie der Gemeinschaften? In jedem Moment beobachten wir die lokale Optimierung (und die Lösung der Unannehmlichkeiten eines anderen), aber zusammen verringert die Summe dieser lokalen Optimierungen die Gesamtoptimalität des Systems. Meiner Meinung nach mehr als der lokale Gewinn jedes Teilnehmers.
Ich verstehe, warum Canonical Druckknöpfe drückt. Ich verstehe das und stimme nicht zu.