Percayai Codd atau fasilitas Anda?

Objek tersimpan bebas sakit kepala: contoh sederhana bekerja dengan objek Caché dalam ObjectScript dan Python



Kastil Neuschwanstein

Pada Juni 2020, tepatnya 50 tahun gudang data tabular atau, secara formal, model data relasional. Ini dokumen resmi - artikel terkenal yang sama . Yang kami ucapkan banyak terima kasih kepada Dr. Edgar Frank Codd. Dan, omong-omong, model data relasional ada dalam daftar Forbes tentang inovasi global paling penting dalam 100 tahun terakhir.

Di sisi lain, anehnya, Codd menganggap database relasional dan bahasa SQL sebagai implementasi terdistorsi teorinya. Sebagai panduan, ia bahkan mengembangkan 12 aturan yang harus dipenuhi oleh setiap sistem manajemen basis data relasional (sebenarnya, ini adalah 13 aturan). Dan, sebenarnya, hari ini, di dunia Anda tidak dapat menemukan DBMS yang memuaskan setidaknya Codd "Rule 0" dan, oleh karena itu, tidak ada yang bisa menyebut DBMS mereka 100% relasional :) Mungkin ada pengecualian, katakan padaku?

Model relasional tidak terlalu kompleks dan dipelajari terus menerus. Bahkan mungkin terlalu dalam dipelajari. Sementara itu, pada tahun 2019 ini kami juga akan merayakan hari jadi yang lain - tepat 10 tahun yang lalu, tagar #NoSQL nanti tentang “tidak hanya SQL” muncul di Twitter dan memulai penetrasi yang cepat ke dalam praktik pengembangan model basis data.

Mengapa pengantar yang begitu panjang? Kenyataan bahwa alam semesta pemrograman terdiri dari data (dan tentu saja algoritma), dan posisi monopoli model relasional mengarah, karena lebih sopan untuk mengatakan, kesadaran pemecah programmer. Karena objek kerja di kepala pengembang (OOP juga total, kan?), Semua daftar ini, antrian, pohon, tumpukan, kamus, utas, dan seterusnya hingga tak terbatas, jauh dari tabel.

Dan jika Anda melanjutkan dan ingat tentang arsitektur penyimpanan di DBMS modern? Katakanlah secara langsung, tidak ada orang waras yang menyimpan data dalam bentuk tabel. Pengembang DBMS paling sering menggunakan varietas B-tree (misalnya, dalam PostrgeSQL) atau, lebih jarang, penyimpanan berbasis kamus. Di sisi lain, barikade yang disimpan pengembang yang menggunakan DBMS tidak beroperasi pada tabel. Dan ini memaksa programmer untuk terus-menerus menjembatani kesenjangan semantik dengan lapisan data menengah yang canggung. Dan, dengan demikian, menyebabkan ketegangan dikotomis internal, ketidaknyamanan sistemik dan debug insomnia.

Singkatnya, ada kontradiksi - kami mengemas data menjadi objek yang cocok untuk tugas tersebut, dan saat menyimpannya harus mengurus beberapa tabel.

Keputusasaan? Tidak :) Tapi bagaimana dengan pemetaan objek-relasional, apakah itu orang biasa dari ORM? Mari kita serahkan perang suci ini ke Yegor Bugaenko dengan kawan-kawan. Dan keseluruhan cerita dari abad terakhir ini, seperti yang menurut Paman Bob, seharusnya tidak membuat kita khawatir .

Tentu saja, perlu disebutkan bahwa "tas dengan byte" (Robert Martin "Arsitektur Murni") dapat diserialisasi dan dimasukkan ke dalam file atau didorong ke aliran lain yang sesuai. Tapi, pertama, itu akan langsung membatasi kita dalam bahasa, dan kedua, sekarang kita hanya akan khawatir tentang menyimpan dalam DBMS.

Ada pengecualian yang menyenangkan untuk pasang surut ini dengan byte bag - Intersystems Caché DBMS (dan sekarang platform data IRIS InterSystems). Ini mungkin satu-satunya DBMS di dunia yang tidak menyembunyikan yang jelas dari pengembang dan bahkan melangkah lebih jauh - itu membebaskan seseorang dari berpikir "bagaimana cara menyimpan semuanya dengan benar." Sudah cukup untuk mengatakan bahwa kelas melanjutkan genus Persisten dan intinya ada di topi, yaitu, di global (jangan bingung dengan variabel global!).

Semua jenis data dapat disimpan, termasuk karakter dan aliran biner. Ini adalah contoh sederhana:

//       - // :      ,     ,     , ,   Class FW.Events Extends %Persistent { Property "My name" As %String; } //      //   «»  set haJS = ##class(FW.Events).%New() //   write haJS.%Id() 

Selain itu, dan ini luar biasa, Anda dapat berkomunikasi dengan objek yang disimpan tidak hanya dalam ObjectScript, asli ke Caché, tetapi dalam mengambil dan menyimpannya secara langsung dalam Python, Java, JavaScript, C ++, C #, Perl. Dan bahkan, oh horor :). Dimungkinkan juga untuk mendapatkan informasi dari objek yang sama secara langsung melalui query SQL, dan juga dimungkinkan untuk memanggil metode Anda sendiri pada objek. Lebih tepatnya, metode dalam kasus ini sendiri (dan kata ajaib SqlProc) berubah menjadi prosedur tersimpan. Semua keajaiban sudah ada di bawah kap CMS DBMS.
Bagaimana cara mendapatkan akses tes gratis ke CMS DBMS Intersystems?
Ini benar-benar nyata, tidak peduli apa kata bahasa jahat! :) Anda dapat mengunduh dan menginstal versi Caché fitur lengkap pengguna tunggal di sini (Anda harus mendaftar secara gratis). Build tersedia untuk MacOS, Windows, dan Linux.
Sangat mudah untuk bekerja dengan kode ObjectScript dan akses langsung langsung ke server DBE Caché (dan platform IRIS InterSystems juga) menggunakan Atelier IDE, yang didasarkan pada Eclipse. Semua instruksi pengunduhan dan instalasi ada di sini .

Bagi yang lebih nyaman dan terbiasa, Anda dapat menggunakan Visual Studio Code yang nyaman dan sederhana, melengkapinya dengan plug-in ObjectScript yang dikembangkan oleh komunitas.

Dan sekarang beberapa contoh praktis. Mari kita coba membuat beberapa objek terkait dan bekerja dengannya dalam ObjectScript dan Python. Integrasi dengan bahasa lain dilaksanakan dengan sangat mirip. Python dipilih karena alasan "afinitas maksimum" dengan ObjectScript - kedua bahasa dapat skrip, mendukung OOP dan tidak memiliki ketikan yang kuat :)

Sebagai contoh, kami beralih ke Khabarovsk yang kuat (jangan bingung dengan Khabrovsk!) Proyek-proyek “Kerangka Kerja Duduk-Duduk”. Kode sumber ideologis ada di github.com/Hajsru/framework-weekend Dan kode sumber kami lebih rendah dalam teks.
Nuansa penting bagi pengguna macOS. Saat memulai modul dukungan untuk Python, Anda harus ingat bahwa Anda harus menentukan jalur DYLD_LIBRARY_PATH ke direktori tempat Anda memasang Caché. Misalnya, seperti ini:
export DYLD_LIBRARY_PATH = / application / Cache / bin: $ DYLD_LIBRARY_PATH
Ini secara khusus ditunjukkan dalam dokumentasi.

Kami membuat kelas tersimpan di ObjectScript


Jadi ayo pergi. Kelas-kelas di Caché akan sangat sederhana. Anda dapat melakukannya tanpa IDE - salin kode kelas langsung melalui portal instance platform Caché Anda (ya, Caché DBMS jauh dari sekadar DBMS): Browser Sistem> Kelas> Impor (Namespace USER).

Setelah menyimpan, objek akan muncul di bola dengan nama yang cocok dengan nama kelas yang sesuai. Lihat juga di portal manajemen Caché: System Browser> Globals (Namespace USER).

 //    , ,      Class FW.Event Extends %Persistent { Property title as %String; Property description as %String; Property date as %Date; Property visitors as list of FW.Attendee; } //    / Class FW.Attendee Extends %Persistent { Property name As %String; } 

Mengakses Objek di Caché dari Python


Pertama, sambungkan ke basis data Caché DBMS. Kami ulangi seperti dalam dokumentasi .
Hanya fakta yang berguna untuk dikerjakan. Gratis, ini juga merupakan versi pelatihan dari Caché DBMS, yang akan memungkinkan Anda untuk melakukan semua yang tersedia dalam versi yang berfungsi penuh, tetapi hanya memungkinkan dua koneksi aktif. Oleh karena itu, pada saat yang sama, tidak mungkin untuk menjaga koneksi dari IDE dan mencoba menjalankan kode lain untuk berinteraksi dengan server. Solusi paling sederhana yang ditemukan adalah menutup IDE ketika kode Python sedang berjalan.
 #   Caché    Python3 import intersys.pythonbind3 #    conn = intersys.pythonbind3.connection() conn.connect_now("localhost[1972]:USER","_SYSTEM","SYS", None) #    print ("conn = %d " % conn.handle) #     database = intersys.pythonbind3.database(conn) 

Dan sekarang kita akan membuat database objek acara IT dan pesertanya. Sangat sangat sederhana. Yang pertama adalah membuat kelas untuk mendaftar dan menyimpan informasi tentang peserta acara. Untuk kesederhanaan ke kelas, hanya nama anggota.

 #         class Attendee: #        def __init__ (self): self.att = database.create_new("FW.Attendee", None) #             id def new (self, name): self.att.set("name", name) self.att.run_obj_method("%Save",[]) #    id     def use (self, id): self.att = database.openid("FW.Attendee",str(id),-1,-1) #       def clean (self): id = self.att.run_obj_method("%Id",[]) self.att.run_obj_method("%DeleteId", [id]) 

Seperti yang Anda lihat, kami menggunakan fungsi pembungkus yang sudah jadi untuk metode mengakses bidang objek di Caché: set dan dalam parameter kami memberikan nama properti dalam tanda kutip dan openid dengan nama paket dan kelas. Tentang fungsi get yang serupa, ada contoh di bawah ini. Untuk mengakses metode lain, termasuk yang diwarisi oleh kelas dari leluhur mereka, gunakan fungsi run_obj_method () dengan nama metode dan parameter panggilan, jika perlu.

Sihir paling penting di baris: self.att.run_obj_method ("% Simpan", [])
Ini adalah bagaimana kami memiliki kemampuan untuk menyimpan objek dengan referensi langsung dan tanpa perlu menggunakan perpustakaan dan kerangka kerja tambahan, seperti ORM di mana-mana dan tidak sedap dipandang.

Selain itu, mengingat sifat berorientasi objek dari ObjectScript, bersama dengan metode kelasnya (dalam contoh kami, kami tidak melakukannya), kami mendapatkan bonus dari akses Python ke seluruh rangkaian metode yang diwarisi dari kelas Persistent dan leluhurnya. Berikut adalah daftar lengkapnya , jika itu.

Buat anggota pertama:

 att = Attendee() att.new("") 

Setelah menjalankan kode ini, global akan muncul dalam database dengan nama FW.AttendeeD dan konten objek yang baru saja disimpan seperti pada tangkapan layar:



Setelah menyimpan, objek ini memiliki id sendiri (dengan nomor 1). Karena itu, Anda dapat memuatnya ke program kami menggunakan id ini:

 att = Attendee() att.use(1) print (att.att.get("name")) 

Dan sekarang, sekali lagi mengetahui id, jika perlu, Anda dapat menghapus objek dari database peserta:

 att = Attendee() att.use(1) att.clean() 

Periksa, setelah menjalankan contoh ini, catatan tentang objek harus menghilang di global. Meskipun data yang diunduh masih tetap "dalam memori" objek Anda sampai program berakhir.

Ayo ambil langkah selanjutnya. Buat catatan acara aktual.

 #        class Event: #        def __init__ (self): self.event = database.create_new("FW.Event", None) #            id def new (self, title, desc, date): self.event.set("title", title) self.event.set("description", desc) self.event.set("date", date) self.event.run_obj_method("%Save",[]) #    id    def use (self, id): self.event = database.openid("FW.Event",str(id),-1,-1) #       def addAttendee (self, att): eventAtt = self.event.get("visitors") eventAtt.run_obj_method("Insert", [att]) self.event.set("visitors", eventAtt) self.event.run_obj_method("%Save",[]) #      def clean (self): id = self.event.run_obj_method("%Id",[]) self.event.run_obj_method("%DeleteId", [id]) 

Struktur kelas hampir sama seperti di atas untuk anggota kelas. Yang paling penting, metode telah muncul untuk menambahkan peserta ke daftar peserta untuk acara ini addAttendee (att).

Kami mencoba membuat objek-record tentang acara baru dan menyimpannya di database:

 haJS = Event() haJS.new("haJS", " ", "2019-01-19") 

Seharusnya menghasilkan sesuatu seperti ini (perhatikan bahwa tanggal secara otomatis dikonversi ke format ObjectScript dan, ketika dimuat kembali ke objek Python, itu akan kembali ke format aslinya):



Tetap menambahkan peserta ke acara:

 #     haJS = Event() haJS.use(1) #    att = Attendee() att.new("") #      haJS.addAttendee(att.att) 

Jadi, contoh-contoh ini menunjukkan bahwa tidak perlu berpikir secara bersamaan tentang model data Anda dan skema penyimpanan tabularnya. Anda dapat menggunakan alat yang lebih jelas untuk tugas Anda.

Petunjuk terperinci untuk menghubungkan dan menggunakan Caché dengan Python dan bahasa lain selalu tersedia untuk Anda dalam dokumentasi dan di portal komunitas pengembang InterSystems - ini tidak kurang dari 5.000 anggota community.intersystems.com
Bantuan: InterSystems Caché multimodel DBMS tetap menjadi pemimpin dunia permanen dalam database objek


Source: https://habr.com/ru/post/id435612/


All Articles