設計:データベースの変更が原因で下位互換性が失われないようにする方法


8

これは私のシナリオです、私はこのインターフェースを持っています:

public interface hitTheDataBase
{
    public void insertMe(String [] values);
    public void modifyMe(String [] values);
    public DataTable selectMe();
}

そして、私はインターフェースを実装するこれらの2つのクラスを持っています:

public Class hitSqlServer implements hitTheDatabase
{
    public void insertMe(String [] values)
    {
         executes insert into table_in_sqlServerBD (col1, col2) values(values[0], values[1])
    }
    public void modifyMe(String [] values)
    {
         executes update table_in_sqlServerBD set col1 = values[0], col2 =  values[1] where rowid = values[3]
    }

    public DataTable selectMe()
    {
         executes select col1, col2 from table_in_sqlServerBD
    }
}

public Class hitSqLite implements hitTheDatabase
{
    public void insertMe(String [] values)
    {
         executes insert into table_in_sqLite (col1, col2) values(values[0], values[1])
    }
    public void modifyMe(String [] values)
    {
         executes update table_in_sqlLite set col1 = values[0], col2 =  values[1] where rowid = values[3]
    }

    public DataTable selectMe()
    {
         executes select col1, col2 from table_in_sqLite
    }
}

これは実際にテスト環境と本番環境(!)で実行されているベータ版アプリの一部ですが、データベース操作に関連しないバグ修正のため、定期的に更新されます。更新は、アンインストールと再インストールによって簡単に行われます。

これで、テーブルに新しい列「col3」を追加する必要がある非常に特定のコーナー状況に対する新しい要件があり、その列にも値を挿入、選択、および更新する必要があります。問題は、ソフトウェアがすでに実行されている既存のデータベースとの下位互換性を壊したくないことです。

HitTheDataBaseインターフェースを実装する3番目のクラス、「col3」が存在するかどうかを確認するヘルパークラスをコーディングすることを考えていました。

hitTheDataBase hitMe = !helperclass.col3Exists() ? new hitSqlServer() : new hitSqlServerWithCol3();

これは良いアプローチですか?「データベースにヒットする」コードを使用するクラスのコードを変更する必要があるため、それは私には良さそうです。また、GUIに表示するためにcol3の値が存在するかどうかを常に確認し、ユーザーが変更できるようにする必要があります。


2
これを15回以上行う必要がある場合でも、これは良いアプローチでしょうか?
Dan Pichelman 2016年

@DanPichelmanいいえ、ベンは正解です。デザインの匂い:(
Broken_Window

例のコードは非常に悪いので、見たときに急激に息を吸いました。
グラハム

@Grahamこれは、独自のコードを開示しないようにこの方法で作成された恐ろしいJava / C#の疑似コードです
Broken_Window

回答:


11

ソフトウェアの更新を展開するときに、スキーマもアップグレードできない理由はありますか?データベーススキーマの変更が必要なソフトウェアの変更は、スキーマがターゲットシステムで変更されることを意味します。

古いバージョンのデータベーススキーマとの下位互換性は、通常、避けるべきものであり、データアクセスレイヤーをハッキングして複数のスキーマバージョンをサポートすることは、デザインの匂いのように感じられます。

よりクリーンな解決策は、コードが記述されているスキーマのバージョンに対してコードが常に実行されるようにすることです。これにより、コードの記述が簡単になり、コードがよりクリーンに保たれるだけでなく、コードのテストも容易になります。アップグレードおよびロールバックのインストール/アンインストールプロセスの一部として移行スクリプトを含めることができます。

スキーマには、どのような種類のバージョンテーブルも含まれていますか?そうでない場合は、スキーマバージョンテーブルをできるだけ早く追加する必要があります。スキーマのバージョン管理は、アップグレードとロールバックに不可欠です。

長期間にわたって、インストール/アンインストール中に特定の順序で実行する必要があるスキーマアップグレードスクリプトが大量に作成される可能性があります。スキーマのバージョン管理メカニズムは、スキーマのアップグレードとロールバックをスムーズに実行するための鍵です。

一方、スキーマをソフトウェアバージョンに合わせて維持するメカニズムがない場合、データアクセスレイヤーは、逆方向に保持するための「ハッキング」の増加に直面しているため、最終的には複雑に爆発する可能性があります。互換性; また、スキーマ内で何かを変更するたびに、回帰テストのオーバーヘッドが増大し続けることになります。


1

これは、データベーススキーマがアプリケーションのバージョンと一致しない場合に起こります。新しいcol3コードを取得するすべてのアプリケーションは、それに合わせてデータベースを更新する必要があります。

テーブルに列が存在するかどうかを確認する問題が発生する場合は、新しいバージョンへの更新中に作成してください。


そうです、アプリとbdスキーマは一致している必要があります。過去に「行方不明のコラムを作成する」というものを作りました。これは、データベース接続に使用しているユーザーに十分な権限がある場合にのみ機能しますが、常にそうであるとは限りません。
Broken_Window

次に、彼らのシステム管理者は、あなたが彼らに提供している更新スクリプトを実行する必要があります。
RubberDuck 2016年

私が使用したソリューションである@RubberDuck。更新スクリプトをインストールファイルに含め、データベースの更新方法をユーザーズマニュアルに含めました。
Broken_Window

1

私はノーと言うでしょう。

これらの「チェック」はすべて実行時に実行されるため、このような「無限」の「もしそうなら、多分、それ以外の場合を除いて」ロジックは狂気へと駆り立てるだけで、おそらくアプリケーションの速度を低下させます。

スキーマの変更をバージョン管理し、そのバージョン[番号]をデータベース内のどこかに保存することをお勧めします(アップグレードの進捗状況の一部として)。

データベースのバージョンごとにデータアクセスクラスのバージョンを作成します。

実行時に、データベースにスキーマバージョンを問い合わせ、それに基づいて「正しい」クラスをインスタンス化します。


2
あなたの最後の文は戦略パターンへの参照であることを言及したいかもしれません。
TMN
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.