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


30

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

私が言えることから:

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

現在、リポジトリは次の構造を持っています。

ルート:

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

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

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

私の議論のいくつかを以下に示します。

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

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

回答:


23

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

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

あなたのサイトにとって、実際に「ビルド」しないと(大した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. 敏ility性-すぐに変更を開発、テスト、リリース、およびデプロイする必要がある場合(SaaSを使用する場合など)、ブランチやリポジトリをジャグリングする貴重な時間を費やすことなく変更できますか?

あなたの議論

また、この分裂についてのあなたの議論の大部分にも同意しません。この長い答えはさらに長くなるので、私はそれらすべてに異議を唱えませんが、いくつかの顕著なものがあります:

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

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

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

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

競合とマージ(これは起こるべきではありませんが、誰かがバックエンドにプッシュすると、他の開発者がバックエンドの変更をプルしてフロントエンドの変更をプッシュします。)1人の開発者はバックエンドでのみ作業するかもしれませんが、常にバックエンドをプルする必要があります周り。

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

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

一方

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


私の母が
ウィリアムペイン

私が書いている時点では、バックエンドなしでフロントエンドを書いています。jsonファイルでバックエンドをエミュレートします。そして、おそらくブラウザでindexedDBを使用して完全にエミュレートすることもできます。バックエンドはjsonにサービスを提供するサーバーです。受信したデータがAPIに準拠している限り、任意のものに置き換えることができます。どちらのプロジェクトも異なるビルドシステムを使用しています。要するに、ウェブサイトとモバイルAndroidアプリを持っているようなものです。Webサーバーリポジトリ内にモバイルアプリケーションを追加します。
ロイックフォール-ラクロア

また、明確でない場合、バックエンドとフロントエンドはユーザー/管理者インターフェースではありません。ただし、フロントエンドは単なるAjaxインターフェイスであり、バックエンドはjsonを提供します。ユーザーとロールは異なる方法で処理され、管理インターフェースはフロントエンドになります。両方の部分を分離し、javascriptで生成されたhtmlがサーバーで生成されたhtmlをロードできないようにするという考え方です。サーバーはjsonまたはxmlのみを提供する必要があります。
ロイックフォール-ラクロア

1
そうすれば、ビルドや展開の問題はないので、大丈夫かもしれません。ただし、大きな変更を加える場合は、フロントエンドとバックエンドの両方に影響するAPIを変更する必要がある場合があります。したがって、2回分岐、2回マージ、2回タグ付けなどが行われます。 3 ... 4 ... 12 ... 20にならないでください。おそらく悪い考えではありません。
ブランドン

適切なバージョン管理でAPIが変更された場合でも、APIバージョンをサポートする各フロントエンドのブランチバージョンを作成できる可能性があります。バックエンドには「下位」互換性があり、古いAPIを可能な限り長く機能させる必要があります。
ロイックフォール-ラクロア14

3

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

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

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

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

これは偽の議論です。特定のバグがどのように修正されたかを調べたい場合は、コミットに修正が含まれているバグトラッカーを調べます。また、特定のコードがどのように進化したかを知りたい場合は、単一のファイル(またはせいぜい一握り)の履歴を見ます。いずれの場合でも、リポジトリに他のモジュールからのファイルがある可能性がありますが、それによって事態が複雑になることはありません。

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

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

ある開発者はバックエンドでのみ作業するかもしれませんが、常にバックエンドをプルする必要があります。

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

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

展開が行われることを人々がどのように構想しているかによって、これは有効な議論になり得ます。展開がサーバー上のzipファイル/ tarbalを展開することで行われる場合、リポジトリがどのように編成されているかは関係ありません。サーバー上のリポジトリ(の一部)をチェックアウトすることで展開を行う場合は、個別に展開されるモジュールに個別のリポジトリを使用することをお勧めします。

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

これは有効な引数ですが、それほど強力ではありません。

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

これは有効な引数です。

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

これは、1つのモジュールに2つのバグ修正を行った後、最初のモジュールを元に戻せないことを意味するため、偽の引数です。半分まともなVCSを使用すると、ほとんどすべての古いコミットをロールバックできます(ただし、場合によっては、HEADの先頭でさえ、これらの変更を元に戻す新しいコミットを作成することを意味します)。

フロントエンドのバグを修正しながらバックエンドを動作させるには、別のフォルダにバックエンドをクローンする必要があります...その後、物事を再マージしようとします... 1つのリポジトリのHEADを移動するので、2つのリポジトリを作成するのは簡単です他を変更しないでください。また、異なるバージョンのバックエンドに対するテストは簡単です。

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


正直に言うと、偽の引数のほとんどはブランチで解決できます。フロントエンドのブランチとバックエンドのブランチ。同期のマスター。しかし、何らかの方法で、そのようなブランチを処理すると、2つのリポジトリを持つよりも複雑になります。
ロイックフォール-ラクロア

1
@Sybiam:実際には、すべての変更がtrunk / mainに対してのみ行われている場合でも、単一のリポジトリの使用に存在する可能性のある問題を強調していないため、これらは偽の引数です。
バートヴァンインゲンシェナウ

あなたの批判は有効だと思います。それが問題のポイントではなかったと思う。
シルバナール

2

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

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

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

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.