69

Subversion を使用すると、 externalsを使用して他のリポジトリの作業コピーを埋め込むことができ、プロジェクト内のサードパーティ ライブラリ ソフトウェアのバージョン管理が容易になります。

これらはライブラリの再利用とベンダー ソフトウェアのバージョン管理には理想的ですが、批判がないわけではありません。

Subversion の外部 (または他のツールで同様のもの) を使用しないでください。これらはアンチパターンであるため、不要です。

外部の使用に隠れたリスクはありますか? それらがアンチパターンと見なされる理由を説明してください。

4

7 に答える 7

71

私は質問の引用の著者です。これは以前の回答からのものです。

ジェイソンが私のような短い発言を疑い、説明を求めるのは正しい。もちろん、その答えのすべてを完全に説明したとしたら、本を書く必要がありました。

Mike が指摘するように、svn:external-like 機能の問題の 1 つは、ターゲット ソースの変更が自分のソースを破壊する可能性があることです。特に、そのターゲット ソースが所有していないリポジトリにある場合はそうです。

私のコメントをさらに説明するにあたり、最初にsvn:external、他のツールや機能と同様に、-like 機能を使用する「安全な」方法があることを述べさせてください。ただし、この機能は悪用される可能性がはるかに高いため、これをアンチパターンと呼んでいます。私の経験では、それは常に誤用されており、そのような安全な方法で使用したり、その使用を推奨したりすることはほとんどありません. さらに、Subversion チームを中傷するつもりはないことに注意してください。私は Subversion が大好きですが、Bazaar に移る予定です。

この機能の主な問題は、あるビルド (「プロジェクト」) のソースを別のビルドのソースに直接リンクすること、またはプロジェクトをバイナリ (DLL、JAR など) にリンクすることを奨励し、通常使用されることです。それが依存するもの。これらの使用はどちらも賢明ではなく、アンチパターンを構成します。

他の回答で述べたように、ソフトウェア ビルドの基本原則は、各プロジェクトが正確に 1 つのバイナリまたは主要な成果物を構築することであると考えています。これは、関心の分離の原則をビルド プロセスに適用したものと見なすことができます。これは、あるプロジェクトが別のプロジェクトのソースを直接参照している場合に特に当てはまり、カプセル化の原則に違反しています。この種の違反のもう 1 つの形式は、サブビルドを再帰的に呼び出してシステム全体またはサブシステムを構築するビルド階層を作成しようとすることです。Maven では、この動作を強く推奨/強制しています。これは、私が推奨しない多くの理由の 1 つです。

最後に、この機能を望ましくないものにするさまざまな実際的な問題があることを発見しました。1 つには、svn:externalいくつかの興味深い行動特性があります (ただし、詳細は今のところわかりません)。もう 1 つの理由として、そのような依存関係をプロジェクト (ビルド プロセス) に明示的に表示する必要があり、ソース管理メタデータとして埋もれないようにする必要があることが常にわかります。

では、この機能を使用する「安全な」方法は何ですか? 作業環境を「設定」する方法など、一時的に 1 人だけで使用する場合だと思います。プログラマーがリポジトリ内に独自のフォルダー (またはプログラマーごとに 1 つ) を作成し、svn:external現在取り組んでいるリポジトリの他のさまざまな部分へのリンクを構成する場所を確認できました。次に、その 1 つのフォルダーをチェックアウトすると、現在のすべてのプロジェクトの作業コピーが作成されます。プロジェクトが追加または終了すると、svn:external定義が調整され、作業コピーが適切に更新されます。ただし、チェックアウトを呼び出すスクリプトでこれを行うなど、特定のソース管理システムに縛られないアプローチを好みます。

記録として、私がこの問題に最近遭遇したのは、2008 年の夏にsvn:external、大規模な規模で使用していたコンサルティング クライアントで発生しました。Ant および Jython ベース (WebLogic 用) のビルド スクリプトは、このマスター作業コピーの上に構築されました。最終的な結果: スタンドアロンで構築できるものは何もなく、文字通り数十のサブプロジェクトがありましたが、単独でチェックアウト/作業するのに安全なものはありませんでした。したがって、このシステムでの作業には、最初に 2 GB を超えるファイルのチェックアウト/更新が必要でした (バイナリもリポジトリに入れました)。何かを成し遂げることは無益な練習であり、私は 3 か月試した後に辞めました (他にも多くのアンチパターンが存在していました)。

編集: 再帰的なビルドについて説明します -

何年にもわたって (特に過去 10 年間)、私はフォーチュン 500 企業や大規模な政府機関向けに、何層にも及ぶディレクトリ階層に配置された何十ものサブプロジェクトを含む大規模なシステムを構築してきました。私は Microsoft Visual Studio プロジェクト/ソリューションを使用して .NET ベースのシステムを整理し、Java ベースのシステムには Ant または Maven 2 を使用し、Python ベースのシステムには distutils と setuptools (easyinstall) を使用し始めました。これらのシステムには、通常、Oracle または Microsoft SQL Server の巨大なデータベースも含まれています。

使いやすさと再現性のために、これらの大規模なビルドを設計することに大きな成功を収めました。私の設計基準は、新しい開発者が初日に現れ、新しいワークステーション (おそらく典型的な OS インストールだけでデルから直接) を与えられ、簡単なセットアップ ドキュメント (通常はインストール手順の 1 ページだけ) を与えられるというものです。また、ワークステーションを完全にセットアップし、完全なシステムをソースから、監視も支援もなしに、半日以内で構築できます。ビルド自体を呼び出すには、コマンド シェルを開き、ソース ツリーのルート ディレクトリに移動し、1 行のコマンドを発行してすべてをビルドする必要があります。

その成功にもかかわらず、このような大規模なビルド システムを構築するには、大規模なビジネス クリティカルなアプリケーション/システムを構築する場合と同様に、細心の注意を払い、堅実な設計原則を厳守する必要があります。重要な部分は、各プロジェクト (単一の成果物/成果物を生成する) には単一のビルド スクリプトが必要であり、明確に定義されたインターフェイス (ビルド プロセスの一部を呼び出すためのコマンド) を備えている必要があることであることがわかりました。他のすべての (サブ) プロジェクトから単独で。歴史的に、システム全体を構築するのは簡単ですが、1 つの部分だけを構築するのは難しい/不可能です。各プロジェクトが真に独立していることを注意深く確認することを学んだのはつい最近のことです。

実際には、これは、少なくとも 2 つのビルド スクリプト層が必要であることを意味します。最下層は、各成果物/アーティファクトを生成するプロジェクト ビルド スクリプトです。そのような各スクリプトは、そのプロジェクト ソース ツリーのルート ディレクトリに存在し (実際、このスクリプトはそのプロジェクト ソース ツリーを定義します)、これらのスクリプトはソース管理について何も知らず、コマンド ラインから実行されることを期待し、プロジェクトのすべてを相対パスで参照します。ビルド スクリプトに追加し、いくつかの構成可能な設定 (環境変数、構成ファイルなど) に基づいて、外部の依存関係 (ツールまたはバイナリ アーティファクト、他のソース プロジェクトではない) を参照します。

ビルド スクリプトの 2 番目のレイヤーもコマンド ラインから呼び出すことを目的としていますが、これらはソース管理について認識しています。実際、この 2 番目のレイヤーは多くの場合、プロジェクト名とバージョンで呼び出される単一のスクリプトであり、名前付きプロジェクトのソースを新しい一時ディレクトリ (おそらくコマンド ラインで指定) にチェックアウトし、そのビルド スクリプトを呼び出します。

継続的インテグレーション サーバー、複数のプラットフォーム、およびさまざまなリリース シナリオに対応するには、さらにバリエーションが必要になる場合があります。

プロジェクト セット全体の特定のサブセットを構築する目的で、(最初のレイヤーを呼び出す) スクリプトの 2 番目のレイヤーを呼び出すスクリプトの 3 番目のレイヤーが必要になる場合があります。たとえば、各開発者は、現在取り組んでいるプロジェクトを構築する独自のスクリプトを持っている場合があります。マスター ドキュメントを生成するため、またはメトリックを計算するために、すべてを構築するスクリプトが存在する場合があります。

とにかく、システムをプロジェクトの階層として扱おうとすると逆効果になることがわかりました。プロジェクトを相互に結び付けて、単独で、または任意の場所 (継続的インテグレーション サーバー上の一時ディレクトリ) または任意の順序 (依存関係が満たされていると仮定) で自由にビルドできないようにします。多くの場合、階層を強制しようとすると、試みる可能性のある IDE 統合が壊れます。

最後に、プロジェクトの大規模な階層を構築すると、パフォーマンスが過度に集中する可能性があります。たとえば、2007 年の春に、Ant を使用して構築した適度なソース階層 (Java と Oracle) を試みましたが、構築は常に Java の OutOfMemoryException で中止されたため、最終的に失敗しました。これは、利用可能なすべてのメモリを使用できるように JVM を調整した 3.5 GB のスワップ スペースを持つ 2 GB RAM のワークステーション上にありました。アプリケーション/システムは、コード量の点では比較的些細なものでしたが、再帰的なビルドの呼び出しにより、どれだけ多くのメモリを割り当てても、最終的にはメモリが使い果たされました。もちろん、実行にも永遠に時間がかかりました (中止されるまでに 30 ~ 60 分が一般的でした)。私は非常にうまく調整する方法を知っていますが、最終的にはツール (この場合は Java/Ant) の限界を超えていました。

ビルドをスタンドアロン プロジェクトとして構築し、それらを完全なシステムに構成してください。軽くて柔軟に保ちます。楽しみ。

編集:アンチパターンの詳細

厳密に言えば、アンチパターンは、問題を解決するように見えても解決しない一般的なソリューションです。これは、重要なギャップを残すか、追加の問題 (多くの場合、元の問題よりも悪い) を導入するためです。ソリューションには、1 つまたは複数のツールと、それらを目前の問題に適用するための手法が必ず含まれます。したがって、ツールまたはツールの特定の機能をアンチパターンと呼ぶのはストレッチであり、人々はそのストレッチを検出して反応しているように見えます。

一方、私たちの業界では技術よりもツールに焦点を当てるのが一般的であるように思われるため、注意を引くのはツール/機能です (ここで StackOverflow に関する質問を簡単に調査すると、簡単に説明できるようです)。私のコメントとこの質問自体は、その慣行を反映しています。

ただし、この場合のように、そのストレッチを行うことが特に正当化される場合があります。一部のツールは、ツールが思考を形作ると主張するところまで、それらを適用するための特定のテクニックにユーザーを「導く」ように見えます(わずかに言い換えられています)。それがアンチパターンであると私が提案するのは、主にその精神にありsvn:externalます。

問題をより厳密に述べると、アンチパターンとは、プロジェクトをソース レベルで結合することを含むビルド ソリューションを設計すること、プロジェクト間の依存関係を暗黙的にバージョン管理すること、またはそのような依存関係を暗黙的に変更できるようにすることです。結果。のような機能の性質上、svn:externalこれらのマイナスの結果を回避することは非常に困難です。

プロジェクト間の依存関係を適切に処理するには、基本的な問題とともにこれらのダイナミクスに対処する必要があり、ツールと手法は別の道をたどります。考慮すべき例はIvyです。これは Maven と同様の方法で役立ちますが、多くの欠点はありません。Java ビルドの問題に対する私の短期的な解決策として、Ant と組み合わせた Ivy を調査しています。長期的には、マルチプラットフォーム ソリューションを促進するオープンソース ツールにコア コンセプトと機能を組み込むことを検討しています。

于 2008-12-05T22:34:10.393 に答える
66

これはまったくアンチパターンではないと思います。私はグーグルでいくつかの簡単な検索を行いましたが、基本的に何も思いつきませんでした... svn:externals の使用が悪い、または有害であると文句を言う人はいません。もちろん、注意しなければならない注意点がいくつかあります...そして、それはすべてのリポジトリに大量に振りかける必要があるものではありません...しかし、元の引用に関しては、それは彼の個人的な(そして主観的な)意見です. 彼は svn:externals について実際に議論したことはありません。その人がどのようにしてその発言をするようになったのかについて、何の裏付けも、少なくとも理由付けもなしに、そのような抜本的な発言は常に疑わしいものです。

とはいえ、external の使用にはいくつかの問題があります。マイクが答えたように、リリースされたソフトウェアの安定したブランチを指すのに非常に役立ちます...特に、すでに制御しているソフトウェアです。ユーティリティ ライブラリなどの多くのプロジェクトで内部的に使用しています。ユーティリティ ライブラリ ベースを拡張して作業する小さなグループがありますが、そのベース コードは多くのプロジェクトで共有されています。さまざまなチームがユーティリティ プロジェクト コードをチェックインするだけでなく、100 万のブランチを処理したくないので、svn:externals は非常にうまく機能します。人によっては、答えにならないかもしれません。ただし、「使用しないでください...」という声明と、これらのツールがアンチパターンを表しているという声明には強く反対します。

于 2008-12-03T22:37:02.700 に答える
19

svn:externalsを使用する場合の主なリスクは、参照されるリポジトリがコードを破壊したり、セキュリティの脆弱性を導入したりする方法で変更されることです。外部リポジトリも管理下にある場合は、これで問題ない可能性があります。

個人的には、私が所有するリポジトリの「安定した」ブランチを指すためにsvn:externalsのみを使用します。

于 2008-12-03T21:56:18.320 に答える
18

古いスレッドですが、外部を変更するとコードが壊れる可能性があるという懸念に対処したいと思います。前に指摘したように、これはほとんどの場合、外部プロパティの不適切な使用が原因です。ほとんどの場合、外部参照は外部リポジトリ URI の特定のリビジョン番号を指す必要があります。これにより、別のリビジョン番号を指すように変更しない限り、外部が変更されないことが保証されます。

エンドユーザー プロジェクトで外部として使用する一部の内部ライブラリについては、Major.Minor バージョンでライブラリのタグを作成すると便利であることがわかりました。この場合、重大な変更は適用されません。4 段階のバージョニング スキーム (Major.Minor.BugFix.Build) により、BugFix.Build の変更によってタグを最新の状態に保つことができます (これも破壊的な変更は適用されません)。これにより、リビジョン番号なしでタグへの外部参照を使用できます。メジャーまたはその他の重大な変更の場合、新しいタグが作成されます。

エクスターナル自体は悪くありませんが、それは人々がそれらの悪い実装を作成することを止めるものではありません。それらを安全かつ効果的に使用する方法を学ぶには、多くの調査は必要ありません。ドキュメントを少し読むだけです。

于 2010-10-05T17:34:49.597 に答える
9

Subversion エクスターナルには明確な欠陥がありますが、現在のプロジェクトが依存するライブラリ (私たち自身とベンダーの両方) を含めるために、それらを合理的にうまく使用しているようです。したがって、私はそれらを「アンチパターン」とは見なしません。私にとって重要な使用上のポイントは次のとおりです。

  • それらは、他のプロジェクトの特定のリビジョンまたはタグ (ヘッドではありません) を指します。
  • それらは、独自のソース コードなどから離れた現在のプロジェクトに挿入されます (たとえば、「サポート ファイル」と呼ばれるサブディレクトリ内)。
  • それらは、他のプロジェクトの「インターフェース」ファイル (例: include フォルダー) とバイナリー・ライブラリー (つまり、他のプロジェクトの完全なソースを取得するわけではありません) のみを参照します。

私も、この取り決めの主要なリスクと、より良いアプローチに興味があります。

于 2008-12-05T23:40:59.977 に答える
9

単純な外部がリポジトリを壊す可能性があるためアンチパターンである場合、明示的なリビジョンを持つものはすべきではありません。

svn bookからの抜粋:

外部定義は、バージョン管理されたリソースの URL** (および場合によっては特定のリビジョン) へのローカル ディレクトリのマッピングです。

それはすべて、機能を使用する目的に依存していると思います。それ自体はアンチパターンではありません。

于 2008-12-05T22:54:21.647 に答える
2

a がbであると言っても、なぜそうであるかを言わない限り aは b にはなりません。

Subversion の外部参照で見られる主な欠陥は、作業コピーを更新するときにリポジトリが存在することが保証されないことです。

Subversion の外部参照は使用および悪用される可能性があり、機能自体はただの機能でしかありません。それはパターンともアンチパターンとも言えません。

私はあなたが引用した人の答えを読みましたが、私は同意しないと言わざるを得ません. プロジェクトでリポジトリのファイル バージョン XYZ が必要な場合は、外部の Subversion 参照で簡単に取得できます。

はい、必要な参照のバージョンを具体的に指定しないと、間違って使用する可能性があります。それはあなたに問題を与えるでしょうか?おそらく!

アンチパターンですか?まあ、それは依存します。引用するテキストの著者によって提供されたリンクをたどると、つまり. ここでは、いいえ。何かが悪い解決策を提供するために使用される可能性があるからといって、それを行う方法全体がアンチパターンになるわけではありません。それがルールである場合、プログラミング言語は概してアンチパターンであると言えます。なぜなら、すべてのプログラミング言語で悪いソリューションを作成できるからです。

于 2008-12-05T23:51:37.040 に答える