2011-03-15 18 views
3

新規顧客ごとにコピー貼り付けされたアプリケーションを維持しています(...はい、私はを知っています)。新しい顧客が必要としない新しい機能が必要だった場合、コード部分のみが変更されました。このソリューションには、すべてのコードがすべての顧客に対して同じである一種の「common.dll」も含まれています。各顧客ごとに異なるデータベース構造を持つマルチ顧客プロジェクトのアーキテクチャー設計

各顧客の基礎となるMSSQLデータベースは、わずかに異なります。すべてが多かれ少なかれ同じテーブルを持っていますが、カスタムの特定の機能のための追加の列や新しいテーブルを持つ顧客もいます。

Visual Studioソリューションでは、顧客ごとに「型付きデータセット」(ADO.NET C#2.0)が使用されているため、常に特定のソリューション(ファイル)があり、特定の型付きデータセット(「XyDataSet.xsd」など) )。ソリューションでは、私はヘルパークラスを持っています。注文を処理する。このクラスのメソッドの1つは、顧客固有のDataSetを使用して注文を取得する(GetDataRow(型指定されたDataRow))GetOrder(string orderId)です。

ご覧のとおり、顧客ごとに「ソリューション」に「GetOrder」メソッドがあります。これは、おそらく追加の列のように注文表にはほとんど違いがないためです。ですから、一般的な "GetOrder"機能に変更が必要な場合、私はもちろんそれをメンテナンスの悪夢となっているすべてのプロジェクトで変更する必要があります。

この「アーキテクチャ」を改善できる方法は誰か分かりますか?または、現在の基礎となるさまざまなDBスキームでは、アプリケーションレベルを上げてもそれほど改善しないでしょうか?

答えて

3

完全にこの質問に答えることは非常に困難ですが、私はこの方法を考え始めるでしょう:

データベースレベル:

  • 共通であるものを検索し、データベース・スキーマとしてそれを持っています。
  • 追加するものを見つけ、それを別のテーブルに入れ、そのテーブルで(共通スキーマから)行の所有者とその対応する値を示す。例えば

    注文{注文ID、顧客IDなど}(これは所有者テーブルである)
    OrderExtensions {ExtensionID、がextensionName、ExtensionValue}(これは、指図の拡張テーブルである)
    OrderExtensionsToCustomers {得意、ExtensionID}(これは、その顧客のために利用可能である拡張示す)

データアクセス層レベル:

  • ここではデータベースレベルの設計を実装する必要があります。

ドメインモデル層レベル:(UI層のための)機能を備えた

  • いくつかの操作はここに移動する必要があります。何かが、例えば、データベース層に移動する必要があります。ここから

    UI層レベルを一部の顧客のみに表示されるUI要素は、特定の顧客に対してのみ有効化された「機能」(拡張機能)と考えることができます。

  • 個人的には、「フィーチャー」用語を抽象化し、動的にロード可能にすることで、私はさらに遠ざかります。リフレクションの使用に慣れていれば、これは簡単に達成できます。これが達成できれば、すべての顧客のすべてのコードがまとめられているわけではなく、必要に応じて特定の顧客の要求に応じて動的にロードされます。

最終画像:

  • お客様が実際にUIインターフェイス、特定のページにアクセスします。
  • 現在の顧客に利用可能なUI機能(たとえば、追加のボタンなど)についてデータベースが照会されました。
  • データベースは、顧客の各機能の定義を返します。
  • 各フィーチャは動的に読み込まれ、ページに追加されます(フィーチャの特殊なプレースホルダなど)。
  • 機能を動作させる必要がある場合、機能はドメインレイヤーに要求を渡します。ドメインレイヤーは、機能の「プロセッサー」部分をロードします。動的に、または機能を呼び出す必要がある実装を見つけます。
  • コールはデータベースにルーティングされ、共通情報は共通(所有者)テーブルに保存され、追加(拡張)情報は他の(拡張)テーブルに保存されます。

私はそれは長い答えですけど、私は、これは、テーブルのすべての一般的なcolumsではなく、特殊なものが含まれている型指定されたデータセットを作成します

+0

ありがとうございます。これにより、より良いアプリケーションアーキテクチャのためにリファクタリングすることができます。 – Patric

1

型指定されていないデータセットを返す一般的な方法(共有アセンブリ内またはサービス内)を使用することはどうですか?次に、このメソッドから返されたデータを型付きのデータセットにするメソッドを各ソリューションに含めることができます。そうすれば、データベースとの対話のロジックを1か所に保持できます。

1

まず、タフなギグ。

あなたがより良いアーキテクチャに移行するためにできることはたくさんあります。どれくらい時間を費やすことができるかによって異なります。私はアイデアのためにKerievskyの "Refactoring to Patterns"を読むことをお勧めします。

あなたの特定の質問に答えるには、「テンプレートメソッド」のパターンを検討します。大まかに言えば、一連のステップとしてgetOrderを定義し、必要に応じてサブクラスがこれらのステップをオーバーライドできるようにします。 http://www.dofactory.com/Patterns/PatternTemplate.aspx

私はOleに賛同する必要があるのは、戻り値の型を整理することです。これは、リファクタリングに関しては人生を楽にします。

まだ単体テストに投資することをお勧めします。

1

:-)理にかなって願っています。各テーブルに対応するXSDファイルに

<xs:anyAttribute /> 

これはXSDデータセットに定義されていないデータテーブルに列をロードすることを可能にするADDD。

一般的な列は、型指定されたデータセットを介してアクセスすることができます。顧客固有の列に名前を付けてアクセスするか、追加の列を取得するためのカスタム固有の拡張メソッドを作成することができます。

vs2008/vs2010 dataset-editorがこれを処理したり、またはanyAttribute情報を破壊しても、私は気にしません。ドットネットxsd.exeコードジェネレータはanyAttributeをサポートしています。現在のドットネットを含むdotnet 4.0以降

関連する問題