Saya punya nilai yang dibutuhkan banyak objek. Misalnya, aplikasi keuangan dengan investasi berbeda sebagai objek, dan sebagian besar membutuhkan tingkat bunga saat ini.
Saya berharap merangkum "lingkungan keuangan" saya sebagai objek, dengan tingkat bunga sebagai properti. Tetapi, objek saudara kandung yang membutuhkan nilai itu tidak dapat mencapai itu.
Jadi, bagaimana cara saya membagikan nilai di antara banyak objek tanpa menyandingkan desain saya secara berlebihan? Jelas saya memikirkan hal yang salah ini.
object-oriented
Greg
sumber
sumber
update
fungsi yang disebut di setiap catatan waktu? Bisakah Anda memposting di pseudocode bagaimana simulasi Anda beroperasi?Singleton
adalah global dengan gula sintaksis OO di atasnya dan merupakan solusi mengerikan yang dengan ketat memasangkan kode Anda dalam beberapa cara terburuk yang mungkin. Baca artikel ini berulang-ulang sampai Anda memahaminya!DateTime
input dan mengembalikan angka sebagai output.Jawaban:
Ini adalah bau desain. Jarang bahwa banyak objek perlu tahu tentang sesuatu. Yang mengatakan, suku bunga saat ini adalah contoh yang cukup baik dari keadaan luar biasa. Satu hal yang perlu dikhawatirkan adalah jarang ada suku bunga. Instrumen keuangan yang berbeda menggunakan kurs yang berbeda pula. Paling tidak, lokal yang berbeda menggunakan tarif 'standar' yang berbeda. Selanjutnya, untuk membantu dalam pengujian dan pelaporan, Anda biasanya ingin memberikan nilai karena Anda tidak ingin menggunakan nilai saat ini di sana. Anda ingin menggunakan tingkat 'bagaimana jika' atau 'pada tanggal pelaporan'.
Dengan membagikannya, tidak memiliki semuanya merujuk pada satu contoh. Melewati hal yang sama di sekitar masih kopling ke tingkat, tetapi tidak over kopling karena sesuatu seperti suku bunga saat ini diperlukan sebagai input ke berbagai perhitungan.
sumber
Dalam contoh khusus ini saya akan menggunakan Pola Singleton . FinancialEnvironment akan menjadi objek yang diketahui semua perpustakaan kelas lainnya, tetapi akan dipakai oleh Singleton. Idealnya Anda kemudian akan mengirim objek instantiated itu ke berbagai pustaka kelas.
Sebagai contoh:
Kelas-kelas lain hanya diikat bersama melalui perpustakaan kelas Entitas, mereka menerima objek FinancialEnvironment instantiated. Mereka tidak peduli bagaimana itu dibuat, hanya lapisan layanannya, yang mereka inginkan hanyalah informasinya. Singleton juga bisa cukup pintar untuk menyimpan beberapa objek FinancialEnvironment, tergantung pada aturan untuk lokal seperti yang ditunjukkan @Telastyn.
Sebagai catatan, saya bukan penggemar berat Pola Singleton, saya menganggapnya sebagai bau kode, karena dapat disalahgunakan dengan sangat mudah. Tetapi dalam beberapa kasus Anda membutuhkannya.
Memperbarui:
Jika Anda benar-benar, secara positif harus memiliki variabel global, maka menerapkan Pola Singleton seperti dijelaskan di atas akan berhasil. Namun, saya bukan penggemar berat ini, dan berdasarkan komentar dari posting asli saya, beberapa orang lain juga tidak. Sebagai sesuatu yang tidak stabil seperti InterestRate, Singleton mungkin bukan solusi terbaik. Lajang bekerja paling baik ketika informasi tidak berubah. Misalnya, saya menggunakan Singleton di salah satu aplikasi saya untuk membuat instance penghitung kinerja. Karena jika mereka berubah maka Anda harus memiliki logika untuk menangani data yang diperbarui.
Jika saya seorang taruhan, saya berani bertaruh tingkat bunga disimpan di suatu tempat di dalam basis data, atau diambil melalui layanan web. Dalam hal itu Repositori (lapisan akses data) akan direkomendasikan untuk mengambil informasi itu. Untuk menghindari perjalanan yang tidak perlu ke database (saya tidak yakin seberapa sering suku bunga berubah, atau informasi lain di kelas FinancialInformation), caching dapat digunakan. Di dunia C # perpustakaan Caching Aplikasi Microsoft blok bekerja dengan sangat baik.
Satu-satunya hal yang akan berubah dari contoh di atas, adalah berbagai kelas di lapisan layanan yang memerlukan Informasi Keuangan akan mengambil dari Data Access Layer alih-alih Singleton yang instantiating objek.
sumber
Singleton
adalah global dengan gula sintaksis OO dan kruk bagi yang malas dan berpikiran lemah.Singleton/global
adalah cara terburuk yang mutlak untuk memasangkan kode Anda dengan ketat ke sesuatu yang nantinya akan menjadi kanker ketika Anda menyadari betapa itu ide yang sangat buruk dan mengapa semua orang mengatakan itu!File Konfigurasi?
Jika Anda memiliki nilai yang digunakan "secara global", harap masukkan dalam file konfigurasi. Kemudian setiap sistem dan subsistem dapat merujuk ini dan menarik kunci yang diperlukan, membuatnya hanya baca.
sumber
Saya berbicara dari pengalaman seseorang yang memiliki sekitar satu bulan pemeliharaan pada proyek berukuran baik (~ 50k LOC) yang baru saja kami rilis.
Saya dapat memberitahu Anda bahwa Anda mungkin tidak benar-benar menginginkan objek global. Memperkenalkan semacam itu memberikan banyak peluang untuk penyalahgunaan daripada membantu.
Saran awal saya adalah jika Anda memiliki beberapa kelas berbeda yang membutuhkan tingkat bunga saat ini maka Anda mungkin ingin mereka menerapkan
IInterestRateConsumer
atau sesuatu. Di dalam antarmuka itu Anda akan memilikiSetCurrentInterestRate(double rate)
(atau apa pun yang masuk akal), atau mungkin hanya sebuah properti.Melewati suku bunga di sekitar sebenarnya bukan penggandengan - Jika kelas Anda membutuhkan suku bunga, itu bagian dari API-nya. Ini hanya berpasangan jika salah satu kelas Anda mulai mengkhawatirkan dengan tepat bagaimana kelas lain menggunakan tingkat bunga itu.
sumber
Martin Fowler memiliki artikel yang membahas secara singkat tentang bagaimana cara memperbaiki global statis menjadi sesuatu yang lebih fleksibel. Pada dasarnya Anda membuatnya menjadi singleton kemudian memodifikasi singleton sehingga mendukung overriding kelas instance dengan subclass (dan jika perlu pindahkan logika yang membuat instance ke kelas terpisah yang dapat sub-class, yang akan Anda lakukan jika membuat instance kelas-super maka menggantinya nanti adalah masalah).
Tentu saja, Anda harus mempertimbangkan masalah dengan lajang (bahkan lajang yang dapat diganti) vs rasa sakit karena melewatkan benda yang sama di mana-mana.
Sejauh objek "lingkungan keuangan" - lebih mudah untuk memprogram pada pass pertama, tetapi ketika Anda selesai Anda telah menambahkan beberapa dependensi tambahan. Kelas yang hanya membutuhkan tingkat bunga sekarang hanya berfungsi ketika melewati objek lingkungan keuangan, yang akan membuat mereka sulit untuk digunakan kembali ketika Anda tidak memiliki objek lingkungan keuangan berbohong. Jadi saya akan mencegah melewatinya secara luas.
sumber
Mengapa tidak memasukkan data suku bunga ke cache pusat?
Anda dapat menggunakan salah satu dari beberapa pustaka cache, yang mana yang paling sesuai dengan kebutuhan Anda, sesuatu seperti memcached menyelesaikan semua masalah manajemen mata uang dan kode Anda dan akan memungkinkan aplikasi Anda untuk menskala ke beberapa proses.
Atau pergilah seluruh babi dan simpanlah dalam basis data, yang akan memungkinkan Anda untuk mengukur ke beberapa server.
sumber
Dalam situasi seperti itu saya telah berhasil memperkenalkan (menggunakan kembali) istilah "konteks" dengan terkadang beberapa lapisan.
Ini berarti singleton, dengan demikian menyimpan objek "global", dari mana objek semacam ini dapat diminta. Kode yang memerlukannya, sertakan tajuk toko, dan gunakan fungsi global untuk mendapatkan instance objek mereka (seperti sekarang, penyedia suku bunga).
Toko dapat berupa:
Semakin besar sistem, semakin dapat digunakan solusi yang terakhir, untuk risiko yang cukup kecil menggunakan enum yang salah. Di sisi lain, dengan bahasa yang memungkinkan deklarasi tipe forward, saya pikir Anda dapat menggunakan pengetik yang diketik tanpa menyertakan semua header di toko.
Satu catatan lagi: Anda mungkin memiliki beberapa instance dari jenis objek yang sama untuk kegunaan yang berbeda, seperti nilai Bahasa yang terkadang berbeda untuk GUI dan untuk cetakan, log tingkat sesi dan global, dll, sehingga nama enum / accessor TIDAK boleh mencerminkan jenis aktual , tetapi peran instance yang diminta (CurrentInterestRate).
Dalam implementasi toko, Anda harus mengelola level konteks dan koleksi instance konteks. Contoh sederhana adalah layanan web, di mana Anda memiliki konteks global (satu contoh untuk semua permintaan untuk objek itu - bermasalah ketika memiliki server server), dan konteks untuk setiap sesi web. Anda juga dapat memiliki konteks untuk setiap pengguna, yang mungkin memiliki banyak, sesi paralel, dll. Dengan beberapa server Anda harus menggunakan semacam cache terdistribusi untuk hal-hal seperti itu.
Ketika permintaan masuk, Anda memutuskan tingkat konteks objek yang diminta, dapatkan konteks untuk panggilan itu. Jika objek ada di sana, Anda mengirimnya kembali; jika tidak, Anda membuat dan menyimpannya di tingkat konteks itu, dan mengembalikannya. Tentu saja, sinkronkan bagian pembuatan (dan publikasikan ke cache yang didistribusikan). Pembuatannya bisa seperti plugin yang dapat dikonfigurasi, paling baik dengan bahasa yang memungkinkan pembuatan instance objek dengan nama kelasnya (Java, Objective C, ...), tetapi Anda bisa melakukannya di C juga dengan pustaka pluggable yang memiliki fungsi pabrik.
Catatan: penelepon TIDAK boleh tahu terlalu banyak tentang konteksnya sendiri, dan tingkat konteks objek yang diminta. Alasan: 1: mudah membuat kesalahan (atau "trik pintar") dengan memainkan parameter ini; 2: tingkat konteks yang diminta dapat berubah nanti. Saya sebagian besar menghubungkan informasi konteks ke utas, sehingga toko objek memiliki informasi tanpa parameter tambahan dari permintaan.
Di sisi lain, permintaan dapat berisi petunjuk untuk contoh: seperti mendapatkan suku bunga untuk tanggal tertentu. Itu haruslah akses "global" yang sama, tetapi beberapa kejadian tergantung pada tanggal (dan mengarahkan nilai tanggal yang berbeda ke contoh yang sama di antara perubahan tarif), sehingga disarankan untuk menambahkan objek "petunjuk" ke permintaan, digunakan oleh pabrik contoh dan bukan toko; dan keyForHint ke pabrik, digunakan oleh toko. Anda dapat menambahkan fungsi-fungsi ini nanti, saya baru saja menyebutkan.
Untuk kasus Anda, ini adalah jenis pembunuhan berlebihan (hanya satu objek yang dilayani di tingkat global), tetapi untuk kode tambahan yang cukup kecil dan sederhana sekarang, Anda mendapatkan mekanisme untuk persyaratan lebih lanjut, mungkin lebih kompleks.
Berita bagus lainnya: jika Anda berada di Jawa, Anda mendapatkan layanan ini dari Spring tanpa berpikir terlalu banyak, saya hanya ingin menjelaskannya secara terperinci.
sumber
Alasan untuk TIDAK menggunakan global (atau singleton) adalah bahwa meskipun Anda awalnya berharap hanya memiliki satu nilai, sering kali berguna untuk dapat menggunakan kode yang sama beberapa kali dalam program yang sama, misalnya:
Saya akan menjadikan suku bunga sebagai anggota kelas "instrumen keuangan", dan menerima bahwa Anda harus meneruskannya ke kelas anggota mana pun (baik per-perhitungan, atau memberi mereka penunjuk / pengait untuk konstruksi).
sumber
Hal-hal harus diteruskan dalam pesan, bukan dibaca dari benda global.
sumber