web-dev-qa-db-ja.com

生成されたコードをソース管理に保存する必要がありますか

これは私が参加している議論です。もっと多くの意見や見解を得たいと思います。

DB操作を処理するためにビルド時に生成されるいくつかのクラスがあります(この特定のケースでは、SubSonicを使用しますが、質問にはそれほど重要ではないと思います)。生成はVisual Studioの事前ビルドステップとして設定されます。したがって、開発者(または公式のビルドプロセス)がビルドを実行するたびに、これらのクラスが生成され、プロジェクトにコンパイルされます。

現在、一部の人々は、これらのクラスをソース管理に保存すると混乱が生じる可能性があり、取得したコードが自分の環境で生成されたものと一致しないと主張しています。

コードが通常ブラックボックスとして扱われる場合でも、コードの履歴を追跡する方法が必要です。

引数または反対引数はありますか?


上記の理由により、現時点では承認された回答を選択しません。

101
Ron Harlev

ソース管理にそれを保存することは、それが価値があることよりも厄介です。

ビルドを行うたびにコミットを実行して、値を設定する必要があります。

一般的に、私が生成したコード(idl、jaxbなど)は、私が作業するソース管理の外部に置いてあり、問題にはなりません

47
Glen

自分の個人リポジトリでソースツリーの変更を表示するたびに、すべての「生成されたファイル」が変更され、コミットする必要があると表示されます。

私は、自動生成された変更ではなく、実行された実際の更新のみを含む修正の明確なリストを用意したいと思います。

それらを省略して、ビルド後に、生成された各ファイルに「無視」を追加します。

31
Kieveli

ソースコード管理に配置します。作成したすべての履歴を将来の開発者が利用できるようにする利点は、同期後に時々再構築するというわずかな痛みよりも重要です。

30
JaredPar

このように見てください。オブジェクトファイルをソース管理にチェックインしていますか?生成されたソースファイルは、オブジェクトファイル、ライブラリ、実行可能ファイルと同様にビルドアーティファクトです。彼らは同じように扱われるべきです。ほとんどの場合、生成されたオブジェクトファイルと実行可能ファイルをソース管理にチェックインするべきではないと主張します。同じ引数が生成されたソースに適用されます。

生成されたファイルの履歴バージョンを確認する必要がある場合は、そのソースの履歴バージョンに同期して再構築できます。

生成されたファイルをソース管理にチェックインすることは、データベースの非正規化に似ています。これを行うにはときどき理由がありますが(通常はパフォーマンスのため)、データが非正規化されると正確さと一貫性を維持することが非常に難しくなるため、これは十分に注意して行う必要があります。

25

生成されたコード(または他のアーティファクト)をソース管理に追加することは避けるべきだと思います。生成されたコードが特定の入力に対して同じである場合は、比較するバージョンをチェックアウトして、比較のためにコードを生成できます。

20
FeatureCreep

DRY原則と呼びます。ビルド時にこれらのコードファイルを生成するために使用される「ソースファイル」がリポジトリにすでにある場合、同じコードをコミットする必要はありません。二回」。

また、たとえばコード生成がいつか壊れると、この方法でいくつかの問題を回避することができます。

17
John Smith

チェックインすべきではないと思います。

確かに、生成されたコードの変更はノイズになる-環境間の変更、または何か他の結果としての変更-例えばDBの変更。 DBの作成スクリプト(またはその他の依存関係)がソース管理にある場合、なぜ生成されたスクリプトも必要なのですか?

14
thatismatt

いいえ、3つの理由があります。

  1. ソースコードは、現在または以前の特定の時点におけるアプリケーションのスナップショットを再現するために必要かつ十分なものすべてです。これが意味することの一部は、チェックインされたすべてに対して誰かが責任を負うことです。一般的に、私は自分が書くコードに対して責任がありますが、自分が書いたものの結果として生成されるコードには責任がありません。

  2. 私は、誰かが最新のものであるかどうかにかかわらず、中間コードを使用してプライマリソースからビルドをショートカットしようとする誘惑に駆られたくありません(さらに重要なことに、私は責任を受け入れたくありません)。それもまたそうではありません。一部の人々は、部分的なビルドに基づいて中間コードの競合をデバッグすることについて、無意味なプロセスに巻き込まれがちです。

  3. ソース管理に入ると、私は責任を負います。そこにある、b。それが最新のものであり、c。そこにある他のすべてのものと確実に統合できます。これには、使用しなくなったときに削除することも含まれます。その責任が少ないほど良い。

13
dkretz

一般的なルールはnoですが、コードの生成に時間がかかる場合(DBアクセス、Webサービスなどのため)、キャッシュされたバージョンをソース管理に保存し、全員を保存することができます。痛み。

ツールもこれを認識し、必要に応じてソース管理からのチェックアウトを処理する必要があります。ツールが多すぎると、理由もなくソース管理からチェックアウトすることになります。
優れたツールは、キャッシュされたバージョンを変更せずに使用します(またはファイルのタイムステップを変更しません)。

また、人々がファイルを変更しないように、生成されたコード内に大きな警告を入れる必要があります。上部の警告は十分ではなく、数十行ごとに繰り返す必要があります。

8
Shay Erlichmen

生成されたDBコードも保存しません。生成されているため、ソースファイルから任意のバージョンで自由に取得できます。それを格納することは、バイトコードなどを格納するようなものです。

ここで、特定のバージョンで使用されるコードジェネレーターが使用可能であることを確認する必要があります。新しいバージョンは異なるコードを生成する可能性があります...

6
PhiLho

はなれる。

生成されたファイルをチェックインしている場合は、何か問題があります。何が悪いのかは異なるかもしれません、それはあなたのビルドプロセスが非効率的であるか、何か他のものかもしれませんが、私はそれを見ることができませんeverは良い考えです。履歴は、生成されたファイルではなく、ソースファイルに関連付ける必要があります。

違いを解決して、ビルドで生成されなくなったファイルを見つけ、それらを削除しようとする人々にとって頭痛の種になるだけです。

生成されたファイルをチェックインする人には、苦痛の世界が待っています!

5
rich

生成されたファイルをチェックインする特別なケースがあります。他のファイルの生成に使用されるツールが利用できないシステム上でビルドする必要がある場合です。この典型的な例、および私が作業しているものの1つが、LexおよびYaccコードです。多種多様なプラットフォームとアーキテクチャでビルドおよび実行する必要があるランタイムシステムを開発しているため、CおよびC++コンパイラーを使用できるのはターゲットシステムのみであり、インターフェース定義の字句解析/解析コードの生成に必要なツールは使用できません翻訳者。したがって、文法を変更するときは、生成されたコードをチェックインして解析します。

4
Phil Miller

少し遅れて到着しました...とにかく...

コンパイラの中間ファイルをソースバージョン管理に入れますか?コード生成の場合、定義上、ソースコードはジェネレーターの入力ですが、生成されたコードは「実際の」ソースとビルドされたアプリケーションの間の中間ファイルと見なすことができます。

だから私は言うでしょう:生成されたコードをバージョン管理下に置かず、ジェネレータとその入力を配置します。

具体的には、私が記述したコードジェネレーターを使用します。生成されたソースコードをバージョン管理下で維持する必要はありませんでした。ジェネレーターが特定の成熟度レベルに達したため、入力(たとえば、モデルの説明)が変更されても、生成されたコードの内容を観察する必要はなかったとも言えます。

4
dilig0

構成管理(バージョン管理は一部に過ぎません)の仕事は、次のことを実行できるようにすることです。

  • 提供されたすべてのビルドにどの変更とバグ修正が行われたかを把握します。
  • 元のソースコードから始めて、提供されたビルドを正確に再現できます。自動生成されたコードは、言語に関係なく「ソースコード」としてカウントされません。

1つ目は、クライアントまたはエンドユーザーに「先週報告したバグが修正され、新機能が追加された」ことを伝えると、2時間後に戻って「いいえ、そうではありません」と言わないようにします。また、「なぜXを使用しているのですか?私たちはXを要求しなかった」と言わないようにします。

2つ目は、クライアントまたはエンドユーザーが1年前に発行したあるバージョンのバグを報告したときに、そのバージョンに戻ってバグを再現し、修正して、修正がバグではなくバグを排除したことを証明できることを意味しますコンパイラーの混乱やその他の修正。

つまり、コンパイラ、ライブラリなどもCMの一部である必要があります。

だから今あなたの質問に答えましょう:上記のすべてを行うことができれば、とにかく同じ答えを得ることが保証されているので、中間表現を記録する必要はありません。上記のすべてを行うことができない場合、同じことを2回実行して同じ答えを得ることが保証できないため、すべての賭けは無効になります。したがって、すべての.oファイルもバージョン管理下に置くことができます。

3
Paul Johnson

一部のプロジェクトでは、生成されたコードをソース管理に追加しますが、それは実際に依存しています。私の基本的なガイドラインは、生成されたコードがコンパイラーの組み込み部分である場合、追加しません。この場合、生成されたコードがSubSonicなどの外部ツールからのものである場合は、ソース管理に追加します。コンポーネントを定期的にアップグレードする場合、バグや問題が発生した場合に備えて、生成されたソースの変更点を知りたいです。

生成されたコードをチェックインする必要がある限り、最悪のシナリオは手動でファイルを差分化し、必要に応じてファイルを元に戻すことです。 svnを使用している場合は、svnにpre-commitフックを追加して、ファイルが実際に変更されていない場合にコミットを拒否できます。

3
Ryan

ここで提示された賛否両論の良い議論があります。記録のために、私はVisual StudioでT4生成システムを構築し、デフォルトの既定のオプションにより、生成されたコードがチェックインされます。チェックインしたくない場合は、もう少し努力する必要があります。

私にとって重要な考慮事項は、入力またはジェネレータ自体が更新されたときに生成された出力を比較することです。

出力をチェックインしていない場合は、ジェネレータをアップグレードしたり入力を変更したりする前に、生成されたすべてのコードのコピーを取得して、新しいバージョンの出力と比較できるようにする必要があります。これはかなり退屈なプロセスだと思いますが、チェックインされた出力では、新しい出力をリポジトリと比較するのは簡単なことです。

この時点で、「なぜ、生成されたコードの変更を気にするのですか?」 (特にオブジェクトコードと比較した場合)いくつかの重要な理由があると思います。これらの理由は、固有の問題ではなく、現在の最新技術に帰着します。

  1. 生成されたコードと緊密に一致する手書きのコードを作成します。最近のobjファイルでは、そうではありません。生成されたコードが変更されると、悲しいことに、手書きのコードを変更して一致させる必要がある場合がよくあります。多くの場合、生成されたコードの拡張ポイントとの高度な下位互換性はありません。

  2. 生成されたコードは、単にその動作を変更します。コンパイラーからこれを容認することはできませんが、公平に言うと、アプリケーションレベルのコードジェネレーターは、受け入れ可能なソリューションの範囲が広い別の問題分野を対象としています。以前の動作について行った仮定が今は破られているかどうかを確認することが重要です。

  3. ジェネレーターの出力がリリースごとに100%信頼されないだけです。厳密なコンパイラベンダーでビルドおよび保守されていなくても、ジェネレータツールから得られる価値はたくさんあります。リリース1.0はアプリケーションに対して完全に安定していた可能性がありますが、おそらく1.1には、ユースケースにいくつかの不具合があります。あるいは、入力値を変更して、以前に使用したことのないジェネレーターの新しい部分を実行していることを発見します-結果に驚かれる可能性があります。

基本的に、これらすべてのことはツールの成熟度に帰着します。ほとんどのビジネスアプリのコードジェネレーターは、コンパイラーやLex/yaccレベルのツールでさえ何年も前からあったレベルに近くありません。

2
GarethJ

正解は「依存する」です。それはクライアントのニーズに依存します。コードを特定のリリースにロールバックし、それなしで外部監査に耐えることができれば、まだしっかりした基盤にありません。開発者としては、「ノイズ」、痛み、ディスク容量だけでなく、知的財産を生成する役割が課せられており、法的な問題が発生する可能性があるという事実を考慮する必要があります。 2年前に顧客が見たとおりにWebサイトを再生成できることを裁判官に証明できますか?

Gendされたファイルを保存するか保存しないかは、おそらく間違っていると判断した件名の専門家に関与していないかどうかを判断する方法は問わない。

私の2セント。

2
James Fleming

どちらの側にも正当で合理的な議論があり、共通点について合意することは困難です。バージョンコントロールシステム(VCS)は、開発者がそこに入れたファイルを追跡し、VCS内のファイルは開発者によって手動で作成され、開発者は履歴とファイルの任意のリビジョン間の変更に関心があることを前提としています。この仮定は、「チェックアウト時にこのファイルを取得したい」という2つの概念を等しくします。 「このファイルの変更に興味があります。」

さて、両側からの議論は次のように言い換えることができます:

  • 「このマシンでファイルを生成するツールがないので、チェックアウト時にこれらの生成されたファイルをすべて取得したいのです。」
  • 「このファイルの変更に興味がないので、VCSに入れるべきではありません。」

幸いなことに、2つの要件は根本的に矛盾していないようです。現在のVCSを拡張すると、両方を使用できるようになります。つまり、これは誤ったジレンマです。しばらく考えてみると、問題がVCSが保持しているという仮定から生じていることを理解するのは難しくありません。 VCSは、開発者が手作業で作成したファイルと、開発者が手作業で作成したのではなく、このVCS内にあるファイルを区別する必要があります。通常、ソースファイル(コード)と呼ばれる最初のカテゴリのファイルについては、VCSは素晴らしい仕事をしています。後者のカテゴリーについては、VCSは私が知る限り、そのような概念をまだ持っていません。

概要

私が意味することを説明するために、一例としてgitを取り上げます。

  • git statusはデフォルトでは生成されたファイルを表示しません。
  • git commitは、生成されたファイルをスナップショットとして含める必要があります。
  • git diffはデフォルトでは生成されたファイルを表示しません。

PS

回避策としてGitフックを使用できますが、Gitがネイティブでサポートしていると便利です。 gitignoreは要件を満たしていません。無視されたファイルはVCSに入りません。enter code here

2
Albert Netymk

それは本当に依存します。最終的に、目標は、必要に応じて、持っていたものを再現できるようにすることです。バイナリを正確に再生成できる場合は、バイナリを保存する必要はありません。ただし、コンテンツを再作成するには、最初に行った正確な構成が必要になる可能性があることを覚えておく必要があります。これは、ソースコードだけでなく、ビルド環境、IDE、場合によっては他のライブラリも意味します、ジェネレーターなど、使用した正確な構成(バージョン).

ビルド環境を新しいバージョンにアップグレードしたり、以前の正確なバイナリーを再作成できなかった別のベンダーにアップグレードしたりすると、プロジェクトで問題が発生しました。特にセキュリティ保護された環境で、提供されるバイナリが一種のハッシュに依存し、コンパイラのアップグレードなどにより、再作成されたファイルが何らかの形で異なる場合、これは本当に痛みです。

だから、あなたは生成されたコードを保存しますか?私はノーと言うでしょう。リリースされたバイナリーまたは成果物(私が保管したもので複製したツールを含む)。そして、それらをソース管理に保存する必要はありません。それらのファイルの適切なバックアップを作成するだけです。

2
nojevive

はい、あなたはそれをソース管理下に置きたいと思います。構成管理の観点からは、ソフトウェアビルドの作成に使用されるすべてのものを再作成できるように制御する必要があります。生成されたコードは簡単に再作成できることを理解していますが、2つのビルド間で日付/タイムスタンプが異なるため、同じではないという主張をすることができます。政府などの一部の地域では、多くの場合、これが行われます。

1
Mark

I (regretfully) wind up putting a lot of derived sources under source control because I work remotely with people who either can't be bothered to set up a proper build environment or who don't have the skills to set it up so that the derived sources are built exactly right. (And when it comes to Gnu autotools, I am one of those people myself! I can't work with three different systems each of which works with a different version of autotools—and only that version.)

この種の困難は、請求書を支払った人が均一なビルド環境を要求できる有料プロジェクトよりも、パートタイムのボランティアのオープンソースプロジェクトに当てはまるでしょう。

これを行うと、基本的には、1つのサイトでのみ、または適切に構成されたサイトでのみ派生ファイルを構築することになります。 Makefiles(または何でも)は、それらが実行されている場所を通知するように設定する必要があり、安全なビルドサイトで実行されていることがわかっている場合を除き、ソースの再派生を拒否する必要があります。

1
Norman Ramsey

多くの理由で、生成されたコードをソース管理に含めます。多くの人がすでに言っていることを繰り返しますが、私がそれをするいくつかの理由は

  1. ソース管理のコードファイルを使用すると、Visual Studioの事前ビルド手順を使用せずにコードをコンパイルできる可能性があります。
  2. 2つのバージョン間で完全な比較を行う場合、生成されたコードが手動で確認することなく、これら2つのタグ間で変更されたかどうかを確認すると便利です。
  3. コードジェネレーター自体が変更された場合は、生成されたコードへの変更が適切に変更されるようにする必要があります。つまり、ジェネレータが変更されても、出力が変更されない場合、コードをコミットしても、以前に生成されたものと生成されたコードの内容に違いはありません。
1
Joe Enos

それがソースコードの一部である場合は、だれが何を生成したかに関係なく、ソース管理に配置する必要があります。ソース管理に、システムを再生成せずにシステムの現在の状態を反映させる必要があります。

1
mezoid

一般に、このコードのリビジョン履歴は、それを生成したコードのリビジョン履歴によって追跡できるため、生成されたコードをソース管理に保存する必要はありません。

ただし、OPが手動でコードを作成する代わりに、生成されたコードをアプリケーションのデータアクセスレイヤーとして使用しているようです。この場合、ビルドプロセスを変更し、コードをソース管理にコミットします。これは、ランタイムコードの重要なコンポーネントであるためです。これにより、開発者が異なるブランチに対して異なるバージョンのツールを使用する必要がある場合に備えて、コード生成ツールへの依存がビルドプロセスから削除されます。

すべてのビルドではなく、コードを生成する必要があるのは1回だけのようです。開発者がオブジェクトがデータベースにアクセスする方法を追加/削除/変更する必要がある場合、手動で変更を加えるのと同じように、コードを再度生成する必要があります。これにより、ビルドプロセスが高速化され、データアクセスレイヤーを手動で最適化できるようになり、データアクセスレイヤーの履歴が簡単な方法で保持されます。

1
benson

私は主張するでしょう。コードをチェックアウトし、ビルド番号を変更し、ソフトウェアをビルドしてからテストする継続的インテグレーションプロセスを使用している場合は、そのコードをリポジトリの一部にするだけの方が簡単で簡単です。

さらに、ソフトウェアリポジトリから取得するすべての「スナップショット」の一部です。ソフトウェアの一部である場合は、リポジトリの一部である必要があります。

1
womp

双方に非常に強力で説得力のある意見があるようです。上位投票の回答をすべて読んでから、特定のケースに適用される引数を決定することをお勧めします。

更新:1つの決定的な答えがあると本当に信じていたので、私はこの質問をしました。すべての回答を見ると、そのような回答はないと確信できます。この決定は、複数のパラメーターに基づいて行う必要があります。他の回答を読むことは、この問題について決定する必要があるときに自問する必要がある種類の質問に非常に良いガイドラインを提供する可能性があります。

0
Ron Harlev

生成されたファイルoutはソースツリーのままにしておきますが、それをin別のビルドツリーにします。

例えばワークフローは

  1. 通常、ソースをチェックイン/アウト/変更/マージします(生成されたファイルはありません)
  2. 適切な機会に、ソースツリーをクリーンなビルドツリーにチェックアウトします
  3. ビルド後、監査/規制目的で存在する必要があるすべての「重要な」ファイル(「実際の」ソースファイル、実行可能ファイル+生成されたソースファイル)をチェックインします。これにより、リリース/テストスナップショットなどに関連し、日々の開発から切り離された時間増分で、適切なすべての適切な生成コード+実行可能ファイル+履歴が提供されます。

Subversion/Mercurial/Git/etcには、両方の場所にある実際のソースファイルの履歴を結び付けるための良い方法がおそらくあります。

0
Jason S