Saya pikir pertanyaan ini harus berlaku untuk sebagian besar program yang memuat pengaturan dari file. Pertanyaan saya adalah dari sudut pandang pemrograman, dan itu benar-benar bagaimana menangani pemuatan pengaturan dari file dalam hal kelas yang berbeda dan aksesibilitas. Contohnya:
- Jika suatu program memiliki
settings.ini
file sederhana , haruskah isinya dimuat dalamload()
metode kelas, atau mungkin konstruktor? - Haruskah nilai disimpan dalam
public static
variabel, atau haruskah adastatic
metode untuk mendapatkan dan mengatur properti? - Apa yang harus terjadi jika file tidak ada atau tidak dapat dibaca? Bagaimana Anda akan membiarkan sisa program tahu bahwa tidak bisa mendapatkan properti itu?
- dll.
Saya berharap saya menanyakan ini di tempat yang tepat di sini. Saya ingin membuat pertanyaan sebagai bahasa agnostik mungkin, tapi saya terutama berfokus pada bahasa yang memiliki hal-hal seperti warisan - terutama Java dan C # .NET.
Jawaban:
Ini sebenarnya adalah pertanyaan yang sangat penting dan sering dilakukan secara salah karena tidak diberikan kepentingan yang cukup meskipun itu adalah bagian inti dari hampir setiap aplikasi. Inilah pedoman saya:
Kelas config Anda, yang berisi semua pengaturan harus hanya tipe data lama, struct / class:
Seharusnya tidak perlu memiliki metode dan tidak boleh melibatkan pewarisan (kecuali itu adalah satu-satunya pilihan yang Anda miliki dalam bahasa Anda untuk menerapkan bidang varian - lihat paragraf berikutnya). Itu dapat dan harus menggunakan komposisi untuk mengelompokkan pengaturan ke dalam kelas konfigurasi spesifik yang lebih kecil (mis. SubConfig di atas). Jika Anda melakukannya dengan cara ini akan ideal untuk lulus dalam tes unit dan aplikasi secara umum karena akan memiliki ketergantungan minimal.
Anda mungkin perlu menggunakan jenis varian, jika konfigurasi untuk pengaturan berbeda heterogen dalam struktur. Diterima bahwa Anda harus memasukkan cast dinamis di beberapa titik ketika Anda membaca nilai untuk melemparkannya ke kelas konfigurasi (sub-) yang tepat, dan tidak diragukan lagi ini akan tergantung pada pengaturan konfigurasi lain.
Anda tidak boleh malas mengetik semua pengaturan sebagai bidang dengan hanya melakukan ini:
Ini menggoda karena itu berarti Anda dapat menulis kelas serialisasi umum yang tidak perlu tahu dengan bidang apa yang dihadapinya, tetapi itu salah dan saya akan menjelaskan mengapa sebentar lagi.
Serialisasi dari konfigurasi dilakukan dalam kelas yang benar-benar terpisah. Apa pun API atau pustaka yang Anda gunakan untuk melakukan ini, isi fungsi serialisasi Anda harus berisi entri yang pada dasarnya sama dengan menjadi peta dari path / kunci dalam file ke bidang pada objek. Beberapa bahasa memberikan introspeksi yang baik dan dapat melakukan ini untuk Anda di luar kebiasaan, yang lain Anda harus menulis pemetaan secara eksplisit, tetapi kuncinya adalah Anda hanya perlu menulis pemetaan sekali saja. Misalnya, pertimbangkan ekstrak ini yang saya adaptasi dari dokumentasi parser opsi program c ++ boost:
Perhatikan bahwa baris terakhir pada dasarnya mengatakan "optimasi" memetakan ke Config :: opt dan juga bahwa ada deklarasi tipe yang Anda harapkan. Anda ingin pembacaan konfigurasi gagal jika jenisnya tidak seperti yang Anda harapkan, jika parameter dalam file tersebut bukan float atau int, atau tidak ada. Yaitu Kegagalan harus terjadi ketika Anda membaca file karena masalahnya adalah dengan format / validasi file dan Anda harus membuang kode kecuali / kembali dan melaporkan masalah yang sebenarnya. Anda seharusnya tidak menunda ini nanti di program. Itu sebabnya Anda tidak perlu tergoda untuk menangkap semua gaya Kamus Conf seperti disebutkan di atas yang tidak akan gagal saat file dibaca - karena casting ditunda hingga nilainya diperlukan.
Anda harus membuat kelas Config hanya-baca dengan cara tertentu - mengatur konten kelas satu kali saat Anda membuatnya dan menginisialisasinya dari file. Jika Anda perlu memiliki pengaturan dinamis di aplikasi Anda yang berubah, dan juga yang tidak, Anda harus memiliki kelas terpisah untuk menangani yang dinamis daripada mencoba untuk membiarkan bit kelas konfigurasi Anda tidak hanya-baca .
Idealnya Anda baca di file dalam satu tempat dalam program Anda yaitu Anda hanya memiliki satu contoh dari "
ConfigReader
". Namun, jika Anda kesulitan untuk mendapatkan instance Config yang diedarkan ke tempat Anda membutuhkannya, lebih baik memiliki ConfigReader kedua daripada memperkenalkan konfigurasi global (yang saya duga adalah apa yang OP maksud dengan "statis". "), yang membawa saya ke poin saya berikutnya:Hindari lagu sirene yang menggoda dari si singleton: "Aku akan menyelamatkanmu karena harus lulus kelas sekelas itu, semua konstruktormu akan indah dan bersih. Ayo, itu akan sangat mudah." Kebenaran dengan arsitektur teruji yang dirancang dengan baik Anda tidak perlu melewati kelas Config, atau bagian dari itu melalui banyak kelas aplikasi Anda. Apa yang akan Anda temukan, di kelas tingkat atas, fungsi utama Anda () atau apa pun, Anda akan mengurai conf menjadi nilai-nilai individual, yang akan Anda berikan kepada kelas komponen Anda sebagai argumen yang kemudian Anda kembalikan bersama-sama (ketergantungan manual injeksi). Konfigurasi tunggal / global / statis akan membuat unit menguji aplikasi Anda lebih sulit untuk diimplementasikan dan dipahami - mis. Itu akan membingungkan pengembang baru untuk tim Anda yang tidak akan tahu mereka harus mengatur keadaan global untuk menguji barang-barang.
Jika bahasa Anda mendukung properti Anda harus menggunakannya untuk tujuan ini. Alasannya adalah itu berarti akan sangat mudah untuk menambahkan pengaturan konfigurasi 'turunan' yang bergantung pada satu atau lebih pengaturan lainnya. misalnya
Jika bahasa Anda tidak mendukung idiom properti, bahasa tersebut mungkin memiliki solusi untuk mencapai efek yang sama, atau Anda cukup membuat kelas pembungkus yang menyediakan pengaturan bonus. Jika Anda tidak bisa memberikan manfaat properti, jika tidak, buang waktu untuk menulis secara manual dan menggunakan getter / setter hanya untuk tujuan menyenangkan beberapa dewa-OO. Anda akan lebih baik dengan bidang tua yang sederhana.
Anda mungkin memerlukan sistem untuk menggabungkan dan mengambil banyak konfigurasi dari berbagai tempat sesuai urutan prioritas. Urutan yang diutamakan itu harus didefinisikan dengan baik dan dipahami oleh semua pengembang / pengguna misalnya mempertimbangkan windows registry HKEY_CURRENT_USER / HKEY_LOCAL_MACHINE. Anda harus melakukan gaya fungsional ini sehingga Anda dapat membuat konfigurasi Anda hanya baca yaitu:
daripada:
Saya akhirnya harus menambahkan itu tentu saja jika kerangka kerja / bahasa yang Anda pilih menyediakan built-in, mekanisme konfigurasi terkenal Anda harus mempertimbangkan manfaat menggunakan itu daripada menggulir sendiri.
Begitu. Banyak aspek yang perlu dipertimbangkan - lakukan dengan benar dan itu akan sangat mempengaruhi arsitektur aplikasi Anda, mengurangi bug, membuat hal-hal mudah diuji dan semacam memaksa Anda untuk menggunakan desain yang baik di tempat lain.
sumber
.ini
sehingga itu dapat dibaca manusia, tetapi apakah Anda menyarankan saya harus membuat serial kelas dengan variabel dalam?Secara umum (menurut saya), yang terbaik adalah membiarkan aplikasi menangani bagaimana konfigurasi disimpan, dan meneruskan konfigurasi ke modul Anda. Ini memungkinkan fleksibilitas dalam cara pengaturan disimpan sehingga Anda dapat menargetkan file atau layanan web atau ...
Plus, itu menempatkan beban "apa yang terjadi ketika sesuatu gagal" pada aplikasi, siapa yang paling tahu apa arti kegagalan itu.
Dan itu membuatnya lebih mudah untuk unit test ketika Anda hanya bisa meneruskan objek konfigurasi daripada harus menyentuh sistem file atau menangani masalah konkurensi yang diperkenalkan oleh akses statis.
sumber
Jika Anda menggunakan .NET untuk memprogram kelas, Anda memiliki opsi berbeda seperti Sumber Daya, web.config, atau bahkan file kustom.
Jika Anda menggunakan Sumber Daya atau web.config, data sebenarnya disimpan dalam file XML, tetapi, pemuatannya lebih cepat.
Mengambil data dari file-file ini dan menyimpannya di lokasi lain akan seperti penggunaan memori ganda karena ini dimuat ke memori secara default.
Untuk file atau bahasa pemrograman lain, jawaban di atas oleh Benedict akan berfungsi.
sumber