DBIx :: Class adalah antarmuka Perl yang populer ke basis data apa pun yang dapat Anda sambungkan melalui DBI . Ada dokumentasi yang bagus untuk detail teknisnya, tetapi sedikit informasi tentang penggunaannya yang tepat (termasuk situasi di mana Anda mungkin tidak menginginkannya).
Dalam banyak situasi, orang meraihnya secara refleksif karena mereka pikir mereka harus menggunakannya untuk semua yang melibatkan basis data. Namun, saya paling sering melihatnya disalahgunakan ke titik di mana ia menjadi titik sakit. Pertanyaan saya selama ulasan kode dan arsitektur selalu "Apa manfaat Foo memberi Anda?" Paling sering, pengembang yang saya lihat dalam situasi ini tidak dapat membentuk jawaban yang koheren untuk itu. Tapi kemudian, mereka juga sering tidak mengerti SQL sederhana.
Selama beberapa bulan terakhir saya telah bertanya kepada orang-orang "Mengapa Anda menggunakan DBIx :: Kelas?" dan hanya menerima satu jawaban yang baik (dan orang itu juga bisa menjawab tindak lanjut "Kapan Anda tidak akan menggunakannya"). Peter Rabbitson, pengembang utama, mendekati jawaban dalam wawancaranya di FLOSS Weekly , tapi agak terkubur di tengah-tengah wawancara.
Jadi, bagaimana saya bisa memutuskan apakah menggunakan DBIx :: Class sesuai untuk suatu proyek?
Jawaban:
Sebelum saya menjawab pertanyaan, saya pikir beberapa latar belakang sudah beres.
Inti Masalah
Setelah bertahun-tahun mewawancarai dan merekrut pengembang, saya telah belajar dua hal:
Sebagian besar pengembang hanya memiliki sedikit pengalaman dalam desain basis data.
Saya telah melihat korelasi longgar antara mereka yang tidak mengerti database dan mereka yang membenci ORM.
(Catatan: dan ya, saya tahu ada orang yang sangat paham database yang membenci ORM)
Ketika orang-orang tidak mengerti mengapa kunci asing penting, mengapa Anda tidak menanamkan nama produsen di
item
meja, atau mengapacustomer.address1
,customer.address2
dancustomer.address3
bidang yang bukan ide yang baik, menambahkan ORM untuk membuatnya lebih mudah bagi mereka untuk bug database yang menulis tidak akan membantu apa pun.Alih-alih, dengan database yang dirancang dengan benar dan case use OLTP, ORM adalah emas. Sebagian besar pekerjaan kasar hilang dan dengan alat-alat seperti DBIx :: Class :: Schema :: Loader , saya bisa beralih dari skema database yang baik untuk bekerja kode Perl dalam hitungan menit. Saya akan mengutip Aturan Pareto dan mengatakan bahwa 80% masalah saya telah diselesaikan dengan 20% pekerjaan, tetapi dalam kenyataannya, saya menemukan manfaat yang bahkan lebih besar dari itu.
Menyalahgunakan Solusi
Alasan lain beberapa orang membenci ORM adalah karena mereka akan membiarkan abstraksi bocor. Mari kita perhatikan kasus umum aplikasi web MVC. Ini adalah sesuatu yang biasa kita lihat (pseudo-code):
Orang-orang menulis rute pengontrol seperti itu dan menepuk diri mereka sendiri di belakang, berpikir itu adalah kode yang baik dan bersih. Mereka akan kaget pada hard-coding SQL di controller mereka, tetapi mereka telah melakukan sedikit lebih banyak daripada mengekspos sintaks SQL yang berbeda. Kode ORM mereka perlu didorong ke dalam model dan kemudian mereka dapat melakukan ini:
Anda tahu apa yang terjadi sekarang? Anda telah mengenkapsulasi model Anda dengan benar, Anda belum mengekspos ORM, dan kemudian, ketika Anda menemukan bahwa Anda bisa mengambil data itu dari cache alih-alih basis data, Anda tidak perlu mengubah kode pengontrol Anda (dan itu lebih mudah untuk menulis tes untuk itu dan menggunakan kembali logika).
Pada kenyataannya, yang terjadi adalah orang-orang membocorkan kode ORM mereka di seluruh pengontrol (dan pandangan) mereka dan ketika mereka mengalami masalah skalabilitas, mereka mulai menyalahkan ORM daripada arsitektur mereka. ORM mendapat rap buruk (saya melihat ini berulang kali untuk banyak klien). Alih-alih, sembunyikan abstraksi itu sehingga ketika Anda benar-benar mencapai batas ORM, Anda dapat memilih solusi yang sesuai untuk masalah Anda alih-alih membiarkan kode digabungkan dengan erat ke ORM sehingga Anda terikat dengan babi.
Pelaporan dan Batasan Lainnya
Seperti yang dijelaskan oleh Rob Kinyon di atas, pelaporan cenderung menjadi kelemahan dalam ORM. Ini adalah himpunan bagian dari masalah yang lebih besar di mana SQL atau SQL rumit yang mencakup beberapa tabel kadang-kadang tidak berfungsi dengan baik dengan ORM. Sebagai contoh, kadang-kadang ORM memaksa tipe join yang tidak saya inginkan dan saya tidak tahu cara memperbaikinya. Atau mungkin saya ingin menggunakan petunjuk indeks di MySQL, tetapi itu tidak mudah . Atau kadang-kadang SQL sangat rumit sehingga akan lebih baik untuk menulis SQL daripada abstraksi yang disediakan.
Ini adalah bagian dari alasan saya mulai menulis DBIx :: Class :: Report . Sejauh ini berfungsi dengan baik dan memecahkan sebagian besar masalah yang dialami orang di sini (asalkan tidak masalah dengan antarmuka hanya baca). Dan meskipun itu tampak seperti tongkat penyangga, pada kenyataannya, selama Anda tidak membocorkan abstraksi Anda (seperti yang dijelaskan di bagian sebelumnya), itu membuatnya bekerja dengan
DBIx::Class
lebih mudah.Jadi Kapan Saya Memilih DBIx :: Kelas?
Bagi saya, saya akan memilih sebagian besar waktu ketika saya membutuhkan antarmuka ke database. Saya telah menggunakannya selama bertahun-tahun. Namun, saya mungkin tidak memilihnya untuk sistem OLAP, dan programmer yang lebih baru pasti akan berjuang dengan itu. Juga, saya sering menemukan saya perlu meta-pemrograman dan sementara
DBIx::Class
menyediakan alat-alat, mereka sangat tidak terdokumentasi.Kunci untuk menggunakan
DBIx::Class
dengan benar sama dengan kebanyakan ORM:Jangan bocor abstraksi.
Tulis tes terkutukmu.
Ketahui cara drop down ke SQL, sesuai kebutuhan.
Pelajari cara menormalkan basis data.
DBIx::Class
, begitu Anda mempelajarinya, akan menangani sebagian besar tugas berat Anda dan menjadikannya mudah untuk menulis aplikasi dengan cepat.sumber
#dbix-class
dan#catalyst
) - kunci untuk bit "jangan bocor abstraksi" adalah bahwa setiap hal yang Anda kerjakan dalam DBIC adalah subkelas dari sesuatu yang menyediakan perilaku cookie-cutter. Anda sangat dianjurkan untuk menambahkan metode ke subclass Anda, dan kecuali Anda melakukan pekerjaan Q & D, hanya metode yang Anda tulis harus menjadi bagian dari antarmuka publik Anda.Untuk mengetahui kapan harus menggunakan sesuatu, penting untuk memahami apa tujuan benda itu. Apa tujuan produk?
DBIx :: Class adalah ORM - Object-Relational Mapper. ORM mengambil struktur data relasional basis data Relasional / Set dan memetakannya ke pohon Objek. Pemetaan tradisional adalah satu objek per baris, menggunakan struktur tabel sebagai deskripsi kelas. Hubungan orangtua-anak dalam database diperlakukan sebagai hubungan yang mengandung di antara objek.
Itulah tulang-tulangnya. Tapi, itu tidak membantu Anda memutuskan apakah Anda harus menggunakan ORM. ORM terutama bermanfaat ketika yang berikut ini benar:
Kekuatan terbesar ORM memiliki adalah membangun SQL yang baik untuk berjalan grafik pohon yang dilapis di atas struktur data relasional. SQL sering berbulu dan kompleks, tetapi itulah harga mengelola ketidakcocokan impedansi.
Sementara ORM sangat pandai menulis baris-ekstraksi SQL, mereka sangat miskin dalam menulis SQL penyusunan. Ini adalah jenis SQL yang menjadi dasar pembuatan laporan. Jenis susunan ini dibangun menggunakan alat yang berbeda, bukan ORM.
Ada banyak ORM dalam berbagai bahasa, beberapa di Perl. Pemetaan lainnya adalah Kelas :: DBI dan Rose :: DB. DBIx :: Kelas sering dianggap lebih baik daripada yang lain sebagian besar pada kekuatan hasilnya. Ini adalah konsep di mana generasi SQL dipisahkan dari eksekusi SQL.
Pembaruan : Menanggapi Ovid, DBIx :: Class (melalui SQL :: Abstract) menyediakan kemampuan untuk menentukan kolom apa yang akan dikembalikan serta petunjuk indeks yang digunakan.
Namun, secara umum, jika Anda ingin melakukan ini, lebih baik Anda tidak menggunakan ORM untuk permintaan tertentu. Ingat - tujuan utama ORM adalah untuk memetakan baris dalam tabel ke objek kelas yang atributnya adalah kolom dari tabel. Jika Anda hanya mengisi beberapa atribut, maka calon pengguna objek itu tidak akan tahu atribut mana yang terisi atau tidak. Hal ini menyebabkan pemrograman defensif yang mengerikan dan / atau kebencian umum ORM.
Hampir selalu, keinginan untuk menggunakan petunjuk indeks atau membatasi kolom mana yang dikembalikan adalah optimasi untuk kecepatan dan / atau permintaan agregasi.
Ya, DBA yang hebat dapat membuat tabel dengan fungsi 100MM + rows di Oracle atau SQL * Server. Jika Anda membaca ini, Anda tidak memiliki DBA hebat pada staf.
Semua ini mengatakan, ORM yang baik tidak hanya membuat grafik objek - ia juga memberikan definisi introspeksi dari database Anda. Anda dapat menggunakan ini untuk membantu membuat kueri ad-hoc dan mengonsumsinya seperti yang Anda lakukan dengan DBI, tanpa membuat grafik objek.
sumber
Sebagai salah satu pengembang inti platform e-commerce Interchange6 (dan gergaji skema utama), saya memiliki pengalaman yang cukup mendalam dengan DBIC. Berikut adalah beberapa hal yang menjadikannya platform yang hebat:
Generator kueri memungkinkan Anda menulis satu kali untuk banyak mesin basis data (dan beberapa versi masing-masing). Kami saat ini mendukung Interchange6 dengan MySQL, PostgreSQL dan SQLite dan akan menambah dukungan untuk lebih banyak mesin begitu kami mendapatkan waktu dan sumber daya. Saat ini hanya ada dua jalur kode di seluruh proyek yang memiliki kode tambahan untuk memenuhi perbedaan antara mesin dan ini murni karena kurangnya fungsi basis data tertentu (SQLite tidak ada di tempat) atau karena kebodohan MySQL yang berubah cara fungsi LEAST-nya menangani NULL di antara dua versi minor.
Kueri yang ditentukan sebelumnya berarti saya dapat membangun metode sederhana yang dapat dipanggil (dengan atau tanpa arg) dari kode aplikasi jadi saya menyimpan pertanyaan saya sebagian besar di dalam definisi skema daripada membuang-buang kode aplikasi saya.
Pembuatan kueri komposabel memungkinkan kueri untuk dipecah menjadi kueri yang telah ditentukan sebelumnya yang dapat dipahami dan kemudian dirantai bersama untuk membuat kueri kompleks yang akan sulit untuk mempertahankan jangka panjang di salah satu DBIC (bahkan lebih buruk dalam SQL murni) jika dibuat dalam satu langkah.
Skema :: Loader memungkinkan kami untuk menggunakan DBIC dengan aplikasi lawas yang memberikan masa pakai baru dan jalur yang lebih sederhana ke masa depan.
Plugin DBIC, DeploymentHandler & Migration semua sangat menambah seperangkat alat yang membuat hidup saya lebih sederhana.
Salah satu perbedaan besar antara DBIC dan sebagian besar platform lain seperti ORM / ORM adalah bahwa meskipun mencoba memandu Anda dalam hal melakukan hal-hal itu juga tidak menghentikan Anda melakukan hal-hal gila yang Anda sukai:
Anda dapat menggunakan fungsi SQL dan prosedur tersimpan yang tidak diketahui oleh DBIC hanya dengan memberikan nama fungsi sebagai kunci dalam kueri (juga dapat menyebabkan kesenangan ketika Anda mencoba menggunakan LEAST di MySQL ^^ tapi itu bukan kesalahan DBIC) .
SQL literal dapat digunakan ketika tidak ada 'cara DBIC' untuk melakukan sesuatu dan hasilnya dikembalikan masih terbungkus dalam kelas yang bagus dengan pengakses.
TL; DR Saya mungkin tidak akan repot menggunakannya untuk aplikasi yang sangat sederhana hanya dengan beberapa tabel tetapi ketika saya perlu mengelola sesuatu yang lebih kompleks, terutama di mana kompatibilitas lintas-mesin dan perawatan jangka panjang adalah kuncinya, maka DBIC adalah umumnya jalur yang saya sukai.
sumber
(Sebelum saya mulai, saya harus mengatakan ini hanya membandingkan pembungkus DBI berbasis DBIC, DBI dan Mojo. Saya tidak memiliki pengalaman dengan ORM Perl lainnya dan karenanya tidak akan berkomentar secara langsung).
DBIC melakukan banyak hal dengan sangat baik. Saya bukan pengguna berat, tapi saya tahu teorinya. Itu pekerjaan yang cukup baik dari generasi SQL dan terutama (seperti yang telah saya katakan) menangani bergabung dll. Ini juga dapat melakukan prefetching data terkait lainnya.
Keuntungan utama seperti yang saya lihat adalah kemampuan untuk menggunakan hasil secara langsung sebagai kelas model Anda. Ini dikenal sebagai "menambahkan metode hasil-set" di mana Anda bisa mendapatkan hasil Anda dan memanggil metode pada hasil tersebut. Contoh umum adalah mengambil objek pengguna dari DBIC dan kemudian memanggil metode untuk memeriksa apakah kata sandi mereka valid.
Tentu penyebaran skema bisa sulit, tetapi selalu sulit. DBIC memiliki alat (beberapa di modul eksternal) yang membuatnya lebih mudah, dan mungkin lebih mudah daripada mengelola skema Anda sendiri dengan tangan.
Di sisi lain dari koin, ada alat lain yang menarik bagi kepekaan lainnya, seperti pembungkus DBI rasa mojo. Ini memiliki daya tarik untuk menjadi ramping namun masih dapat digunakan. Sebagian besar juga telah mengambil isyarat dari Mojo :: Pg (asli) dan menambahkan fitur berguna seperti manajemen skema dalam flat-file dan integrasi pubsub.
Modul beraroma Mojo ini tumbuh dari satu titik lemah lain dari DBIC, yaitu bahwa ia belum mampu melakukan permintaan asinkron. Para penulis telah meyakinkan saya bahwa secara teknis mungkin mungkin bahkan cepat tetapi ada masalah merancang api yang cocok. (Memang saya bahkan telah diminta untuk membantu dengan ini, dan sementara saya melakukannya, saya hanya tidak tahu bagaimana menggerakkan jarum pada saat saya harus mencurahkannya).
TL; DR menggunakan DBIC kecuali Anda menyukai SQL atau Anda memerlukan async, dalam hal ini selidiki pembungkus DBI rasa Mojo.
sumber
Saya menulis pemikiran saya tentang ini dalam DBIC vs DBI tiga tahun lalu. Untuk meringkas, saya mencantumkan dua alasan utama:
Adapun anti-pola, baik satu-satunya yang bisa saya pikirkan adalah kinerja. Jika Anda benar-benar ingin memeras setiap siklus clock dari CPU Anda, maka mungkin DBIC bukan alat yang tepat untuk pekerjaan itu. Tapi, pasti untuk aplikasi yang menulis, kasus-kasus itu semakin langka. Saya tidak ingat kapan terakhir kali saya menulis aplikasi baru yang berbicara ke database dan tidak menggunakan DBIC. Tentu saja, ini membantu jika Anda tahu sedikit tentang menyetel kueri yang dihasilkan DBIC.
sumber
Cara saya membuatnya skala:
buat satu kelas yang menyediakan konstruktor soket DBI dan metode pengujian.
turunkan kelas itu ke dalam kelas kueri SQL Anda (satu kelas per tabel sql) dan uji soket pada waktu konstruktor.
menggunakan variabel cakupan kelas untuk menyimpan nama tabel dan nama kolom indeks utama Anda.
Tulis semua nama tabel interpolasi SQL Anda dan kolom indeks primer dari variabel-variabel itu alih-alih mendefinisikannya dalam SQL secara statis.
menggunakan editor makro untuk memungkinkan Anda membuat pasangan metode DBI dasar (mempersiapkan dan mengeksekusi) saat mengetik HANYA pernyataan sql.
Jika Anda dapat melakukannya, Anda dapat menulis kode API bersih di atas DBI sepanjang hari dengan relatif mudah.
Apa yang akan Anda temukan adalah banyak pertanyaan Anda akan portabel di beberapa tabel. Pada titik itu Anda dapat memotong dan menempelkan ke kelas EXPORTER dan memercikkannya kembali di tempat yang diperlukan. Di sinilah kelas interpolasi mencakup nama tabel dan nama kolom indeks utama ikut bermain.
Saya menggunakan pendekatan ini untuk mengukur ratusan metode DBI dengan kinerja yang relatif baik. Saya tidak ingin mencoba dan mempertahankan kode DBI dengan cara lain.
Kapan harus menggunakan DBI: Selalu.
Saya pikir itu bukan pertanyaan sebenarnya. Pertanyaan Anda yang sebenarnya adalah: "Ini terlihat seperti PITA besar, tolong beri tahu saya bahwa saya tidak perlu melakukan ini?"
Kamu tidak. Letakkan dengan benar dan bagian DBI menjadi cukup berlebihan untuk sebagian besar dapat mengotomatiskannya.
sumber
Saya bukan ahli Perl, tapi saya sering menggunakannya. Ada banyak hal yang saya tidak tahu atau tahu bagaimana melakukan lebih baik; beberapa hal yang saya belum bisa mengerti, meskipun ada dokumentasi.
Saya cenderung memulai dengan DBI karena saya pikir, "Oh, ini adalah proyek sederhana, saya tidak perlu mengasapi ORM dan saya tidak ingin repot dengan pengaturan dan modul Skema." Tapi sangat cepat - hampir setiap waktu - saya dengan cepat mulai mengutuk diri sendiri untuk keputusan itu. Ketika saya ingin mulai menjadi kreatif dalam kueri SQL saya (kueri dinamis, bukan hanya placeholder pembanding), saya berjuang untuk mempertahankan kewarasan menggunakan DBI. SQL :: Abstract sangat membantu, dan biasanya itu mungkin cukup bagi saya. Tapi perjuangan mental saya berikutnya adalah mempertahankan begitu banyak SQL di dalam kode saya. Ini sangat mengganggu bagi saya untuk memiliki garis dan garis-garis tertanam SQL di dalam heredocs jelek. Mungkin saya perlu menggunakan IDE yang berkualitas.
Pada akhirnya, lebih sering daripada tidak, saya tetap menggunakan DBI lurus. Tapi saya terus berharap ada cara yang lebih baik. DBIx :: Class memiliki beberapa karakteristik yang sangat rapi dan saya telah menggunakannya beberapa kali, tetapi tampaknya sangat berlebihan untuk semua kecuali proyek-proyek terbesar. Saya bahkan tidak yakin mana yang menurut saya lebih rumit untuk dikelola: DBI dengan SQL atau DBIC yang tersebar dengan modul Schema yang tersebar.
(Oh, hal-hal seperti kendala dan pemicu adalah nilai tambah besar bagi saya untuk DBIC.)
sumber