web-dev-qa-db-ja.com

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

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

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の値が存在するかどうかを常に確認し、ユーザーが変更できるようにする必要があります。

8
Broken_Window

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

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

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

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

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

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

11
Ben Cottrell

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

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

1
JeffO

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

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

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

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

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

1
Phill W.