Cara terbaik untuk referensi data database statis dalam kode?

24

Banyak aplikasi menyertakan 'data statis': data yang tidak benar-benar berubah selama masa pakai aplikasi. Misalnya, Anda mungkin memiliki daftar Area Penjualan yang mungkin merupakan daftar tetap untuk masa mendatang.

Tidak jarang menemukan data statis ini dalam tabel database (sering kali karena Anda ingin merujuknya dalam kunci asing tabel lain). Tabel contoh sederhana akan memiliki Id untuk digunakan sebagai kunci utama dan Deskripsi. Misalnya, tabel SalesArea Anda akan memiliki (setidaknya) kolom SalesAreaId dan kolom SalesAreaDescription.

Sekarang, dalam kode Anda mungkin tidak ingin memperlakukan setiap baris tabel sama. Misalnya, Anda mungkin ingin menetapkan Area Penjualan default pada beberapa layar, memberikan angka berbeda untuk beberapa area, atau membatasi apa yang dapat dilakukan pengguna di area lain.

Apa cara terbaik untuk merujuk ke data statis ini dalam kode? Mengapa?

  1. Hard-code deskripsi dalam kode Anda. Gunakan ini untuk mencari SalesAreaId dari database saat Anda membutuhkannya.
  2. Hard-kode ID dalam kode Anda. Gunakan ini untuk mencari deskripsi SalesArea saat Anda membutuhkannya.
  3. Tambahkan kolom ke tabel untuk setiap tujuan, misalnya kolom "IsDefaultOnProductLaunchScreen" dan seterusnya (mungkin ada banyak di antaranya).
  4. Sesuatu yang lain

Apakah ada pertimbangan khusus lain yang harus saya buat ketika berhadapan dengan data database statis? Misalnya, memberi tabel ini nama khusus?

Kramii Reinstate Monica
sumber
1
Kemungkinan rangkap: programmers.stackexchange.com/questions/304169/... Saya yakin jawaban untuk yang satu itu (ditautkan) mendapatkan inti masalah yang sedikit lebih baik IMO
JoeCool

Jawaban:

14

Bagaimana dengan memuatnya ke dalam cache (biasanya diimplementasikan sebagai tabel hash) ketika aplikasi dijalankan? Jika Anda melakukannya, Anda bahkan tidak perlu melakukan query database (well, tidak lebih dari sekali).

Saya juga menyarankan menghindari apa pun pengkodean keras. Tambahkan indikator default (awalnya dalam tabel DB dan juga dalam struktur cache) untuk layar yang membutuhkan default. Untuk melakukan pencarian pada non-defauilts, cobalah untuk menyimpan kunci yang akan dicari dalam file konfigurasi atau properti jika Anda bisa.

FrustratedWithFormsDesigner
sumber
Caching tentu saja bagus, tetapi bagaimana Anda memperbarui nilai-nilai ini? Agaknya aplikasi restart, atau semacam strategi pembatalan cache?
Steve
1
@Steve Ya, tepatnya. Tergantung pada aplikasi. Restart baik untuk sesuatu yang sering dimulai. Untuk aplikasi yang berjalan lama, mungkin memuat ulang cache sekali sehari selama masa-masa lambat. Pertanyaan saya adalah, bagaimana dengan skenario di mana aplikasi menjalankan banyak waktu yang sangat singkat. Seperti, mungkin skrip PHP atau sejenisnya.
tylermac
Basis data akan menjalankan cache sendiri untuk data yang sering diakses sehingga Anda akan mengimplementasikan kembali sesuatu yang sudah diimplementasikan (dan mungkin tidak juga!)
James Anderson
@JamesAnderson: Caching dalam sarana aplikasi akan hanya pernah menjadi salah satu panggilan ke database. Ya, basis data akan memiliki cache mereka sendiri tetapi itu bisa dibatalkan / disegarkan oleh peristiwa di luar kendali aplikasi Anda, dan Anda masih harus memiliki koneksi ke database dan membuat kueri untuk mendapatkan data itu (dan berharap itu ada di cache db). Benar-benar tidak sulit untuk mengimplementasikan cache dalam aplikasi yang sederhana.
FrustratedWithFormsDesigner
7

Alternatif untuk DB atau hard coding adalah dengan menggunakan file konfigurasi yang dibaca pada saat start-up. Anda kemudian dapat menyimpan data ini dalam struktur hanya baca dalam kode Anda.

DALAM kasus yang jarang (tetapi bukan tidak mungkin) di mana Anda mengedit data ini, Anda harus me-restart aplikasi. Jika ini tidak memungkinkan, Anda dapat menulis manajer konfigurasi yang lebih kompleks yang memeriksa perubahan dalam file konfigurasi setiap kali data diakses, ini sebenarnya cukup efisien karena Anda hanya perlu memeriksa cap waktu pada file dan kemudian membatalkan semua data. jika file diperbarui.

Steve
sumber
1
Gagasan bagus untuk beberapa jenis data statis, tetapi tidak begitu baik jika Anda ingin menegakkan hubungan FK seperti dijelaskan dalam pertanyaan.
Kramii Reinstate Monica
Pertanyaan tidak mengatakan ini adalah persyaratan, hanya sebuah skenario. Jika tidak diperlukan maka pendekatan file config berfungsi dengan baik.
Steve
Anda benar, saya tidak cukup jelas. Tapi saya senang ... karena saya telah belajar sesuatu dari jawaban Anda. Saya belum pernah menemukan pendekatan ini sebelumnya.
Kramii Reinstate Monica
3

Jika data terkait dengan data yang ada di DB Anda, mungkin efisien untuk menambahkannya ke DB seperti menambahkannya ke kode. Jika tidak maka saya biasanya tergoda untuk "mengambil peluru itu sekali," dan memasukkannya ke dalam kode sampai pertama kali itu berubah.

Seringkali apa yang kita pikir statis ternyata tidak menjadi, dan ketika itu terjadi, Anda tidak ingin harus menunggu rilis kode untuk perubahan yang harus dilakukan. Segera setelah itu terjadi sekali, masukkan ke dalam database dan tulis halaman administrator untuk melakukan pembaruan lebih lanjut.

Untuk mengambil contoh Anda, jika Anda sudah memiliki Area Penjualan di DB, tambahkan deskripsi di sana, jangan membangun tabel hash untuk menghubungkan data database ke daftar hard-coded. Tetapi jika Anda tidak membangun tabel hash dari Area Penjualan dengan segala cara, tetapi bersiaplah, pertama kali seseorang mengubah deskripsi atau menambahkan Area Penjualan baru, pindahkan ke DB.

pdr
sumber
"Seringkali apa yang kita anggap statis ternyata tidak menjadi" - begitu benar.
Kramii Reinstate Monica
3

Kenapa tidak hanya kode keras segalanya? Masalah utama yang selalu saya alami adalah merujuk nilai statis dari DB dalam kode aplikasi. Itu satu hal jika Anda hanya secara langsung membangun daftar drop-down atau sesuatu dari nilai-nilai statis, tetapi bagaimana jika beberapa logika aplikasi tergantung pada nilai-nilai dari DB?

Dalam aplikasi sederhana, saya saat ini memiliki daftar status sunting untuk konten: Draf, Diterbitkan, Diarsipkan.

Item konten perlu diperlakukan berbeda tergantung pada negara mana mereka berada. Jika saya menyimpan data status ini dalam DB, masing-masing dengan nilai 1, 2, 3, bagaimana saya mengecek apakah ada sesuatu dalam Draf negara?

if (content.State == 1)
atau
if (content.State == "Draft")?

Saya baru saja mengkodekan nilai!
Hal yang sama jika Anda menggunakan tabel cache / hash: Anda masih harus menggunakan beberapa nilai yang ditulis dalam kode Anda sebagai kunci untuk mencari data Anda.

Apa kerugian dari pendekatan hard-coding?

Dave
sumber
Kerugiannya adalah seperti kata pdr, "Seringkali apa yang kita pikir statis ternyata tidak menjadi".
tylermac
2
Tetapi jika Anda benar-benar mereferensikan nilai data statis dalam kode, Anda tidak dapat mengubahnya dalam database tanpa merusak aplikasi. Yang pasti itu tergantung pada apa data yang digunakan untuk: seperti yang saya sebutkan di atas, jika itu hanya mengisi elemen UI sehingga pengguna dapat memilih nilai dan memiliki yang disalurkan langsung kembali ke DB sebagai bagian dari catatan di tabel lain , maka data statis di DB dapat berubah secara independen dari kode aplikasi. Saya cukup yakin itulah yang dibicarakan oleh @pdr: aplikasi yang menangani set data statis sebagai satu item.
Dave
2

Mirip dengan apa yang dikatakan FrustratedWithFormsDesigner, ini biasanya dilakukan dengan cache, karena itu berarti Anda hanya perlu memuat data statis satu kali, tetapi mengikuti pola OAOO, artinya kita tidak mendefinisikan data di dua tempat (database dan di kode Anda).

Saya tahu NHibernate ORM menawarkan fungsionalitas ini melalui cache level 2 . Anda bisa mengatakannya untuk menyimpan data dari tabel tertentu, dan mengatakan itu hanya baca. Itu akan dimuat pertama kali diperlukan, dan tidak akan mengenai database lagi setelah itu, bahkan jika Anda mengakses data dari beberapa sesi.

Scott Whitlock
sumber
+1 untuk Sekali dan Hanya Sekali. Tetapi bagaimana dengan memperlakukan baris yang berbeda secara berbeda?
Kramii Reinstate Monica
1
@Kramii - Anda bisa menggunakan sesuatu seperti kelas enumerasi . Jika metadata hanya terkait dengan program Anda, maka saya akan menempatkan logika bisnis ( IsDefaultOn...) di properti pada entitas. Apakah itu mengembalikan true untuk satu entitas. Itu akan memungkinkan Anda untuk menemukan entitas itu, mengingat seluruh koleksi. Atau Anda bisa menggunakan kelas pengontrol yang akan memberi Anda entitas yang sesuai dengan pemanggilan metode.
Scott Whitlock
2

Ini adalah optimasi prematur yang lebih buruk.

Pertama, setiap DBMS modern akan mengambil data dari tabel kecil dengan kecepatan kilat dan mereka semua memiliki algoritma caching mulai dari bagus hingga hebat (semakin banyak Anda membayar untuk DBMS, semakin baik cacheing!). Jadi, Anda mengoptimalkan sesuatu yang menghabiskan sumber daya minimal.

Kedua, Anda memiliki sedikit pengalaman tentang aplikasi bisnis dunia nyata jika Anda membayangkan sesuatu seperti "area penjualan" adalah data statis. Ini bertanggung jawab untuk berubah dengan setiap perubahan Direktur Pemasaran atau CEO. Jadi, Anda menuju dunia kesakitan dua tahun ke depan.

Hanya ada dua cara untuk pergi ke sini: -

Simpan dalam database dan akses data dengan sql "normal".

Menyimpannya dalam file konfigurasi XML mewah (mungkin diakses melalui REST atau SOAP) yang dapat dengan mudah diedit setiap kali ada "perubahan kebijakan strategis".

James Anderson
sumber
1

Itu tergantung pada apa yang Anda lakukan dengan data. Jika itu adalah daftar sesuatu, saya biasanya akan menariknya ke dalam array. Jika daftar perlu tumbuh di versi lain, mudah saja menambahkan ke database dan mengubah kode untuk menangani data tambahan dalam array (yang bahkan mungkin tidak diperlukan tergantung pada kode, misalnya daftar data dengan untuk loop menggunakan batas atas array). Jika ini adalah daftar pengaturan, saya biasanya akan mengkodekannya karena biasanya tidak banyak dan lebih mudah dan lebih cepat daripada menggunakan pernyataan SQL. Jika ini adalah pengaturan yang dapat diubah oleh pengguna dan saya ingin menyimpan pilihan untuk peluncuran berikutnya, saya akan membuat tabel untuk digunakan sebagai registri dan hanya menarik entri individual ke variabel yang diperlukan.

MaQleod
sumber
1

Saya tahu jawaban ini diterima tetapi saya ingin berbagi bagaimana kami melakukan ini di toko pengembangan web terakhir saya di mana kami mencoba mengurangi basis data I / O sebanyak mungkin.

Kami menggunakan sisi server memasukkan file untuk sebanyak mungkin mencari tipe struktur data yang kami bisa. Terutama ini untuk navigasi situs (untuk memasukkan subnavigation) tetapi kami juga menggunakannya untuk drop-down dan checkbox sebanyak mungkin (Negara, Negara, Kategori).

Awalnya, kami menarik semua data ini dari database. Karena kami memberi pelanggan widget admin, mereka dapat mengubah data ini sesuka hati dan kami tidak pernah terhenti dengan sedikit perubahan receh. Sebagian besar waktu data ini hampir tidak pernah berubah tetapi kadang-kadang itu akan berubah.

Kami selalu mencari waktu muat yang lebih cepat. Jadi kami memutuskan untuk mengimplementasikan sebanyak mungkin file teks sisi server statis. Kami melakukan ini di samping widget admin. Setiap kali tabel database diperbarui, kami akan membuat kembali file teks statis yang sesuai. Ini memberi kami lingkungan yang sangat fleksibel dan cepat.

Michael Riley - AKA Gunny
sumber
0

Solusi saya untuk ini, yang mungkin tidak berfungsi di semua situasi, adalah untuk mengikat data database statis ke hard-coded enum. Karena masalah berasal dari memiliki data dinamis (database) yang terikat dengan logika statis (kode), buat ikatan ini eksplisit (dan longgar) dengan memiliki tabel database yang terkait dengan enum. Ex:

LooseDBCodeBinding (database table)
   ID : Int32 (key)
   Name : String
   HardCodedTypeID : Int32

// in code:
public enum LooseDBCodeBinding
{
   TYPE_1 = 1,
   TYPE_2 = 2,
   TYPE_3 = 3 // etc...
}

Kemudian tulis UI yang memungkinkan Anda untuk dengan mudah melihat daftar LooseDBCodeBindingcatatan, dan memetakannya ke LooseDBCodeBinding enumnilai - nilai (termasuk mendukung binding "broken"). Anda kemudian dapat memprogram sekitar enum, dan mendesain database di sekitar kunci tabel, dan hanya tabel ini yang memiliki pengetahuan tentang kedua konteks.

Dave Cousineau
sumber