Desain: Bagaimana menghindari pemecahan kompatibilitas karena perubahan basis data


8

Ini skenario saya, saya punya antarmuka ini:

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

Dan saya memiliki dua kelas ini yang mengimplementasikan antarmuka:

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
    }
}

Ini adalah bagian dari aplikasi beta yang benar-benar berjalan dalam lingkungan pengujian dan produksi (!), Tetapi akan diperbarui secara teratur karena perbaikan bug yang tidak terkait dengan operasi basis data. Pembaruan hanya dilakukan melalui uninstall dan menginstal ulang.

Sekarang, saya memiliki persyaratan baru untuk situasi sudut yang sangat spesifik yang akan membutuhkan kolom "col3" baru ditambahkan ke tabel, dan saya harus memasukkan, memilih dan memperbarui nilai-nilai dalam kolom itu juga. Masalahnya adalah saya tidak ingin merusak kompatibilitas dengan database yang ada di mana perangkat lunak sudah berjalan.

Saya sedang berpikir tentang pengkodean kelas ketiga yang mengimplementasikan antarmuka HitTheDataBase, kelas pembantu untuk memeriksa apakah "col3" ada, dan membuat sesuatu seperti:

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

Apakah ini pendekatan yang baik? Kelihatannya bagus untuk saya, kecuali karena saya perlu memodifikasi kode di kelas yang menggunakan yang "tekan database". Saya juga harus terus memeriksa apakah nilai col3 ada untuk menunjukkannya di GUI dan membiarkan pengguna memodifikasinya.


2
Apakah ini masih menjadi pendekatan yang baik jika Anda perlu melakukan ini 15 kali lebih banyak?
Dan Pichelman

@DanPichelman nggak, Ben benar: Bau desain :(
Broken_Window

Contoh kode sangat buruk sehingga saya membuat napas tajam ketika saya melihatnya.
Graham

@ Graham ini adalah Java / C # seudocode yang menghebohkan yang dibuat dengan cara ini karena tidak mengungkapkan kode propietary
Broken_Window

Jawaban:


11

Ketika pembaruan perangkat lunak Anda digunakan, apakah ada alasan mengapa Anda tidak dapat memutakhirkan skema Anda juga? Perubahan pada perangkat lunak yang memerlukan perubahan pada skema database menyiratkan bahwa skema tersebut harus berubah pada sistem target.

Kompatibilitas mundur dengan versi lama dari skema database biasanya adalah sesuatu yang harus dihindari, dan meretas Lapisan Akses Data Anda untuk mendukung beberapa versi skema terasa seperti bau desain.

Solusi yang lebih bersih adalah untuk memastikan bahwa kode Anda selalu berjalan terhadap versi skema yang telah ditulis untuk kode itu. Ini tidak hanya akan membuat kode lebih mudah untuk ditulis, dan menjaga kode tetap bersih, juga akan membuat kode lebih mudah untuk diuji. Anda dapat menyertakan skrip migrasi sebagai bagian dari proses instal / hapus instalan Anda untuk peningkatan dan juga kembalikan.

Apakah skema Anda termasuk segala jenis tabel versi? Jika tidak, Anda perlu menambahkan tabel versi skema ASAP. Versi skema sangat penting untuk upgrade dan rollback.

Selama periode waktu yang lebih lama Anda kemungkinan akan berakhir dengan banyak skrip pemutakhiran skema yang perlu dijalankan dalam urutan tertentu selama pemasangan / pencopotan pemasangan. Mekanisme versi skema adalah kunci untuk memastikan bahwa skema upgrade dan rollback berjalan dengan lancar.

Di sisi lain, jika Anda tidak memiliki mekanisme untuk menjaga skema Anda dalam-langkah dengan versi perangkat lunak Anda, maka Layer Akses Data Anda akhirnya akan meledak dalam kompleksitas karena Anda dihadapkan dengan semakin banyak "peretasan" untuk mempertahankan mundur. kesesuaian; dan Anda akan dibebani dengan overhead yang terus meningkat dari pengujian regresi setiap kali Anda mengubah apa pun dalam skema Anda.


1

Inilah yang terjadi jika skema database Anda tidak cocok dengan versi aplikasi. Aplikasi apa pun yang mendapatkan kode col3 baru, harus memiliki basis data yang diperbarui bersama dengannya.

Jika Anda akan kesulitan memeriksa apakah ada kolom dalam tabel, buat saja saat pembaruan ke versi yang lebih baru.


Anda benar, skema aplikasi dan bd harus cocok. Saya membuat "menciptakan kolom yang hilang" di masa lalu. Ini hanya berfungsi jika pengguna yang saya gunakan untuk koneksi database memiliki cukup privilege, dan ini tidak selalu terjadi.
Broken_Window

Kemudian admin sistem mereka perlu menjalankan skrip pembaruan yang Anda berikan kepada mereka.
RubberDuck

@RubberDuck itulah solusi yang saya gunakan. Saya menyertakan skrip pembaruan dengan file instalasi dan cara memperbarui basis data dalam manual Pengguna.
Broken_Window

1

Saya akan mengatakan tidak.

Jenis [tanpa akhir] ini "jika, tetapi, mungkin, kecuali, kecuali" logika hanya akan membuat Anda gila, dan mungkin yang lebih penting, memperlambat aplikasi Anda, karena semua "pemeriksaan" ini dilakukan saat run-time.

Saya sarankan versioning perubahan skema dan toko yang versi [jumlah] di suatu tempat dalam database (sebagai bagian dari kemajuan upgrade Anda).

Buat versi kelas akses data Anda untuk setiap versi database.

Pada saat run-time, interogasi database untuk versi skema dan instantiate kelas "benar" berdasarkan itu.


2
Anda mungkin ingin menyebutkan bahwa kalimat terakhir Anda adalah referensi ke pola Strategi .
TMN
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.