10

クライアントごとにコア製品を簡単にカスタマイズおよび拡張できるようにする方法について、いくつかのアドバイスを探しています。おそらく大きすぎる質問だと思います。ただし、この設定を間違えると、何年にもわたって問題が発生する可能性があるかのように、実際にいくつかのアイデアを得る必要があります。既存の製品のカスタマイズや拡張の経験はあまりありません。

私たちは通常、クライアントごとにオーダーメイドのコア製品を持っています。最近、MVC3フロントエンドを使用してC#4で製品を書き直しました。リファクタリングを行い、ソリューションを構成する3つのプロジェクトがあります。

  • コアドメインプロジェクト(名前空間-projectname.domain。*)-ドメインモデル(EFで使用)、ドメインサービスインターフェイスなど(リポジトリインターフェイス)で構成されます
  • ドメインインフラストラクチャプロジェクト(名前空間-projectname.infrastructure。*)-ドメインサービスを実装します-EFコンテキスト、リポジトリの実装、ファイルのアップロード/ダウンロードインターフェイスの実装など。
  • MVC3(namespace --projectname.web。*)-コントローラー、ビューモデル、CSS、コンテンツ、スクリプトなどで構成されるプロジェクト。プロジェクトのDIを処理するIOC(Ninject)もあります。

このソリューションは、スタンドアロン製品として正常に機能します。私たちの問題は、クライアントごとに製品を拡張およびカスタマイズすることです。私たちのクライアントは通常、ブランド化されたCSSとスタイルを使用して、コア製品バージョンを非常に迅速に(通常は契約に署名してから数日以内に)提供することを望んでいます。ただし、クライアントの70%は、カスタマイズによって機能を変更することを望んでいます。ドメインモデル、ビューモデル、ビューなどの追加プロパティなど、一部のカスタマイズは小規模です。その他のカスタマイズはより重要であり、まったく新しいドメインモデルとコントローラーなどが必要です。

一部のカスタマイズはすべてのクライアントに役立つように思われるため、定期的にカスタマイズから変更してコアに追加したいと考えています。

現在、ソースコードをTFSに保存しています。プロジェクトを開始するには、通常、ソースを新しいチームプロジェクトに手動でコピーします。クライアント名を反映するように名前空間を変更し、基本部分のカスタマイズを開始してから、Azureにデプロイします。これは明らかに完全に重複したコードベースになり、それを実行する正しい方法ではないと確信しています。コア機能を提供し、必要に応じて拡張/オーバーライドするものが必要だと思います。しかし、私はこれについてどうやって行くのか本当にわかりません。

だから私はそれを可能にする最良のプロジェクト構成に関するアドバイスを探しています:

  • コードの迅速な展開–ブランド化/マイナーな変更を可能にするために、新しいクライアントを簡単に開始できます
  • コードのコピーと貼り付けの必要性を防ぎます
  • 緩く結合した状態を維持するために、可能な限り多くのDIを使用する
  • クライアントごとにコードのスポークを許可する
  • コア製品を1か所で拡張し、コアの最新バージョンを入手して再デプロイした場合にすべてのクライアントにその機能を提供させる機能

どんな助け/アドバイスも大歓迎です。誰もが役立つと思う情報を追加してください。

4

2 に答える 2

8

私はこれに完全には答えないかもしれませんが、ここにいくつかのアドバイスがあります:

  1. 理由が何であれ、コードをコピーしないでください。
  2. 特定のクライアントバージョンを識別するために名前空間の名前を変更しないでください。そのためにブランチと継続的インテグレーションを使用してください。
  3. 次のような分岐モデルを選択します。「Main」というルートブランチを作成し、製品のメジャーバージョンごとにMainから1つのブランチを作成し、次にクライアントごとに1つのブランチを作成します。何かを開発するときは、何をしているかに応じて、開発するブランチを最初からターゲットにします(クライアント固有の機能はクライアントブランチに、グローバルバージョンはバージョンブランチまたはクライアントブランチに、プロトタイプを作成する場合は使用します)最初はそれなど)
  4. ブランチ間のマージを容易にするために、どのブランチに実装されているかを知るために開発した機能を追跡するために、ワークアイテムに依存するように最善を尽くしてください。

開発者にとって適切なブランチをターゲットにすることが最も重要です。「その場合に何をするか」という厳しいルールを定義する必要はありませんが、一貫性を保つようにしてください。

私は75以上のバージョンで10年間の大きなプロジェクトに取り組んできましたが、通常は次のように行いました。

  • 次のメジャーバージョン:Main、devInsideから新しいブランチを作成します
  • 次のマイナーバージョン:現在のメジャーブランチの開発者。ラベルを使用して、ブランチ内の各マイナーバージョンにマークを付けます。
  • いくつかの複雑な機能機能は、それを要求したクライアントのブランチで開発され、「ブランド化されていない」ことに成功すると、バージョンブランチに逆統合されました。
  • クライアントブランチのバグ修正。必要に応じて他のブランチで報告されます。(そのためにワークアイテムを使用する必要があります。そうしないと、簡単に迷子になります)。

私の考えでは、他の人は別の見方をしているかもしれませんが、コードのトレーサビリティについては作業項目に大きく依存していました。これは、コードの配信とレポート作成に大いに役立ちました。

編集

わかりました、ブランチに関するいくつかの考え/フィードバックを追加します:

ソフトウェア構成管理(SCM)には、バージョン管理に役立つ2つの機能があります。ブランチとラベルです。それぞれが他よりも良くも悪くもありません、それはあなたが必要とするものに依存します:

  1. ラベルは、後で必要に応じてその時点に戻ることができるように、ラベルを使用して特定の時点をマークするために使用されます。
  2. ブランチは、コードを「複製」して、2つのバージョンで同時に動作できるようにするために使用されます。

したがって、ブランチの使用は、実行できるようにすることだけに依存します。1つの多くの異なるバージョン(たとえば、クライアントごとに1つ)を同時に処理する必要がある場合:ブランチを使用する以外に対処する方法はありません。

ブランチの数を制限するには、新しいブランチとなるもの、またはクライアント固有のバージョン、メジャーバージョン、マイナーバージョン、サービスパックなどのラベルでマークされるものを決定する必要があります。

クライアントバージョンにブランチを使用するのは簡単なことのようです。メジャーバージョンごとに1つのブランチを使用するのは、最も難しい選択かもしれません。すべてのメジャーバージョンに1つのブランチのみを使用することを選択した場合、同時に異なるメジャーバージョンで作業する柔軟性はありませんが、ブランチの数は可能な限り少なくなります。

最後に、Jemery Thompsonは、すべてのコードをクライアントに依存させる必要はなく、クライアントごとにカスタマイズしてはならないライブラリ(通常は最低レベルのライブラリ)があると言ったときに良い点があります。私たちが通常行うことは、フレームワーク、横断的、低レベルのサービスライブラリに分離されたブランチツリー(クライアントごとではない)を使用することです。次に、クライアントごとのバージョンプロジェクトでこれらのプロジェクトを参照します。

バージョン管理された依存関係を定義する最良の方法であるため、これらのライブラリにNugetを使用し、それらのnugetパッケージを作成することをお勧めします。Nugetパッケージの定義は非常に簡単で、ローカルのNugetサーバーをセットアップすることもできます。

于 2012-05-03T11:29:26.003 に答える
4

I just worried that with 30 or 40 versions (most of which aren't that different) branching was adding complexity.


+1すばらしい質問です。それは、あなたがしなければならないビジネス上の決定です。

メンテナンスが簡単で、機能と修正がすべてのお客様に迅速に展開される、きちんとしたコードベースが必要ですか?

または、1つのコードベースのインスタンスを多数分割し、それぞれに小さな調整を加えて(編集:「ブランド解除」できるALM MVPでない限り)、トランクにマージする必要がありますか。


私は@Nockawaが言及したほとんどすべてに同意しますが、IMHOはコードアーキテクチャをブランチで拡張する代わりにはなりません。

ブランチ/トランク戦略を確実に使用しますが、ブランチが多すぎるquicklyと、サイト全体の機能を展開するのが難しくなり、プロジェクト全体の継続的インテグレーションが妨げられます。コピー/貼り付けを防止したい場合は、ブランチの数を制限してください。

コーディングソリューションに関して、ここにあなたが探していると私が信じているものがあります:

  • モジュール/プラグイン、インターフェース、DIは的を射ています!
  • ベースクラスからカスタムクラスを派生させる(顧客ごとにDSLを拡張するAssembly.Load())
  • カスタムレポートソリューション(新しいページの代わりに、多くのカスタムリクエストがレポートになる可能性があります)
  • スプレッドシートのあるページ(私は知っていますが、おかしなことにそれは機能します!)

モジュール/プラグインポイントの優れた例は、DotNetNukeやKenticoなどのCMSです。Facebookのアドインアーキテクチャ、オーディオおよびビデオ編集用のプラグイン、3Dモデリングアプリ(3DMaxなど)、および独自のレベルを構築できるゲームを調べることで、他のアイデアを得ることができます。

理想的なソリューションは、モジュール(DLL)を選択し、CSS(スキン)を調整し、dBをスクリプト化し、ソリューションをAzureに自動展開できる管理アプリです。この目標プラグインを達成することは非常に理にかなっているので、コードベースは分割されません。また、モジュールに拡張が行われると、すべてのクライアントにロールアウトできます。

ユーザーコントロール、派生クラス、関数オーバーライドを使用して、ドメインモデル、ビューモデル、ビューなどの追加プロパティなどの小さなカスタマイズを簡単に行うことができます。

それを本当に一般的に行います。たとえば、システム内の全員の年齢を集計するラベルを作成し、関数を呼び出しint SumOfField(string dBFieldName, string whereClause)て、その顧客のサイトにその関数にバインドするラベルを付けたいと顧客が言ったとします。次に、別の顧客が顧客による製品購入数をカウントする関数を必要としている場合、それを再利用できます:SumOfField( "product.itemCount"、 "CustomerID = 1")。

まったく新しいドメインモデルやコントローラーなどを必要とするより重要な変更は、プラグインアーキテクチャに適合します。たとえば、顧客が2番目のアドレスフィールドを必要としている場合、現在のアドレスユーザーコントロールを微調整して任意のページへのプラグインにし、CRUD操作へのインターフェイスを実装できるdBテーブルとフィールドを知るための設定があります。 。

クライアントごとに30〜40のブランチで機能をカスタマイズすると、保守性が非常に難しくなり、それらを(簡単に)マージできないように感じます。これが本当に大きくなる可能性がある場合は、275のブランチを管理したくありません。ただし、その専門分野である場合は、クライアントごとにユーザー制御レベルに下げる必要があり、「ユーザーは独自のページをデザインできない」場合、フロントエンドにNockawaのブランチ戦略を設定することは完全に合理的です。

于 2012-05-12T00:41:46.043 に答える