Database relasional dan pengembangan berulang

19

Dalam banyak pendekatan untuk pengembangan perangkat lunak seperti metodologi gesit, Desain Berbasis Domain dan Analisis dan Desain Berorientasi Objek, kami didorong untuk mengambil satu pendekatan berulang untuk pengembangan.

Jadi kita tidak seharusnya menyelesaikan model domain dengan benar saat pertama kali kita mulai bekerja di proyek. Alih-alih, seiring berjalannya waktu kami memperbaiki model karena kami memperoleh pemahaman yang lebih dalam tentang domain masalah dengan waktu.

Terlepas dari itu, bahkan jika kita mencoba untuk mendapatkan model yang sempurna dimuka, yang saya sudah yakin sangat sulit, persyaratan dapat berubah. Jadi setelah perangkat lunak telah digunakan untuk produksi, pengguna akhir mungkin memperhatikan bahwa persyaratan tertentu tidak sepenuhnya dipahami, atau lebih buruk, beberapa persyaratan hilang.

Intinya di sini adalah bahwa kita mungkin akhirnya perlu mengubah model setelah perangkat lunak telah dikerahkan. Jika ini terjadi, kami memiliki masalah: basis data produksi memiliki data pengguna yang penting dan sudah dipasang dalam format untuk model lama .

Memperbarui kode mungkin merupakan tugas yang sulit jika kode tersebut tidak dirancang dengan baik dan jika sistemnya besar. Tapi itu bisa dilakukan dengan waktu, kami memiliki alat seperti Git yang membantu kami melakukannya tanpa merusak versi siap produksi.

Di sisi lain, jika model berubah, jika properti kelas hilang atau apa pun, database juga harus berubah. Tapi kami punya masalah: sudah ada data di sana yang tidak bisa hilang, yang sudah diformulasikan untuk model lama.

Tampaknya basis data relasional di sini menjadi penghalang yang mencegah kami melakukan pengembangan berulang dan bahkan memperbarui perangkat lunak saat dibutuhkan oleh pengguna akhir.

Satu pendekatan yang sudah saya gunakan adalah untuk kode kelas khusus yang memetakan tabel database lama ke yang baru. Jadi kelas-kelas ini mengambil data dalam format lama, mengonversinya ke format yang digunakan oleh model baru, dan menyimpan ke tabel baru.

Pendekatan ini tampaknya bukan yang terbaik. Pertanyaan saya di sini adalah: apakah ada pendekatan yang terkenal dan direkomendasikan untuk merekonsiliasi pengembangan berulang dengan database relasional?

pengguna1620696
sumber
6
Kebetulan, saya tidak berpikir ini ada hubungannya dengan database relasional pada khususnya. Saya memiliki masalah yang sama dengan proyek yang sedang saya kerjakan, tetapi kami memiliki itu dengan skema untuk string JSON kami yang mewakili objek yang sangat non-relasional. Ini mungkin memengaruhi semua bentuk kegigihan secara setara.
Ixrec
1
Anda mengubah skema basis data dengan cara yang tidak kehilangan data, en.wikipedia.org/wiki/Schema_migration .
RemcoGerlich
1
Saya yakin topik ini telah dibahas secara luas di suatu tempat sebelumnya, tidak dapat menemukannya di Programmer. Tetapi lihat di sini martinfowler.com/articles/evodb.html atau di sini stackoverflow.com/questions/334059/…
Doc Brown
1
"Terlepas dari itu, bahkan jika kita mencoba untuk mendapatkan model yang sempurna dimuka, yang saya sudah yakin sangat sulit, persyaratan dapat berubah." Saya ingin menambahkan bahwa Anda seharusnya tidak mencoba untuk mendapatkan model (hampir sempurna) di muka. Itu mungkin mengikat pola pikir Anda ke satu jenis solusi alih-alih menjaga pilihan Anda tetap terbuka.
Bent

Jawaban:

15

Tidak harus kelas khusus, tetapi ya, Anda memerlukan sesuatu yang akan mengambil database dalam format sebelumnya dan mengubahnya menjadi yang sekarang.

Masalahnya di sini adalah bahwa Anda perlu mengembangkan proses untuk menulis dan menguji skrip dan disiplin ini untuk tidak pernah menyentuh database pengujian dan produksi dengan tangan, tetapi selalu dengan skrip migrasi.

Setiap kali Anda perlu melakukan perubahan ke database, Anda menulis skrip yang akan melakukannya, baik dalam SQL atau menggunakan lapisan ORM Anda, dan komit ke kontrol versi Anda bersama dengan perubahan yang memerlukan skema baru. Kemudian Anda memiliki beberapa skrip kontrol yang akan memutakhirkan database dengan menerapkan semua skrip migrasi yang belum diterapkan secara berurutan.

Dan pastikan Anda hanya pernah memodifikasi lingkungan pengembangan, pengujian, dan QA apa pun dengan menerapkan skrip dan memutar kembali ke versi sebelumnya jika tidak berfungsi, sehingga Anda dapat yakin mereka akan berfungsi seperti yang dimaksudkan saat Anda melepaskannya pada produksi .

Instalasi baru dilakukan dengan menerapkan semua skrip. Setelah beberapa waktu, Anda mungkin akan memiliki ratusan dari mereka dan berpikir itu sangat tidak efisien, tetapi jangan terjebak dalam upaya mengoptimalkannya. Instalasi adalah kegiatan satu kali dan menjaganya agar tetap andal membuatnya cepat.

@ Doc Brown sudah menautkan Martin Fowler: Desain Basis Data Evolusi dan /programming/334059/agile-development-and-database-changes , dan saya akan menambahkan Alex Papadimoulis: Perubahan Basis Data Dilakukan dengan Benar , yang lebih pendek dan memiliki beberapa contoh.

Sebagai contoh yang layak dari alat yang mengimplementasikan proses tersebut saya sarankan Alembic . Ini didasarkan pada kerangka Python SQLAlchemy , tetapi Anda dapat menggunakannya dengan bahasa dan kerangka kerja lain jika mereka tidak memiliki dukungan migrasi sendiri. Halaman Wikipedia tentang Migrasi Skema mencantumkan lebih banyak alat tersebut .

Jan Hudec
sumber
1
@Tibo Anda membangun skema dari awal dengan menjalankan urutan skrip yang sama. Itulah cara Anda mengelola masalah. Mengingat bahwa sebagai standar Anda bisa dapatkan dari setiap instance dari database - termasuk yang belum ada - ke skema saat ini dan memiliki keyakinan bahwa itu sama. Tidak perlu memiliki dua cara sesuai contoh Anda. (Setidaknya tidak diberikan garis dasar yang konsisten - langkah pertama adalah menetapkan garis dasar dan setelah Anda mencapai garis dasar itu masalahnya hilang.)
Murph
1
Jempol untuk artikel Alex; ini mungkin tidak lebih pendek, tetapi bacaan yang lebih berorientasi pada praktik dan menghibur.
Murphy
1
Kami adalah toko Agile dan kami menjalankan layanan uptime 100% dan keduanya juga berlaku untuk DB. Kami memigrasikan skema produksi rata-rata sekali sehari dan saya akan mendukung semua yang dikatakan Jan. Satu hal tambahan yang kami lakukan yang sangat berharga adalah apa yang kami sebut pengujian migrasi, ini berjalan sebagai bagian dari proses membangun dan menggunakan kami. Dibutuhkan snapshot skema dari produksi, menerapkan migrasi yang tertunda dari master ke sana dan kemudian menjalankan tes unit dari kode produksi yang saat ini digunakan terhadap skema itu. Tujuannya adalah untuk memeriksa bahwa menerapkan migrasi tidak akan merusak sistem yang sedang berjalan.
Gordon Wrigley
1

Anehnya, ini adalah masalah yang dihadapi tim pengembangan saya saat ini. Pertanyaan tersebut berisi beberapa sub-pertanyaan, sehingga akan dibahas secara mandiri.

Pertama dan terpenting, apakah basis data relasional terlalu membatasi model data, membuat perubahan sangat sulit?

Paling pasti , tetapi belum tentu karena alasan yang dikutip. Sayangnya, fleksibilitas sistem manajemen basis data relasional juga menyebabkan kejatuhan mereka. RDBMS pada awalnya dikembangkan untuk menawarkan platform penyimpanan data yang relatif sederhana yang akan menerima set data besar dan menguranginya ke ukuran yang relatif kecil. Ini dilakukan dengan mengorbankan kompleksitas dalam model data dan daya komputasi yang diperlukan. Ketika kompleksitas basis data meningkat, prosedur tersimpan, pandangan, fungsi, dan pemicu muncul untuk membantu administrator database menangani kompleksitas dengan cara yang konsisten dan dapat diukur.

Sayangnya, model database relasional tidak berorientasi objek, dan tidak secara alami memetakan ke entitas dunia nyata sebagaimana model data seharusnya. Itu menuntun kita pada kebutuhan akan alat perantara seperti pemetaan obyek-relasional dan sejenisnya. Sayangnya, sementara alat-alat ini jelas memiliki tempat di dunia pengembangan saat ini, penggunaannya hanya ditargetkan pada gejala masalah kompleksitas data relasional, daripada penyebab yang mendasari, yang merupakan ketidaksejajaran model data ke dunia nyata.

Itu mengarah ke bagian kedua dari pertanyaan, yang benar-benar lebih dari asumsi, tetapi harus dilihat sebagai pertanyaan: apakah kita harus menyelesaikan model domain kita dengan benar pertama kali?

Ya, sampai batas tertentu. Seperti yang ditunjukkan pertanyaan, jarang mungkin untuk sepenuhnya memahami masalah ketika kita memulai proses desain. Namun, perbedaan antara model data yang benar-benar salah, yang bertentangan dengan model yang dapat di-tweak saat kita mendapatkan pemahaman yang lebih besar tentang domain, adalah model yang secara koheren memetakan ke dunia nyata. Ini berarti bahwa kita harus melakukan segala upaya untuk membuat model data awal yang konsisten dengan pemahaman kita tentang masalah dalam hal entitas dunia nyata. Jika kita mulai menormalkan entitas yang salah, model data akan salah dalam dua cara, dan pemulihan akan sulit.

Dalam banyak hal, perpindahan ke solusi database "No SQL" adalah hasil dari masalah ketidakcocokan model data. Memanfaatkan berorientasi objek Tidak ada pendekatan SQL menyebabkan kita berpikir lebih banyak tentang pemetaan antara objek kita dalam kode dan orang-orang di dunia nyata - dan ketika kita mengalami ketidakkonsistenan, itu sering terbukti dengan sendirinya karena tidak mungkin diterapkan di basis data. Ini mengarah pada desain keseluruhan yang lebih baik.

Itu mengarah pada pertanyaan terakhir: apakah model data relasional tidak konsisten dengan pendekatan gesit?

Tidak, tetapi dibutuhkan lebih banyak keterampilan. Sedangkan di dunia No-SQL, sepele untuk menambahkan bidang, atau mengubah properti menjadi array, sama sekali tidak sepele untuk melakukan hal-hal ini di dunia relasional. Setidaknya diperlukan seseorang yang mampu memahami model data relasional dan entitas dunia nyata yang mereka wakili. Orang ini adalah individu yang akan memfasilitasi memperbarui model relasional sebagai pemahaman tentang perubahan model dunia nyata. Tidak ada peluru perak untuk menyelesaikan masalah ini.

theMayer
sumber
1
Saya sangat berharap Anda membesar-besarkan masalah membuat bidang baru di tabel RDBMS untuk membuat pernyataan lebih dramatis. Tabel database harus sangat istimewa (atau tipe bidang baru harus menjadi sesuatu yang luar biasa) untuk benar-benar membuat masalah untuk menambahkan satu bidang.
Alexey Zimarev
Ya, tapi tidak pernah hanya satu bidang ...
theMayer
1
Saya akan mengatakan lebih sering itu hanya satu bidang. Perubahan skema dramatis tidak sesering itu. Saya bukan penggemar menggunakan RDBMSes dengan desain OO karena ketidakcocokan impedansi. Namun, menambahkan tipe baru (tabel) dan properti (kolom) relatif mudah di kedua dunia meskipun di NoSQL memang sedikit lebih mudah. Tetapi perubahan kompleks adalah rasa sakit pada kedua kasus. Lebih buruk lagi menjadi dalam sistem event-source dengan snapshots, berlawanan dengan betapa menyenangkan pengalaman pengembangan untuk sistem tersebut.
Alexey Zimarev
Saya melihat bahwa basis data relasional sering digunakan sebagai "palu universal" untuk menyelesaikan kebutuhan penyimpanan data - padahal sebenarnya ada alasan yang sangat spesifik untuk menggunakannya. Dalam sistem yang dipikirkan dengan saksama, orang jarang perlu khawatir tentang masalah yang saya tulis dalam jawaban saya - saya berbicara pada audiens yang lebih umum yang mungkin tidak memiliki pengalaman untuk sampai pada desain sistem yang tepat di muka.
theMayer
Tidak ada perbedaan antara model relasional dan itu biasanya memetakan ke dunia nyata sama seperti model lainnya. Beberapa operasi akan lebih mudah dengan satu jenis dan lainnya dengan jenis lainnya. Masalahnya adalah ketika Anda membuat model dari satu jenis (berorientasi objek) dan mencoba menerapkannya dengan alat jenis lain (relasional). Itu tidak bekerja dengan baik. Tetapi dunia nyata tidak berorientasi objek. Itu hanya dan Anda memodelkannya. Dan harus menggunakan alat yang tepat untuk jenis model yang dipilih.
Jan Hudec
-1

Poin utamanya adalah jangan terlalu banyak bereaksi sehingga model Anda berubah di luar semua pengakuan. Bahkan dengan pengembangan berulang Anda harus benar-benar membangun di atas hal-hal yang ada dan tidak refactoring menjadi berkeping-keping.

Ini memberi Anda 2 opsi utama untuk menangani perubahan besar ketika mereka datang: yang pertama adalah untuk membangun lapisan DB sebagai API, gunakan prosedur tersimpan sehingga mereka dapat diubah agar sesuai dengan klien tanpa mengubah skema data yang mendasarinya.

Cara lain adalah mengganti tabel dengan sedikit migrasi data. Saat diperlukan perubahan skala besar, Anda membuat skema baru dan mengimplementasikan serangkaian skrip untuk mengambil data lama dan memijatnya ke dalam format baru. Dibutuhkan waktu untuk melakukan hal ini, itulah mengapa Anda lebih mengandalkan metode yang lebih murah untuk memodifikasi akses ke data (misalnya melalui SP) sebagai pilihan pertama.

Jadi: 1. cobalah untuk berpikir ke depan dengan desain sehingga Anda tidak perlu mengubah banyak hal.

  1. Andalkan pembungkus atau API sehingga perubahan terbatas atau dapat disembunyikan di dalam komponen yang terisolasi

  2. Luangkan waktu untuk meningkatkan dengan benar jika Anda harus.

Langkah-langkah ini berlaku untuk semuanya, bukan hanya database.

gbjbaanb
sumber
Skema yang mendasarinya terkadang perlu diubah. Saat aplikasi memasuki pengujian pelanggan, atribut baru muncul yang belum pernah Anda dengar, atribut yang Anda pikir nomor berubah menjadi string, hubungan yang Anda harapkan menjadi 1: 1 ternyata tidak menjadi seperti itu dan seterusnya. Anda tidak dapat membahas hal-hal semacam ini di belakang prosedur tersimpan (selain itu, prosedur tersimpan adalah bagian dari masalah, karena, seperti hal-hal lain dalam database, mereka tidak hidup dalam kontrol versi).
Jan Hudec
@ JanHudec sejak kapan SP tidak hidup dalam kontrol versi? Anda dapat membahas hal-hal seperti itu, Anda mengubah API SP untuk mengambil string dan menulisnya ke bidang yang berbeda, menangani angka lama dan string baru dalam sedikit kode dalam SP Anda. Bukan yang terbaik, tetapi bisa lebih baik daripada pergi ke setiap situs pelanggan untuk memigrasikan data mereka ke format string baru (ada contoh yang lebih baik, tetapi Anda mendapatkan idenya). Jika perubahannya ternyata besar, maka Anda harus bermigrasi, tetapi setidaknya dengan DB API Anda juga memiliki opsi lain yang lebih murah.
gbjbaanb
Anda masih harus pergi ke setiap situs pelanggan untuk menginstal SP dan menambahkan bidang baru. Dan ketika Anda berada di sana, Anda dapat memigrasikan data juga. SP berguna karena memungkinkan Anda untuk membuat antarmuka yang kompatibel jika Anda memiliki beberapa aplikasi mengakses database, jadi Anda tidak perlu memutakhirkan semuanya pada saat yang sama. Tetapi mereka tidak menyimpan langkah apa pun ketika skema perlu diubah karena perubahan persyaratan.
Jan Hudec