ベストプラクティス?#ifdef
(または、実行時構成またはその他のコンパイル時または実行時条件によって、条件付きで含まれているか、条件付きで依存関係が注入されている同じインターフェイスの個別の実装)!
並列バージョンをブランチとして維持することは、どのバージョン管理システムでも苦痛です。並列バージョンは、適切な条件付きコンパイルまたはランタイム構成手法を使用して維持するのが最適です。
ブランチ A をブランチ B にマージし、ブランチ B をブランチ A に戻す場合、両方のブランチはまったく同じになることに注意してください。これは、3 方向マージの固有のプロパティです。これはまさに機能ブランチに必要なものですが、さまざまな顧客のために並行バージョンを維持するのにはまったく適していません。
さまざまな顧客のバージョンを保持するには、代わりに条件付きコンパイルを使用してください。
- オブジェクト指向コードでは、通常、共通のロジックを持つ基本クラスと、条件付きでプロジェクトに含まれるか、条件付きでインスタンス化されるバリアントに固有のロジックのみを持つバリアントごとのカスタム派生クラスを持つことができます。
- ほとんどのプログラミング言語は何らかの形式の条件付きコンパイルをサポートしていますが、Java は顕著な例外です。
このアプローチにより、すべてのバリアントのテストを実行するか、すべてのバリアントを継続的インテグレーション サーバーでビルドしてテストすることにより、いずれのバリアントの機能も壊していないことを誰もがすぐに確認できます。
あなたはPHPに言及しています。そこにはコンパイル手順がないため、構成はランタイムのみになります。おそらく、条件付きで適切なテンプレートに含まれる顧客固有のオーバーライドを含むディレクトリを作成します。
注: 私は現在、この方法で 20 を超える顧客向けにカスタマイズされた C++ プロジェクトに取り組んでおり、問題なくスケーリングします。顧客ごとの正確なコードはありません。代わりに、オプションの一連の機能があり、さまざまなサブセットがさまざまな顧客に出荷されます。これにより、最大のバリアントを作成してテストできるため、すべての機能をテストするのが少し簡単になります。これは、多数の機能に成長する場合に役立ちます。特に、プロジェクトのビルドに時間がかかる場合 (継続的インテグレーション ビルドは約 1 時間実行され、夜間ビルドは 8 時間、すべての顧客バリアントのビルドには 1 日以上かかります)。