プログラミング言語のパッケージマネージャーの基本的な問題

なぜこれほど多くの異なるパッケージマネージャーがあるのですか? 多くのオペレーティングシステム(apt、yum、pacman、Homebrew)と多くのプログラミング言語(Bundler、Cabal、Composer、CPAN、CRAN、CTAN、EasyInstall、Go Get、Maven、npm、NuGet、OPAMの両方で使用できます。 、PEAR、pip、RubyGemsなど)。 「各プログラミング言語には独自のパッケージマネージャーが必要です。これはすでに広く認識されている真実になっています。」 どのような不可解な魅力が、プログラミング言語をこの崖に滑り込ませますか? 既存のパッケージマネージャーを使用しないのはなぜですか?


おそらく、aptを使用してRubyパッケージを管理するのは良い考えではない理由をすでにいくつかお持ちでしょう。 「システムパッケージマネージャーとプログラミング言語のパッケージマネージャーは、まったく異なるものです。 すべてのパッケージの中央配布は素晴らしいですが、GitHubに投稿されたほとんどのライブラリにはまったく適していません。 集中化されたパケット配信が遅すぎる。 すべてのプログラミング言語は異なっており、そのコミュニティは互いに対話しません。 このようなパッケージマネージャーはパッケージをグローバルにインストールし、使用するライブラリのバージョンを管理したいと考えています。」これらの欠点は確かにこのソリューションに存在します。 しかし、彼らはこれらすべての問題の本質を逃しています。

基本的な問題は、さまざまなプログラミング言語のパッケージマネージャーが分散化されていることです。

この分散化は、パッケージマネージャーの定義にも含まれています。これは、インストール時にローカルで利用できなかったリモートソースからプログラムとライブラリをインストールするプログラムです。 理想的な一元化されたパッケージマネージャーを想像しても、このライブラリのコピーは2つあります。1つはサーバー上のどこかに、2つ目はこのライブラリを使用してアプリケーションを作成するプログラマーにローカルに配置されます。 ただし、実際には、ライブラリエコシステムは断片化の影響を大きく受けます。さまざまな開発者が作成した多くのライブラリが統合されます。 もちろん、すべてのライブラリを1か所でロードしてインデックスを作成できますが、これはライブラリの作成者が他のユースケースを知っていることを意味するものではありません。 そして、Perlの世界でDarkPANと呼ばれるものを入手します:存在すると思われる無数のコードですが、それはプロプライエタリコードのどこかに配線されているか、企業のどこかで動作するため、サーバー。 分散化は、アプリケーションのすべてのコードを完全に制御する場合にのみバイパスできます。 しかし、この場合、パッケージマネージャーは必要ないでしょう。 (ところで、私の同僚は、これはWindowsオペレーティングシステムやGoogle Chromeブラウザーなどの大規模プロジェクトには必須であると言っていました。)

分散システムは複雑です。 真剣に、非常に複雑です。 そのようなシステムのアーキテクチャを慎重に検討しないと、依存関係の地獄が予想されます。 この問題に対する「正しい」解決策はありません。異なる世代のパッケージマネージャーが使用するこの問題を解決するために、少なくとも3つの異なるアプローチを挙げることができ、それぞれに長所と短所があります。

ドッキング可能なバージョン。 おそらく最も人気があるのは、開発者が使用するパッケージのバージョンを厳密に示す必要があるという意見です。 このアプローチは、RubyのBundler、PHPのComposer、Pythonのvirtualenvと組み合わせたpip、およびその他のインスパイアされたRuby / node.jsアプローチ(たとえば、Gradle for JavaまたはCargo for Rust)などのマネージャーによって推進されています。 それらのアセンブリの再作成がボールを支配します-これらのパッケージマネージャーは、バージョンを修正するとすぐにパッケージのエコシステム全体が存在しなくなると単純に仮定して、分散の問題を解決します。 このアプローチの主な利点は、コードで使用するライブラリのバージョンを指定できることです。 もちろん、これもマイナスです。これらのライブラリのバージョンを常に管理する必要があります。 通常、バージョンは単に修正され、重要なセキュリティ更新プログラムが公開されても、それらは安全に忘れられます。 すべての依存関係のバージョンを更新するには開発サイクルが必要ですが、この時間はほとんどの場合他のことに費やされます(たとえば、新しい機能の開発)。

安定したバージョン。 パッケージ管理のために、個々のアプリケーション開発者がすべての依存関係を最新の状態に維持するために時間と労力を費やし、アプリケーションおよび相互に正しく動作し続けることを確認する必要がある場合、この作業を集中化する方法はありますか? これにより、別のアプローチが可能になります。承認済みのパッケージが連携して動作する集中リポジトリを作成し、下位互換性を維持しながらバグ修正とセキュリティ更新を発行します。 さまざまなプログラミング言語について、そのようなパッケージマネージャーの実装があります。 私が知っている少なくとも2つは、Python用のAnacondaとHaskell用のStackageです。 しかし、よく見ると、 まったく同じモデルがオペレーティングシステムのパッケージマネージャーで使用されていることがわかります。 システム管理者として、オペレーティングシステムリポジトリで配布されるライブラリをユーザーに優先させることをお勧めします。 OSの新しいリリースバージョンに切り替えるまで、下位互換性が失われることはありません。同時に、常に最新のバグ修正とセキュリティアップデートを使用します。 (はい、新しいバージョンの機能を利用することはできませんが、それ自体は安定性の概念に反しています。)

分散化を検討する。 ここまでは、分散化を容認できるアプローチとはみなさないようにしました。 彼らは、中央リポジトリの必要性と開発者による更新の制御について話しました。 しかし、私たちは赤ちゃんに水をかけないのですか? 集中型アプローチの主な欠点は、すべてのパッケージの安定した動作を保証し、これらのパッケージを最新の状態に保つために行う必要がある膨大な量の作業です。 さらに、絶対にすべてのパッケージが相互に互換性があるとは誰も期待していませんが、それでも特定のカテゴリのパッケージを他のパッケージと使用することを妨げません。 理想的な分散システムでは、このシステムに参加するすべての人がどのパッケージを連携させることができるかを決定するタスクがシフトします。これにより、基本的な疑問が生じます。動作する分散パッケージマネージャーのエコシステムをどのように作成できますか?

ここに私たちを助けることができるいくつかの原則があります:

  1. 依存関係の厳密なカプセル化。 依存関係の地獄をそんなに潜んでいる問題にしている理由の1つは、パッケージの依存関係がコアAPIの不可欠な部分であることが多いことです。したがって、依存関係の選択はアプリケーション全体に影響するグローバルな選択の多くです。 ライブラリが内部で依存関係を使用し、この選択がこのライブラリの内部実装の詳細によってのみ完全に決定される場合、グローバルな制限につながるべきはありません 。 NPM for NodeJSは、この原則を論理的な限界まで引き上げます。デフォルトでは、依存関係の重複を制限せず、各ライブラリが依存パッケージの独自のインスタンスをロードできるようにします。 私は絶対にすべてのパッケージを複製する価値があるとは思いませんが(これはJavaのMavenエコシステムで見つかります)、このアプローチが依存関係の構成可能性を高めることに同意します。
  2. セマンティックバージョニングの促進。 分散システムでは、ライブラリ開発者がライブラリに関するできるだけ正確な情報を提供し、パッケージを操作するユーザーとユーティリティが情報に基づいた意思決定を行えるようにすることが特に重要です。 異なるバージョン形式とバージョン範囲は、すでに難しいタスクを複雑にしているだけです(以前の投稿で書いたように)。 セマンティックバージョン使用する機会がある場合、またはセマンティックバージョンの代わりに、インターフェースで型レベルの依存関係を示すより適切なアプローチを使用する場合は、ユーティリティでより適切な選択を行うことができます。 分散システムの情報の「ゴールドスタンダード」は「パッケージAはパッケージBと互換性があります」であり、この情報は分析が非常に難しい(または、動的な型付けを行うシステムでは不可能)ことがよくあります。
  3. 特別な機会のための集中化。 分散システムの原則の1つは、各参加者が自分に最適な環境を収集できることです。 これは、中央のソースを選択したり、独自のソースを作成および使用する際の特定の自由-特別な場合の中央集権化を意味します。 ユーザーがオペレーティングシステムで使用されるスタイルで独自のリポジトリを作成すると想定した場合、これらのリポジトリを簡単に作成して使用できるツールを提供する必要があります。


長い間、ソースコードエコシステムは集中システムを中心に完全に構​​築されていました。 Gitなどのバージョン管理システムの普及により状況は根本的に変わりました。Gitは、技術から習熟までの人々にとってSubversionよりも複雑に見えるかもしれませんが、分散化の利点ははるかに広く多様です。 しかし、パッケージ管理用に同じGitを作成できた人はまだいません。 パッケージ管理の問題が解決し、Bundlerを再発明したことを誰かが保証した場合は、分権化について適切に考えてください。

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


All Articles