Bayangkan pelanggan Anda ingin memiliki kemungkinan untuk menambahkan properti baru (misalnya warna) ke produk di eshop mereka di CMS mereka.
Alih-alih memiliki properti sebagai bidang:
class Car extends Product {
protected String type;
protected int seats;
}
Anda mungkin akan akhirnya melakukan sesuatu seperti:
class Product {
protected String productName;
protected Map<String, Property> properties;
}
class Property {
protected String name;
protected String value;
}
Artinya, membuat sistem tipe sendiri di atas yang sudah ada. Rasanya bagi saya seperti ini dapat dilihat sebagai membuat domain spesifik, atau tidak?
Apakah pendekatan ini merupakan pola desain yang dikenal? Apakah Anda akan memecahkan masalah secara berbeda? Saya tahu ada bahasa di mana saya bisa menambahkan bidang dalam runtime, tetapi bagaimana dengan basis data? Apakah Anda lebih suka menambahkan / mengubah kolom atau menggunakan sesuatu seperti yang ditunjukkan di atas?
Terima kasih atas waktu Anda :).
Jawaban:
Selamat! Anda baru saja mengelilingi dunia bahasa pemrograman / sistem ketik, tiba di sisi lain dunia dari mana Anda pergi. Anda baru saja mendarat di perbatasan bahasa dinamis / objek berbasis prototipe!
Banyak bahasa dinamis (mis. JavaScript, PHP, Python) memungkinkan seseorang untuk memperluas atau mengubah properti objek saat runtime.
Bentuk ekstrim dari ini adalah bahasa berbasis prototipe seperti Self atau JavaScript. Mereka tidak memiliki kelas, secara tegas. Anda dapat melakukan hal-hal yang terlihat seperti pemrograman berbasis kelas, berorientasi objek dengan pewarisan, tetapi aturannya sangat santai dibandingkan dengan bahasa berbasis kelas yang lebih tajam seperti Java dan C #.
Langauges seperti PHP dan Python hidup di jalan tengah. Mereka memiliki sistem reguler berbasis kelas idiomatik. Tetapi atribut objek dapat ditambahkan, diubah, atau dihapus saat runtime - walaupun dengan beberapa batasan (seperti "kecuali untuk tipe bawaan") yang tidak Anda temukan di JavaScript.
Pertukaran besar bagi dinamisme ini adalah kinerja. Lupakan seberapa kuat atau lemahnya bahasa itu diketik, atau seberapa baik dapat dikompilasi ke kode mesin. Objek dinamis harus direpresentasikan sebagai peta / kamus fleksibel, bukan struct sederhana. Ini menambahkan overhead ke setiap akses objek. Beberapa program berusaha keras untuk mengurangi overhead ini (misalnya dengan penugasan phantom kwarg dan kelas berbasis slot di Python), tetapi overhead tambahan biasanya hanya setara untuk kursus dan harga tiket masuk.
Kembali ke desain Anda, Anda mencangkok kemampuan untuk memiliki properti dinamis ke subset dari kelas Anda. A
Product
dapat memiliki atribut variabel; mungkin suatuInvoice
atauOrder
akan dan tidak bisa. Itu bukan cara yang buruk untuk pergi. Ini memberi Anda fleksibilitas untuk memiliki variasi di mana Anda membutuhkannya, sambil tetap dalam bahasa yang ketat dan sistem jenis. Di sisi bawah, Anda bertanggung jawab untuk mengelola properti fleksibel tersebut, dan Anda mungkin harus melakukannya melalui mekanisme yang terlihat sedikit berbeda dari atribut yang lebih asli.p.prop('tensile_strength')
bukannyap.tensile_strength
, misalnya, danp.set_prop('tensile_strength', 104.4)
bukannyap.tensile_strength = 104.4
. Tetapi saya telah bekerja dengan dan membangun banyak program dalam Pascal, Ada, C, Java dan bahkan bahasa dinamis yang menggunakan akses pengambil-penyetel untuk tipe atribut non-standar; pendekatannya jelas bisa diterapkan.Oleh karena itu, ketegangan antara tipe statis dan dunia yang sangat bervariasi ini sangat umum. Masalah analog sering terlihat ketika merancang skema database, terutama untuk penyimpanan data relasional dan pra-relasional. Kadang-kadang ditangani dengan membuat "baris super" yang berisi cukup banyak fleksibilitas untuk menampung atau menentukan gabungan dari semua variasi yang dibayangkan, kemudian memasukkan semua data yang masuk ke dalam bidang tersebut. The WordPress
wp_posts
meja , misalnya, memiliki bidang-bidang seperticomment_count
,ping_status
,post_parent
danpost_date_gmt
yang hanya menarik dalam kondisi tertentu, dan bahwa dalam prakteknya sering kosong. Pendekatan lain adalah, seperti tabel normalisasiwp_options
, sangat mirip dengan AndaProperty
kelas. Meskipun memerlukan manajemen yang lebih eksplisit, item di dalamnya jarang kosong. Database berorientasi objek dan dokumen (misalnya MongoDB) seringkali lebih mudah berurusan dengan perubahan opsi, karena mereka dapat membuat dan mengatur atribut dengan cukup banyak.sumber
Saya suka pertanyaan, dua sen saya:
Dua pendekatan Anda sangat berbeda:
Dalam C ++, banyak yang akan menggunakan std :: map of boost :: varian untuk mencapai campuran keduanya.
Penyimpangan: Perhatikan bahwa beberapa bahasa, seperti C #, memungkinkan pembuatan jenis yang dinamis. Yang bisa menjadi solusi bagus untuk masalah umum penambahan anggota secara dinamis. Namun, "memodifikasi / menambahkan" jenis setelah kompilasi tidak merusak sistem jenis itu sendiri, dan membuat jenis "dimodifikasi" Anda hampir tidak berguna (misalnya, bagaimana Anda mengakses properti yang ditambahkan seperti itu, karena Anda bahkan tidak tahu mereka ada? Satu-satunya cara yang masuk akal akan menjadi refleksi sistematis atas setiap objek ... diakhiri dengan bahasa dinamis murni _ Anda dapat merujuk ke 'dinamis' .NET kata kunci)
sumber
Membuat jenis saat runtime terdengar jauh lebih rumit daripada hanya membuat lapisan abstraksi. Sangat umum membuat abstraksi untuk memisahkan sistem.
Izinkan saya menunjukkan contoh dari latihan saya. Pertukaran Moskow memiliki inti perdagangan yang disebut Plaza2 dengan API pedagang. Pedagang menulis program mereka untuk bekerja dengan data keuangan. Masalahnya adalah bahwa data ini sangat besar, kompleks, dan sangat rentan terhadap perubahan. Itu dapat berubah setelah produk keuangan baru diperkenalkan atau perubahan kliring berubah. Sifat perubahan di masa depan tidak bisa diprediksi. Secara harfiah, ini dapat berubah setiap hari dan programmer yang buruk harus mengedit kode dan merilis versi baru, dan pedagang yang marah harus merevisi sistem mereka.
Keputusan yang jelas adalah menyembunyikan semua neraka finansial di balik abstraksi. Mereka telah menggunakan abstraksi tabel SQL yang terkenal. Bagian terbesar dari inti mereka dapat bekerja dengan skema yang valid, sama seperti perangkat lunak trader yang secara dinamis dapat menguraikan skema dan mencari tahu apakah itu kompatibel dengan sistem mereka.
Kembali ke contoh Anda, adalah normal untuk membuat bahasa abstrak di depan beberapa logika. Itu bisa "properti", "tabel", "pesan", atau bahkan bahasa manusia, tetapi perhatikan kelemahan dari pendekatan ini:
sumber
Dalam XML dan HTML, ini akan menjadi atribut untuk simpul / elemen. Saya juga mendengar mereka disebut properti diperluas, pasangan nama / nilai, dan parameter.
Begitulah cara saya memecahkan masalah, ya.
Database akan seperti Java, dalam beberapa hal. Dalam pesudo-sql:
Ini akan sesuai dengan Java
Perhatikan bahwa tidak perlu untuk kelas Properti, karena Peta menyimpan nama sebagai kunci.
Saya sudah mencoba menambahkan / mengubah hal kolom, dan itu adalah mimpi buruk. Itu bisa dilakukan, tetapi hal-hal tetap tidak sinkron dan saya tidak pernah berhasil dengan baik. Struktur tabel yang saya uraikan di atas jauh lebih sukses. Jika Anda perlu untuk melakukan pencarian dan ketertiban oleh ini, pertimbangkan untuk menggunakan atribut tabel untuk setiap jenis data (
date_attributes
,currency_attributes
, dll) atau menambahkan beberapa sifat sebagai kolom database lama baik dalam tabel produk. Laporan seringkali jauh lebih mudah untuk ditulis pada kolom basis data daripada sub tabel.sumber