Ringkasan: Apakah ada pola desain yang baik untuk mengurangi duplikasi informasi di antara nilai-nilai yang saling bergantung erat?
Dalam pekerjaan saya, cukup umum untuk memiliki hubungan antara jumlah sehingga Anda dapat memperoleh salah satu dari jumlah tersebut jika Anda tahu yang lain. Contohnya adalah hukum gas Ideal :
Pv = RT
Anda bisa membayangkan membuat kelas untuk mewakili keadaan gas ideal. Kelas akan memiliki 3 sifat, secara alami Pressure
, Temperature
dan SpecificVolume
masing-masing jenis yang tepat.
Untuk pengguna objek kelas ini, akan wajar untuk mengharapkan bahwa jika Anda menetapkan nilai untuk keduanya Pressure
dan Temperature
, Anda kemudian bisa membaca nilai untuk SpecificVolume
dan berharap objek telah menghitungnya untuk Anda.
Demikian juga, jika Anda menetapkan nilai untuk keduanya Pressure
dan SpecificVolume
, Anda bisa membacanya Temperature
, dll.
Namun untuk benar-benar mengimplementasikan kelas ini diperlukan duplikasi informasi. Anda perlu memprogram semua variasi persamaan secara eksplisit, memperlakukan variabel yang berbeda sebagai dependen dalam setiap kasus:
T = P * v / R
P = R * T / v
v = R * T / P
yang tampaknya melanggar prinsip KERING . Meskipun masing-masing menyatakan hubungan yang sama, kasus-kasus ini membutuhkan pengkodean & pengujian independen.
Dalam kasus nyata, logika yang saya pikirkan lebih kompleks dari contoh ini, tetapi menunjukkan masalah dasar yang sama. Jadi akan ada nilai nyata jika saya bisa mengekspresikan logika hanya sekali, atau setidaknya lebih sedikit.
Perhatikan bahwa kelas seperti ini mungkin juga harus berurusan dengan memastikan bahwa itu diinisialisasi dengan benar sebelum nilai akan dibacakan, tapi saya pikir itu adalah pertimbangan sekunder.
Meskipun saya memberikan contoh matematika pertanyaannya tidak terbatas hanya pada hubungan matematika antara data. Itu hanya tampak sebagai contoh sederhana untuk menjelaskan maksudnya.
sumber
Pv/T != R
. Tidak yakin apakah gagasan itu dapat membantu Anda memecahkan masalah yang mendasarinya, atau apakah itu menyulitkannya.Jawaban:
Tidak ada masalah dari perspektif OO. Anda bisa memiliki metode penawaran GasLaw kelas statis
dan lain-lain
dan tidak akan ada masalah duplikasi. Tidak ada objek, tidak ada anggota data. Hanya perilaku yang semuanya berbeda.
Anda dapat menganggap hukum gas sebagai "satu hal" tetapi operasinya berbeda. Tidak ada yang salah dengan memiliki metode untuk setiap kasus penggunaan hukum.
sumber
Ini tidak mungkin terjadi dengan cara Anda bertanya.
Pertimbangkan: Saya memiliki objek gas yang ideal
g
. Jika saya secara eksplisit mengatur ketiganya dari suhu, tekanan dan volume tertentu, dan kemudian mendapatkan suhu lagi, seperti:haruskah itu:
t1
awalnya saya tetapkan?Jika Anda harus melakukan ini, Anda perlu melacak banyak status untuk setiap anggota: apakah tidak diinisialisasi, ditetapkan secara eksplisit oleh kode klien, atau caching nilai yang dihitung? Apakah nilai yang ditetapkan secara eksplisit atau di-cache dibatalkan oleh anggota lain di kemudian hari?
Perilaku ini jelas sulit diprediksi dari membaca kode klien. Ini adalah desain yang buruk, karena akan selalu sulit untuk mencari tahu mengapa Anda mendapatkan jawaban yang Anda lakukan. Kompleksitas adalah tanda bahwa masalah ini sangat tidak cocok untuk OO, atau setidaknya bahwa objek gas ideal stateful adalah pilihan abstraksi yang buruk.
sumber
Pertama saya tidak berpikir Anda melanggar Prinsip KERING karena ketiga rumus menghitung nilai yang berbeda. Faktanya itu adalah ketergantungan antara ketiga nilai tersebut karena Anda melihatnya sebagai persamaan matematika dan bukan sebagai tugas variabel terprogram.
Saya sarankan untuk menerapkan kasus Anda dengan kelas IdealGas yang tidak berubah sebagai berikut
Biarkan saya jelaskan implementasinya. Kelas IdealGas merangkum 3 properti Pressure, Temperature dan SpecificVolume sebagai nilai akhir untuk kekekalan. Setiap kali Anda menelepon getXXX, perhitungan tidak akan dilakukan. Caranya adalah memiliki 3 konstruktor untuk semua 3 kombinasi dari 2 parameter yang diberikan. Di setiap konstruktor Anda menghitung variabel ketiga yang hilang. Perhitungan dilakukan satu kali, pada waktu konstruksi dan ditetapkan ke atribut ketiga. Karena ini dilakukan dalam konstruktor, atribut ketiga dapat bersifat final dan tidak berubah. Untuk kekekalan saya berasumsi bahwa kelas Tekanan, Suhu dan Spesifik Volume juga tidak berubah.
Satu-satunya bagian yang tersisa adalah memiliki getter untuk semua atribut. Tidak ada setter karena Anda meneruskan parameter ke konstruktor. Jika Anda perlu mengubah atribut, buat instance IdealGas baru dengan parameter yang diinginkan.
Dalam contoh saya, kelas Pressure, Temperature, dan SpecificVolume adalah pembungkus sederhana dengan nilai ganda. Kode sampel dalam java, tetapi dapat digeneralisasi.
Pendekatan ini dapat digeneralisasi, meneruskan semua data terkait ke dalam konstruktor, menghitung data terkait dalam konstruktor dan hanya memiliki getter.
sumber
Ini pertanyaan yang sangat menarik! Anda pada prinsipnya benar bahwa Anda menggandakan informasi karena persamaan yang sama digunakan dalam ketiga kasus, hanya dengan perbedaan yang tidak diketahui.
Tetapi dalam bahasa pemrograman arus utama yang khas tidak ada dukungan bawaan untuk memecahkan persamaan. Variabel dalam pemrograman selalu diketahui jumlahnya (pada saat eksekusi), jadi meskipun ada persamaan yang dangkal, ekspresi dalam bahasa pemrograman tidak dapat dibandingkan dengan persamaan matematika.
Dalam aplikasi tipikal, persamaan seperti yang Anda gambarkan hanya akan ditulis sebagai tiga ekspresi terpisah dan Anda hidup dengan duplikasi. Tapi perpustakaan pemecahan persamaan memang ada dan bisa digunakan dalam kasus seperti itu.
Ini lebih dari sebuah pola, itu adalah paradigma pemrograman keseluruhan, yang disebut penyelesaian kendala, dan ada bahasa pemrograman khusus seperti Prolog untuk masalah seperti ini.
sumber
Ini adalah iritasi umum ketika meng-encode model matematika ke dalam perangkat lunak. Keduanya menggunakan notasi yang sangat mirip untuk model sederhana seperti hukum gas, tetapi bahasa pemrograman bukan matematika dan banyak hal yang dapat Anda tinggalkan saat bekerja di dunia matematika harus dilakukan secara eksplisit dalam perangkat lunak.
Itu tidak mengulangi dirimu sendiri. Tidak ada konsep persamaan, transformasi aljabar atau "penyelesaian untuk x" di sebagian besar bahasa pemrograman. Tanpa representasi perangkat lunak dari semua konsep tersebut, tidak ada cara bagi perangkat lunak untuk sampai pada persamaan
T = P * v / R
yang diberikanPv = RT
.Sementara itu mungkin tampak seperti batasan yang tidak masuk akal dari bahasa pemrograman ketika melihat model-model sederhana seperti hukum gas, bahkan matematika yang sedikit lebih maju memungkinkan persamaan yang tidak memiliki solusi aljabar tertutup, atau tidak ada metode yang dikenal yang dapat secara efisien memperoleh solusi. Untuk arsitektur perangkat lunak Anda tidak dapat bergantung padanya dalam kasus yang lebih kompleks.
Dan kasus sederhana dengan sendirinya? Saya tidak yakin apakah itu layak untuk membaca spesifikasi fitur dalam bahasa pemrograman. Model cenderung diganti, tidak dimodifikasi dan biasanya hanya memiliki beberapa variabel untuk dipecahkan.
sumber
Tidak, dua saja sudah cukup. Tapi membuat mereka pribadi dan mengekspos metode sebagai
pressure()
,temperature()
, danspecificVolume()
. Salah satunya, tidak sesuai dengan dua properti pribadi, harus memiliki logika yang sesuai. Dengan demikian kita bisa menghilangkan duplikasi data.Seharusnya ada tiga konstruktor dengan parameter
(P, T)
,(P, v)
dan(T, v)
. Salah satunya, sesuai dengan dua properti pribadi, hanya bertindak sebagai pemukim. Dua lainnya harus memiliki logika yang sesuai. Tentu saja logika ditulis tiga kali (dua kali di sini dan satu kali dalam paragraf sebelumnya), tetapi mereka bukan duplikat. Bahkan jika Anda menganggapnya sebagai duplikat, mereka dibutuhkan.Ya secara matematis dan tidak ada OO-ly. Dalam objek OO adalah warga negara kelas satu tidak ekspresi. Untuk membuat ekspresi warga negara kelas pertama (atau untuk membuat hubungan diungkapkan oleh hal yang sama) kita perlu menulis kelas, katakanlah,
Expression
atauEquation
yang bukan tugas yang mudah (mungkin ada beberapa perpustakaan).Hubungan juga bukan warga negara kelas satu. Untuk itu kita mungkin perlu menulis kelas
Relationship
yang juga tidak mudah. Tetapi hidup dengan duplikat lebih mudah.Jika Anda memutuskan untuk hidup dengan duplikat dan jika parameter dalam hubungan tinggi pertimbangkan menggunakan pola Builder . Sekalipun parameternya kurang pertimbangkan menggunakan Pabrik Statis untuk menghindari batasan overloading konstruktor.
sumber
Kelas harus mewakili perilaku gas ideal. Sebuah instance kelas - sebuah objek - mewakili negara.
Ini bukan memilih nits. Desain kelas harus dari perspektif perilaku dan fungsionalitas. Perilaku tersebut diekspos secara publik sehingga objek yang dipakai (ya, itu berlebihan) mencapai keadaan melalui perilaku berolahraga.
Begitu:
Dan berikut ini hanya omong kosong dan tidak mungkin di dunia nyata. Dan jangan lakukan itu dalam kode juga:
Perilaku membuat moot pertanyaan "duplikat informasi"
Mempengaruhi properti negara yang sama melalui metode yang berbeda bukanlah duplikasi. Berikut ini juga mempengaruhi suhu, tetapi ini bukan duplikat dari yang di atas:
sumber
Mungkin Anda bisa menggunakan pembuatan kode untuk menghasilkan berbagai bentuk persamaan dari bentuk tunggal yang Anda tentukan.
Saya dapat membayangkannya akan cukup sulit untuk formula yang lebih kompleks. Tetapi untuk yang sederhana, Anda hanya perlu memberi
Saya bisa membayangkan jika Anda menambahkan perkalian, penambahan dan pengurangan ke daftar itu dan rumus dasar Anda memiliki masing-masing variabel hanya sekali maka Anda dapat menggunakan manipulasi string untuk secara otomatis menghasilkan semua versi formula dengan kode boilerplate yang tepat untuk menggunakan yang benar mengingat variabel yang diketahui dikenal .
Wolfram Alpha memiliki berbagai alat manipulasi persamaan misalnya.
Namun!! kecuali Anda memiliki daftar besar kelas-kelas ini untuk menghasilkan saya tidak dapat melihat kode seperti itu sebagai penggunaan waktu Anda secara efektif.
Anda hanya perlu membuat kode ini sekali per fungsi dan fungsi Anda cenderung terlalu rumit untuk dipecahkan sesederhana contoh Anda.
Manual coding setiap versi kemungkinan menjadi metode tercepat dan paling dapat diandalkan menghasilkan fungsi dan meskipun Anda bisa membayangkan solusi di mana Anda kode untuk iteratif menebak nilai dan tes untuk kebenaran, saya pikir Anda lakukan kebutuhan untuk menghasilkan dan mengkompilasi fungsi untuk menghitung variabel yang tidak diketahui dengan jumlah daya pemrosesan yang masuk akal.
sumber
Saya pikir Anda terlalu memikirkan ini, pertimbangkan solusi berikut:
Anda hanya perlu mendefinisikan satu fungsi, tidak ada duplikasi, Anda bahkan bisa menggunakan ini untuk implementasi kelas internal, atau Anda bisa menggunakan fungsi ini Anda cukup mengubah parameter mana yang Anda gunakan di mana.
Anda juga dapat menggunakan pola yang sama ini untuk situasi apa pun di mana Anda memiliki fungsi di mana nilai ditukar.
Jika Anda menggunakan langauge yang diketik secara statis dan harus berurusan dengan fungsi di mana nilainya bisa menjadi tipe yang berbeda, Anda bisa menggunakan pemrograman template (catatan, menggunakan sintaks C ++)
sumber