多くの競合する依存関係を必要とするソフトウェアの俗語
依存関係地獄 とは、他のソフトウェアパッケージの特定の バージョンに 依存 する ソフトウェアパッケージ をインストールした一部のソフトウェアユーザーが感じる フラストレーションを表す俗語 です 。 [1]
依存関係の問題は、複数のパッケージが同じ 共有 パッケージまたはライブラリに依存しているものの、それらのパッケージがそれぞれ異なるバージョン、かつ互換性のないバージョンに依存している場合に発生します。共有パッケージまたはライブラリが単一のバージョンでしかインストールできない場合、ユーザーは依存パッケージの新しいバージョンまたは古いバージョンを入手することで問題に対処する必要があるかもしれません。その結果、他の依存関係が壊れ、問題が別のパッケージセットにまで及ぶ可能性があります。
問題
依存地獄にはいくつかの形があります
多くの依存関係
アプリケーションは多くの ライブラリ に依存しているため、ダウンロードに時間がかかり、大量のディスク容量が必要になり、移植性も高くなります(すべてのライブラリが既に移植されているため、アプリケーション自体の移植は容易です)。また、すべての依存関係を見つけるのが難しい場合もありますが、リポジトリを用意することで解決できます(下記参照)。これはある程度避けられないことです。特定の コンピューティングプラットフォーム( Java など)で構築されたアプリケーションでは、そのプラットフォームのインストールが必要ですが、他のアプリケーションでは必要ありません。これは、アプリケーションが大きなライブラリの小さな部分を使用している場合( コードのリファクタリング で解決できます )、または単純なアプリケーションが多くのライブラリに依存している場合に特に問題になります。 [2]
依存関係の長い連鎖
app が liba に依存し、 libb が libb に依存し 、... libz に依存している場合 。これは、依存関係を手動で解決する必要がある場合 (たとえば、 app をインストールしようとすると、最初に liba をインストールするように求められ、次に liba をインストールしようとすると、 libb を インストールするように求められ、以下同様に求められる)、「多くの依存関係」とは異なります。ただし、この長い依存関係のチェーン中に、同じパッケージの異なる 2 つのバージョンが必要になるという競合が発生することがあります [3] (以下の 依存関係の競合を参照)。これらの長い依存関係のチェーンは、すべての依存関係を自動的に解決する パッケージ マネージャー を使用することで解決できます 。面倒なこと (すべての依存関係を手動で解決すること) に加えて、手動での解決により、依存関係の循環や競合が隠される可能性があります。
競合する依存関係
あるソフトウェアの依存関係を解決すると、モグラ叩き のように別のソフトウェアの互換性が失われる場合があります 。 app1 が libfoo 1.2に依存し 、 app2 が libfoo 2.0に依存していて 、異なるバージョンの libfoo を 同時にインストールできない場合、 app1 と app2 を 同時に使用することはできません (インストーラが依存関係をチェックする場合はインストールできません)。 可能な場合は、異なる依存関係の同時インストールを許可することでこの問題を解決します。 あるいは、新しい依存関係をインストールするには、既存の依存関係を、それに依存するすべてのソフトウェアとともにアンインストールする必要があります。 Linux システムで異なるディストリビュータからパッケージをインストールすると、依存関係の長いチェーンによって、何千ものパッケージが依存する C 標準ライブラリ ( GNU C ライブラリ など) のバージョンが競合する可能性があるという問題があります。 このような事態が発生すると、ユーザーはそれらのパッケージをすべてアンインストールするように求められます。
循環依存関係
アプリケーションA がアプリケーション B の特定のバージョンに依存していて、そのバージョンがないと実行できない 場合 、アプリケーション Bもアプリケーション A の特定のバージョンに依存していて、そのバージョンがないと実行できない 場合、いずれかのアプリケーションをアップグレードすると、別のアプリケーションが動作しなくなります。このスキームは分岐が深くなる可能性があります。コアシステムに影響したり、ソフトウェア自体を更新したりすると、その影響は非常に大きくなる可能性があります。 特定のランタイムライブラリ ( B ) が機能するために必要なパッケージマネージャ ( A ) は、このライブラリ ( B ) を次のバージョンにアップグレードするときに、プロセスの途中でパッケージマネージャ ( A )自体が動作しなくなる可能性があります。ライブラリ ( B ) のバージョンが正しくないため 、パッケージマネージャ ( A ) は動作しなくなり、ライブラリ ( B )をロールバックまたはダウングレード できなくなります。通常の解決策は、両方のアプリケーションをダウンロードしてデプロイすることです。これは、一時的な環境内から行う場合もあります。
パッケージマネージャーの依存関係
パッケージマネージャー(例: APT )を介して準備されたパッケージをインストールすることで依存関係地獄が発生する可能性は [4] あります が、主要なパッケージマネージャーは成熟しており、公式リポジトリが適切に管理されているため、その可能性は低いです。これは、 Debianの現在のリリースや Ubuntu などの主要な派生ディストリビューションに当てはまります。ただし、パッケージインストーラー(例: RPMパッケージマネージャー (RPM)または dpkg ) を介してパッケージを直接インストールすると、依存関係地獄が発生する可能性があります
ダイヤモンド依存関係
ライブラリ A がライブラリ B と C に依存している場合、 B と Cは 両方ともライブラリ D に依存しますが、 Bは バージョン D.1 を必要とし、 Cは バージョン D.2 を必要とします。最終的な実行ファイルには D のバージョンが1つしか存在できないため、ビルドは失敗します
yum [5] のようなパッケージマネージャは リポジトリ内のパッケージ間で競合が発生しやすく、 CentOS や Red Hat Enterprise Linux などのLinuxディストリビューションでは依存関係地獄を引き起こします。
解決策
依存関係の削除
多くのソフトウェアライブラリは、ほとんどのユーザーのニーズを満たすように、寛大な方法で記述されていますが、ホストコードでは機能のごく一部しか必要とされない場合があります。ソースを調べることで、機能を(ライセンスに関して)はるかにコンパクトな方法で書き直すことができます。一般的に、これによりアプリケーションコードが大幅に削減され、後々のメンテナンスコストが削減され、プログラマーのソフトウェア作成スキルが向上します
バージョン番号
この問題に対する非常に一般的な解決策は、標準化された番号体系を持つことです。ソフトウェアは、各バージョン( メジャーバージョン)に特定の番号を使用し、各リビジョン( マイナーバージョン )にもサブ番号を使用します (例: 10.1、5.7 ) 。メジャーバージョンは、そのバージョンを使用していたプログラムが互換性を失った場合にのみ変更されます。マイナーバージョンは、他のソフトウェアの動作を妨げない程度の単純なリビジョンでも変更される可能性があります。このような場合、ソフトウェアパッケージは、特定のメジャーバージョンと、任意のマイナーバージョン(特定のマイナーバージョン以上)を持つコンポーネントを要求するだけで済みます 。 その ため、マイナーバージョンが変更されても、ソフトウェアパッケージは引き続き動作し、依存関係も正常に解決されます。セマンティックバージョニング(別名「SemVer」 [6] )は、特定の形式の番号を用いてソフトウェアのバージョン管理スキームを作成する技術仕様を作成する取り組みの一例です。
アプリケーションごとのプライベートバージョン
Windows 2000 で導入された Windowsファイル保護は、アプリケーションによるシステムDLL( ダイナミックリンクライブラリ )の上書きを防止しました。開発者は代わりに 、プログラムフォルダに保存されたシステムDLLの複製であるプライベートDLLの 使用を推奨されました 。これにより、カスタム依存関係をプログラムにパッケージ化する必要が生じ、依存関係地獄を防ぐことができます。 [7]
TrueOS ( FreeBSD ベースの オペレーティングシステム )の前身であるバージョン8.2までのPC-BSDは、パッケージと依存関係を /Programs 内の自己完結型ディレクトリに配置することで、システムライブラリのアップグレードや変更による破損を回避しています。 パッケージ管理には 独自の プッシュボタンインストーラ(PBI)を使用しています。 [8]
複数のバージョンの並列インストール
バージョン番号付けソリューションは、バージョン番号付けをオペレーティングシステムがサポートする機能に昇格させることで改善できます。これにより、アプリケーションは一意の名前 と バージョン番号の制約を使用してモジュール/ライブラリを要求できるようになり、ライブラリ/モジュールのバージョン管理の責任をアプリケーションからオペレーティングシステムに効果的に移行できます。共有モジュールは、モジュールの以前のバージョンまたはそれ以降のバージョンに依存するアプリケーションを動作させるリスクなしに、中央リポジトリに配置できます。各バージョンは、同じモジュールの他のバージョンと並んで、独自のエントリを持ちます。
このソリューションは Windows Vista以降の Microsoft Windowsオペレーティングシステムで使用されており、 グローバルアセンブリキャッシュは 、関連サービスを備えた中央レジストリの実装であり、インストールシステム/パッケージマネージャと統合されています。Gentoo Linuxは、 スロットと呼ばれる概念でこの問題を解決し、複数のバージョンの共有ライブラリをインストールできるようにします。 [9]
スマートパッケージ管理
一部の パッケージマネージャーは 、相互に依存するソフトウェアコンポーネントを同時にアップグレードするスマートアップグレードを実行できるため、メジャー番号の非互換性の問題も解決できます
現在の多くの Linux ディストリビューションは、依存関係の問題を解決するために、 リポジトリ ベースのパッケージ管理システムも実装しています。これらのシステムは、 RPMパッケージマネージャ (RPM)、 dpkg 、またはその他のパッケージングシステムの上位層に位置し、1つ以上の定義済み ソフトウェアリポジトリ を検索することで依存関係を自動的に解決するように設計されています 。これらのシステムの例としては、Advanced Packaging Tool( APT )、 Yum 、 Urpmi 、 ZYpp 、 Portage 、 Pacman などがあります。通常、ソフトウェアリポジトリは、 ファイル転送プロトコル (FTP)サイトまたはウェブサイト、ローカルコンピュータ上の ディレクトリ、または ネットワーク 共有 ディレクトリ、あるいはそれほど一般的ではありませんが、CDやDVDなどのリムーバブルメディア上のディレクトリです。これにより、これらのリポジトリにパッケージ化されたソフトウェアの依存関係地獄が解消されます。これらのリポジトリは通常、Linuxディストリビューションプロバイダーによって保守され、世界中に ミラーリングされています 。これらのリポジトリは巨大であることが多いですが、すべてのソフトウェアをそこに収めることは不可能であるため、依存関係地獄は依然として発生する可能性があります。いずれの場合も、リポジトリメンテナーは依存関係地獄に直面しています。 [4]
インストーラーオプション
ソフトウェアごとに依存関係が異なるため、 新しいパッケージを追加するたびにさらに複数のパッケージのインストールが必要になるため、 依存関係の 要件の 悪循環、つまり要件 ツリー が拡大し続ける可能性があります。DebianのAdvanced Packaging Tool( APT )などのシステムは、ユーザーにさまざまな解決策を提示し、ユーザーが必要に応じて解決策を受け入れるか拒否するかを選択できるようにすることで、この問題を解決できます
プログラミングの容易な適応性
アプリケーションソフトウェアが、OS、ウィンドウマネージャ、またはデスクトップ環境を扱うインターフェース層をプログラマが新しい標準や変化する標準に容易に適応させることができるように設計されていれば、プログラマは環境作成者やコンポーネントライブラリ設計者からの通知を監視し、ユーザー向けのアップデートに合わせてソフトウェアを迅速に調整するだけで済みます。しかも、コストと時間のかかる再設計は最小限の労力で済みます。この方法により、プログラマは、自分たちが依存している関係者に対し、関係者にとって負担にならない合理的な通知プロセスを維持するよう圧力をかけるようになるでしょう。
コード開発と保守における厳格な互換性要件
アプリケーションやライブラリが下位互換性を保証した上で開発・保守されていれば、アプリケーションやライブラリはいつでも新しいバージョンに置き換えることができ、何も壊すことはありません。これは多くの依存関係を軽減するものではありませんが、パッケージマネージャやインストーラの作業を大幅に簡素化します。
ソフトウェアアプライアンス
依存関係の問題を回避するもう一つのアプローチは、アプリケーションをソフトウェアアプライアンス として展開することです 。ソフトウェアアプライアンスは、依存関係を事前に統合された自己完結型のユニットにカプセル化するため、ユーザーはソフトウェアの依存関係の解決に煩わされることはありません。代わりに、その負担はソフトウェアアプライアンスの開発者に移ります。 コンテナ とそのイメージ( Docker やDocker Hubなどが提供するもの)は、ソフトウェアアプライアンスの実装と見なすことができます。
ポータブルアプリケーション
完全に自己完結的で、何もインストールする必要がないアプリケーション(または既存の従来型アプリケーションのバージョン)。必要なすべてのコンポーネントが含まれるようにコーディングされているか、必要なすべてのファイルを独自のディレクトリ内に保持するように設計されており、依存関係の問題は発生しません。これらは、接続されているシステムとは独立して実行できる場合が多いです。RISC OS および ROX Desktop for Linuxのアプリケーションは アプリケーションディレクトリを 使用しますが、これはほぼ同じように動作します。プログラムとその依存関係は、独自のディレクトリ(フォルダ)に自己完結しています。 [10]
この配布方法は、 Unix系 プラットフォーム向けに設計されたアプリケーションをWindowsに移植する際にも有効であることが証明されていますが、最も顕著な欠点は、同じ 共有ライブラリ が複数インストールされることです。例えば、 gedit 、 GIMP 、 HexChatのWindowsインストーラーには、ウィジェットのレンダリングに使用する GTK ツールキットの同一のコピーが含まれています 。一方、各アプリケーションで異なるバージョンのGTKが必要な場合は、これが正しい動作であり、依存関係地獄をうまく回避できます。
特定のコンピューティングプラットフォーム では 、 依存関係地獄 は多くの場合、ローカル固有の名前、通常はコンポーネントの名前で呼ばれます
参照
参考文献
^ Michael Jang (2006). Linux annoyances for geeks . O'Reilly Media, Inc. p. 325. ISBN 9780596552244 2012年2月16日 閲覧 。
^ Donald, James (2003年1月25日). 「共有ライブラリの移植性の向上」 (PDF) . プリンストン大学 . 2007年9月26日時点の オリジナル (PDF) からのアーカイブ。 2010年4月9日 閲覧
^ Stevens, Al (2001-05-01). 「見つけられる仕事は良い仕事だ:依存関係カルーセル」 J-DDJ . 26 (5): 121– 124. ISSN 1044-789X. 2011年8月11日時点のオリジナルよりアーカイブ 。 2010年4月10日 閲覧– drdobbs.com/blogより。
^ ab Pjotr Prins; Jeeva Suresh & Eelco Dolstra (2008-12-22). 「Nix fixes dependency hell on all Linux distributions」 linux.com . オリジナルから2015-07-08にアーカイブ 。2013-05-22 に閲覧 。APT 、RPM、FreeBSD Ports Collectionなど、一般的なパッケージマネージャーはすべて、破壊的なアップグレードの問題を抱えています。アップグレードを実行すると、単一のアプリケーションであれオペレーティングシステム全体であれ、パッケージマネージャーは現在システム上にあるファイルを新しいバージョンで上書きします。パッケージが常に完全な下位互換性を持っている限り、これは問題にはなりませんが、現実の世界では、パッケージは完全に下位互換性があるわけではありません。例えば、Firefoxをアップグレードし、パッケージマネージャーがGTKの新しいバージョンも必要だと判断したとします。新しいGTKに下位互換性がない場合、システム上の他のアプリケーションが突然動作しなくなる可能性があります。 Windows の世界では、同様の問題が DLL 地獄として知られていますが、依存関係地獄は、Unix の世界でも同様に、あるいはそれ以上に大きな問題です。これは、Unix プログラムは多くの外部依存関係を持つ傾向があるためです。
^ “Yum Dependency Hell”. 2016年12月19日時点のオリジナルよりアーカイブ 。 2015年12月28日 閲覧。
^ 「プロジェクトウェブサイト: semver.org」。
^ Anderson, Rick (2000年1月11日). 「DLL地獄の終焉」. Microsoft.com . 2001年6月5日時点のオリジナルよりアーカイブ。 2010年7月7日 閲覧 。
^ 「pbiディレクトリ」。2013年3月27日時点のオリジナルよりアーカイブ。
^ "Slotting". gentoo.org . 2025年3月10日 閲覧。
^ 「アプリケーションディレクトリ」 。 2013年 9月7日 閲覧 。
^ Weinstein, Paul (2003年9月11日). 「Linuxは迷惑か?」 linuxdevcenter.com . 2010年4月10日 閲覧 。