web-dev-qa-db-ja.com

プロジェクトを複数のサブプロジェクトに分離する場合

私が取り組んでいるプロジェクトを1つではなく2つのリポジトリに分割することが理にかなっているのかどうか知りたいのですが。

私が言えることから:

  • フロントエンドはhtml + jsで記述されます
  • .netのバックエンド
  • バックエンドはフロントエンドに依存せず、フロントエンドはバックエンドに依存しません
  • フロントエンドは、バックエンドに実装されたRESTful APIを使用します。
  • フロントエンドは、任意の静的httpサーバーでホストできます。

現在のところ、リポジトリの構造は次のとおりです。

ルート:

  • フロントエンド/*
  • バックエンド/ *

両方のプロジェクトを同じリポジトリに保持するのは間違いだと思います。両方のプロジェクトには相互に依存関係がないため、個々のリポジトリに属し、必要に応じてサブモジュールを持つ親リポジトリに属している必要があります。

それは無意味であり、それを行うことから何の利益も得られないと私は言われました。

ここに私の議論のいくつかがあります:

  • 相互に依存しない2つのモジュールがあります。
  • 長期的に両方のプロジェクトのソース履歴があると、状況が複雑になる可能性があります(探しているバグとはまったく関係のないコミットの半分を持っている間に、フロントエンドで何かを履歴で検索してみてください)
  • 競合とマージ(これは起こり得ないことですが、誰かがバックエンドにプッシュすると、他の開発者がバックエンドの変更をプッシュフロントエンドの変更にプルすることになります。)
  • 1人の開発者がバックエンドでのみ作業する可能性がありますが、常にフロントエンドまたは他の方法でプルする必要があります。
  • 長期的には、いつ展開するか。ある方法では、フロントエンドは、1つのバックエンドサーバーを持ちながら、複数の静的サーバーに展開できます。いずれの場合も、バックエンド全体を複製するか、すべてのサーバーにフロントエンドのみをプッシュするか、バックエンドを削除するカスタムスクリプトを作成する必要があります。 1つだけが必要な場合は、両方よりもフロントエンドまたはバックエンドのみをプッシュ/プルする方が簡単です。
  • 反論(1人が両方のプロジェクトで作業する可能性があります)、サブモジュールを使用して3番目のリポジトリを作成し、それを使用して開発します。履歴は個別のモジュールに分離されており、バックエンド/フロントエンドのバージョンが実際に同期して連携するタグをいつでも作成できます。 1つのリポジトリでフロントエンドとバックエンドの両方を一緒に使用しても、それらが一緒に機能するとは限りません。両方の履歴を1つの大きなリポジトリにマージしているだけです。
  • プロジェクトにフリーランサーを追加したい場合、サブモジュールとしてフロントエンド/バックエンドを用意すると、物事が簡単になります。場合によっては、コードベースへの完全なアクセス権を付与したくないことがあります。 「外部の人」が見たり編集したりできるものを制限したい場合は、1つの大きなモジュールがあると状況が難しくなります。
  • バグの紹介とバグの修正、フロントエンドに新しいバグを挿入しました。次に、誰かがバックエンドのバグを修正します。 1つのリポジトリでは、新しいバグの前にロールバックするとバックエンドもロールバックされ、修正が困難になる可能性があります。フロントエンドのバグを修正しながらバックエンドを機能させるには、別のフォルダーにバックエンドのクローンを作成する必要があります...その後、再マージを試みます... HEADで他のリポジトリが変更されることはありません。また、異なるバージョンのバックエンドに対するテストは簡単です。

彼らを説得するために誰かが私にもっと多くの議論を与えることができますか、少なくともプロジェクトを2つのサブモジュールに分割することが無意味な(より複雑な)理由を教えてもらえますか?プロジェクトは新しく、コードベースは数日前のものなので、修正するのに早すぎません。

33

私の会社では、システムのすべてのコンポーネントに個別のSVNリポジトリを使用しています。それは非常にイライラすることをあなたに言うことができます。私たちのビルドプロセスには、非常に多くの抽象化レイヤーがあります。

これはJavaで行うため、javacコンパイル、JibXバインディングコンパイル、XML検証などのビルドプロセスが重いです。

あなたのサイトでは、実際に「構築」していなければ(Vanilla PHPなど)、それほど大したことではないかもしれません。

製品を複数のリポジトリに分割することの欠点

  1. ビルド管理-コードをチェックアウトし、自己完結型のビルドスクリプトを実行して、実行可能/インストール可能/デプロイ可能な製品を作成することはできません。複数のリポジトリに出て、複数の内部ビルドスクリプトを実行し、アーティファクトをアセンブルする外部ビルドシステムが必要です。
  2. 変更の追跡-誰が何を、いつ、なぜ変更したかを確認します。フロントエンドのバグ修正でバックエンドの変更が必要な場合、後で参照するための2つの分岐パスがあります。
  3. 管理-管理が必要なユーザーアカウント、パスワードポリシーなどの数を本当に2倍にしますか?
  4. マージ-新機能により、多くのコードが変更される可能性があります。プロジェクトを複数のリポジトリに分割することで、必要なマージの数を増やします。
  5. ブランチの作成-ブランチの作成と同じように、ブランチを作成するには、各リポジトリにブランチを作成する必要があります。
  6. タグ付け-コードのテストが成功したら、リリースのバージョンにタグを付けます。これで、作成するタグが複数あり、各リポジトリに1つあります。
  7. 何かを見つけるのは難しい-多分フロントエンド/バックエンドは簡単ですが、それは滑りやすい斜面になります。十分な数のモジュールに分割した場合、開発者は、一部のコードがソース管理のどこにあるかを調査する必要がある場合があります。

私の場合は少し極端です。私たちの製品は14の異なるリポジトリに分割されており、各リポジトリは4〜8個のモジュールに分割されています。覚えていると思いますが、80個程度の「パッケージ」があり、すべて個別にチェックアウトしてから組み立てる必要があります。

バックエンド/フロントエンドのみの場合のケースはそれほど複雑ではないかもしれませんが、私はそれに対してアドバイスします。

極端な例は、ほとんど何でも賛成または反対の説得力のある議論になり得ます:)

決定に使用する基準

次の要因を考慮した後、製品を複数のソースコードリポジトリに分割することを検討します。

  1. ビルド-各コンポーネントのビルド結果は、製品を形成するために一緒にマージされますか?一連のコンポーネントの.classファイルを一連の.jarファイルまたは.warファイルに結合するようなものです。
  2. 配置-1つのユニットとして一緒に配置されるコンポーネント、または別のサーバーに移動する異なるユニットとして配置されることになりますか?たとえば、データベーススクリプトはDBサーバーに送られ、JavaScriptはWebサーバーに送られます。
  3. 共同変更-彼らは頻繁にまたは一緒に変更する傾向がありますか?あなたの場合、それらは個別に変更されるかもしれませんが、それでも頻繁です。
  4. ブランチ/マージの頻度-誰もがトランクにチェックインし、ブランチがまれである場合、それを回避できる可能性があります。ブランチやマージを頻繁に行うと、これが悪夢に変わる可能性があります。
  5. 俊敏性-変更を開発、テスト、リリース、デプロイする必要がある場合(SaaSを使用している可能性が高い)、ブランチとリポジトリのジャグリングに貴重な時間を費やすことなくそれを実行できますか?

引数

また、この分割に関するあなたの主張のほとんどに同意しません。この長い答えはさらに長くなるため、私はそれらすべてに異議を唱えることはしませんが、目立つものはいくつかあります。

相互に依存しない2つのモジュールがあります。

ナンセンス。バックエンドを削除した場合、フロントエンドは機能しますか?私もそう思っていました。

長期的に両方のプロジェクトのソース履歴があると、状況が複雑になる可能性があります(探しているバグとはまったく関係のないコミットの半分を持っている間に、フロントエンドで何かを履歴で検索してみてください)

プロジェクトルートがフロントエンド/とバックエンド/に分かれている場合は、それらの階層の履歴を個別に確認できます。

競合とマージ(これは発生しないはずですが、誰かがバックエンドにプッシュすると、他の開発者がバックエンドの変更をプッシュフロントエンドの変更に強制することになります。)1人の開発者はバックエンドでのみ作業する可能性がありますが、常にバックエンドまたは他の方法でプルする必要があります。周り。

プロジェクトを別のリポジトリに分割しても問題は解決しません。フロントエンドの競合とバックエンドの競合により、リポジトリが1倍、競合が2倍、またはリポジトリが2倍になり、競合が2つ残ります。誰かがまだそれらを解決する必要があります。

2つのリポジトリがフロントエンド開発者がフロントエンドコードをマージできる一方で、バックエンド開発者がバックエンドコードをマージできるという懸念がある場合でも、SVNを使用して単一のリポジトリでそれを行うことができます。 SVNはどのレベルでもマージできます。多分それはgitまたはMercurialの制限(両方にタグを付けたので、どのSCMを使用するかわからない)でしょうか?

一方で

以上のことすべてを踏まえて、プロジェクトを複数のモジュールまたはリポジトリーに分割することが機能するケースを見てきました。私は、Solrを製品に統合した特定のプロジェクトのために一度だけそれを主張しました。 Solrはもちろん別のサーバーで実行され、変更セットが検索に関連している場合にのみ変更されます(当社の製品は検索以上のものです)、個別のビルドプロセスがあり、コードアーティファクトやビルドアーティファクトは共有されません。

25
Brandon

引数の一部は有効で、一部は無効です。

相互に依存しない2つのモジュールがあります。

それは実際には完全に真実ではありません。通信できるようにするには、フロントエンドとバックエンドの両方に共通のインターフェース(説明)が必要です。そのため、両方を共通のリポジトリに置くことを支持する弱い議論になります。しかし、それほど大きな違いはないので、弱い議論にすぎません。

長期的に両方のプロジェクトのソース履歴があると、状況が複雑になる可能性があります(探しているバグとはまったく関係のないコミットの半分を持っている間に、フロントエンドで何かを履歴で検索してみてください)

これは偽の議論です。特定のバグがどのように修正されたかを調べたい場合は、コミットに修正が含まれているバグトラッカーを調べます。また、特定のコードがどのように進化したかを知りたい場合は、1つのファイル(または多くても少数)の履歴を調べます。どちらの場合でも、リポジトリに他のファイル(おそらく他のモジュールからのもの)が存在しても、状況が複雑になることはありません。

競合とマージ(これは起こり得ないことですが、誰かがバックエンドにプッシュすると、他の開発者がバックエンドの変更をプッシュフロントエンドの変更にプルすることになります。)

これは偽の議論です。変更をコミット/プッシュする前にリポジトリ全体を同期する必要がある(適切な)VCSについては知りません。ほとんどの場合、変更されたファイルを含むフォルダー(多くの場合、ファイル自体のみ)を同期する必要があります。

開発者の1人はバックエンドでのみ作業する場合がありますが、常にバックエンドをプルするか、その逆にする必要があります。

これは前のものと同じ偽の引数です。

長期的には、いつ展開するか。ある方法では、フロントエンドは、1つのバックエンドサーバーを持ちながら、複数の静的サーバーに展開できます。いずれの場合も、バックエンド全体を複製するか、すべてのサーバーにフロントエンドのみをプッシュするか、バックエンドを削除するカスタムスクリプトを作成する必要があります。 1つだけが必要な場合は、両方よりもフロントエンドまたはバックエンドのみをプッシュ/プルする方が簡単です。

展開が行われることを人々がどのように想定するかに応じて、これは有効な議論になる可能性があります。サーバー上にZipファイル/ tarbalを解凍することで展開を行う場合、リポジトリの構成は問題ではありません。サーバー上のリポジトリー(の一部)をチェックアウトしてデプロイメントを行う場合は、個別にデプロイされるモジュールに個別のリポジトリーを使用することをお勧めします。

反論(1人が両方のプロジェクトで作業する可能性があります)、サブモジュールを使用して3番目のリポジトリを作成し、それを使用して開発します。履歴は個別のモジュールに分離されており、バックエンド/フロントエンドのバージョンが実際に同期して連携するタグをいつでも作成できます。 1つのリポジトリでフロントエンドとバックエンドの両方を一緒に使用しても、それらが一緒に機能するとは限りません。両方の履歴を1つの大きなリポジトリにマージしているだけです。

これは有効な議論ですが、それほど強くはありません。

プロジェクトにフリーランサーを追加したい場合、サブモジュールとしてフロントエンド/バックエンドを用意すると、物事が簡単になります。場合によっては、コードベースへの完全なアクセス権を付与したくないことがあります。 「外部の人」が見たり編集したりできるものを制限したい場合は、1つの大きなモジュールがあると状況が難しくなります。

これは有効な引数です。

バグの紹介とバグの修正、フロントエンドに新しいバグを挿入しました。次に、誰かがバックエンドのバグを修正します。 1つのリポジトリでは、新しいバグの前にロールバックするとバックエンドもロールバックされ、修正が困難になる可能性があります。

これは、1つのモジュールに2つのバグ修正を行った後、最初のモジュールを元に戻すことができないことを意味するため、偽の引数です。ほぼ適切なVCSであれば、古いコミットのほぼすべてをロールバックできます(多くの場合、これらの変更を元に戻す新しいコミットを作成することになります。場合によっては、HEADの先頭でも変更されます)。

フロントエンドのバグを修正しながらバックエンドを機能させるには、別のフォルダーにバックエンドのクローンを作成する必要があります...その後、再マージを試みます... HEADで他のリポジトリが変更されることはありません。また、異なるバージョンのバックエンドに対するテストは簡単です。

これは実際にはかなり良い議論です。 2つのリポジトリーがあると、デプロイされたフロントエンドとバックエンドが(わずかに)同期しなくなる可能性があるシナリオのテストが容易になります。

この投稿は少し古いですが、貢献したいと思います。バックエンドはフロントエンドについて実際には認識していませんが、フロントエンドはバックエンドのAPIと一致するリクエストを持っている必要があります。バックエンドをREST APIと見なす場合、Swagger YAMLインターフェースなどのインターフェースファイルを定義できます。これで、実際には3つのプロジェクトがあり、個別に異なるリポジトリに分割できます。あなたが合うと思うように:

  • API定義
  • バックエンド
  • フロントエンド

API定義は他の2つのプロジェクトの依存関係です。依存関係注入ツールとしてMavenを使用していたとしましょう。次に、バージョン管理をどの程度厳密に行いたいかによって異なります。変更を加えるたびにAPI定義プロジェクトのバージョンを上げて、プロジェクトが常に互換性のある状態であることを確認しますが、より多くのオーバーヘッドが必要になります。または、mavenでSNAPSHOTSのようなものを使用し、一度バージョン管理を行うことができます。オーバーヘッドの少ないインターフェースに満足していますが、多くの場合非互換性があります。ただし、フロントエンドとバックエンドでAPI定義を適用する限り、プロジェクトをさまざまなリポジトリに細かく分割できます。

これらの問題は、依存関係の管理に関するものです。プロジェクトが分割されておらず、同じリポジトリにある場合でも、フロントエンドとバックエンドが同期していない状態にウェブサイトを置くのは非常に簡単です。実際にこれを停止する唯一の方法は、2つの間のコントラクトを実際に定義することですが、代わりにインターフェイスにコーディングするのと同じように、フロントエンドとバックエンドの実装を結合しない方法でそれを実行したいOOプログラミングにおける実装の。

また、このインターフェースファイルを維持するオーバーヘッドが生じるという批判を先取りして処理するために、たとえばswaggerは、さまざまなプログラミング言語やJAX-RSなどのフレームワーク用のコードスタブを生成することもできます。したがって、選択したテクノロジーでインターフェースを作成してから、このインターフェースを実装できます。また、非常に素晴らしいドキュメントがバックエンドに追加され、フロントエンドの開発者が仕事をしやすくなります。

2
Snickers3192