Apakah ORM memungkinkan pembuatan model domain kaya?

21

Setelah menggunakan Hibernate di sebagian besar proyek saya selama sekitar 8 tahun, saya telah mendarat di sebuah perusahaan yang tidak mendukung penggunaannya dan ingin aplikasi hanya berinteraksi dengan DB melalui prosedur tersimpan.

Setelah melakukan ini selama beberapa minggu, saya belum dapat membuat model domain yang kaya dari aplikasi yang saya mulai buat, dan aplikasi tersebut hanya terlihat seperti skrip transaksional (mengerikan).

Beberapa masalah yang saya temukan adalah:

  • Tidak dapat menavigasi grafik objek karena prosedur yang tersimpan hanya memuat jumlah data minimum, yang berarti bahwa kadang-kadang kita memiliki objek serupa dengan bidang yang berbeda. Salah satu contoh adalah: kami memiliki prosedur tersimpan untuk mengambil semua data dari pelanggan, dan yang lain untuk mengambil informasi akun ditambah beberapa bidang dari pelanggan.
  • Banyak logika berakhir di kelas pembantu, sehingga kode menjadi lebih terstruktur (dengan entitas yang digunakan sebagai struct C lama).
  • Kode perancah yang lebih membosankan, karena tidak ada kerangka kerja yang mengekstrak set hasil dari prosedur yang disimpan dan menempatkannya dalam suatu entitas.

Pertanyaan saya adalah:

  • Adakah yang pernah berada dalam situasi yang sama dan tidak setuju dengan pendekatan prosedur toko? apa yang kamu lakukan?
  • Apakah ada manfaat sebenarnya dari menggunakan prosedur tersimpan? terlepas dari titik konyol "tidak ada yang bisa mengeluarkan drop table".
  • Apakah ada cara untuk membuat domain kaya menggunakan prosedur tersimpan? Saya tahu bahwa ada kemungkinan menggunakan AOP untuk menyuntikkan DAO / Repositori ke entitas untuk dapat menavigasi objek grafik. Saya tidak suka opsi ini karena sangat dekat dengan voodoo.

Kesimpulan

Pertama, terima kasih atas jawaban Anda. Kesimpulan yang saya sampaikan adalah bahwa ORM tidak memungkinkan pembuatan model Rich Domain (seperti beberapa orang sebutkan), tetapi itu menyederhanakan jumlah pekerjaan (sering berulang). Berikut ini adalah penjelasan yang lebih rinci tentang kesimpulan, tetapi tidak didasarkan pada data keras apa pun.

Sebagian besar aplikasi meminta dan mengirim informasi ke sistem lain. Untuk melakukan ini, kami membuat abstraksi dalam ketentuan model (misalnya acara bisnis) dan model domain mengirim atau menerima acara. Peristiwa biasanya membutuhkan sebagian kecil informasi dari model, tetapi tidak keseluruhan model. Misalnya di toko online, gateway pembayaran meminta beberapa informasi pengguna dan total untuk menagih pengguna, tetapi tidak memerlukan riwayat pembelian, produk yang tersedia, dan semua basis pelanggan. Jadi acara tersebut memiliki set data kecil dan spesifik.

Jika kita mengambil database aplikasi sebagai sistem eksternal, maka kita perlu membuat abstraksi yang memungkinkan kita untuk memetakan entitas Model Domain ke database ( seperti yang NimChimpsky sebutkan , menggunakan data-mapper). Perbedaan yang jelas, adalah bahwa sekarang kita perlu membuat pemetaan untuk setiap entitas model ke basis data (baik skema lama atau prosedur tersimpan), dengan rasa sakit tambahan bahwa, karena keduanya tidak sinkron, satu entitas domain mungkin memetakan sebagian ke entitas basis data (misalnya kelas UserCredentials yang hanya berisi nama pengguna dan kata sandi dipetakan ke tabel Pengguna yang memiliki kolom lain), atau satu entitas model domain dapat memetakan ke lebih dari satu entitas basis data (misalnya jika ada satu-ke- satu pemetaan di atas meja, tetapi kami ingin semua data hanya dalam satu kelas).

Dalam aplikasi dengan beberapa entitas, jumlah pekerjaan tambahan mungkin kecil jika tidak perlu melintangi entitas, tetapi meningkat ketika ada kebutuhan bersyarat untuk melintangi entitas (dan dengan demikian kita mungkin ingin menerapkan semacam 'malas' pemuatan'). Ketika sebuah aplikasi tumbuh memiliki lebih banyak entitas, pekerjaan ini hanya meningkat (dan saya merasa bahwa itu meningkat secara non-linear). Asumsi saya di sini, adalah bahwa kita tidak mencoba untuk menemukan kembali ORM.

Salah satu manfaat memperlakukan DB sebagai sistem eksternal, adalah kita dapat membuat kode di sekitar situasi di mana kita menginginkan 2 versi berbeda dari aplikasi yang berjalan, di mana setiap aplikasi memiliki pemetaan yang berbeda. Ini menjadi lebih menarik dalam skenario pengiriman kontinu ke produksi ... tapi saya pikir ini juga dimungkinkan dengan ORM pada tingkat yang lebih rendah.

Saya akan mengabaikan aspek keamanan, atas dasar bahwa pengembang, bahkan jika dia tidak memiliki akses ke database, dapat memperoleh sebagian besar jika tidak semua informasi yang disimpan dalam sistem, hanya dengan menyuntikkan kode berbahaya (mis. Saya tidak percaya saya lupa menghapus garis yang mencatat rincian kartu kredit pelanggan, Tuanku! ).


Pembaruan kecil (6/6/2012)

Prosedur tersimpan (setidaknya dalam Oracle) mencegah melakukan apa pun seperti pengiriman terus-menerus dengan Zero downtime, karena setiap perubahan pada struktur tabel akan membatalkan prosedur dan pemicu. Jadi selama DB diperbarui, aplikasi akan turun juga. Oracle memberikan solusi untuk Redefinisi Berbasis Edisi ini , tetapi beberapa DBA yang saya tanyakan tentang fitur ini menyebutkan bahwa itu diimplementasikan dengan buruk dan mereka tidak akan memasukkannya ke dalam DB produksi.

Augusto
sumber
Yah, jelas Anda bisa melakukan apa yang Hibernate lakukan dan menggunakan warisan untuk menghasilkan objek proxy dinamis, yang memungkinkan Anda untuk mengambil grafik objek. Itu sangat tidak sopan dengan SP: D
Max
Jadi saya akhirnya akan menemukan kembali setengah dari hibernate, tanpa 10+ tahun pengalaman yang dimiliki oleh tim hibernate :).
Augusto
1
Setiap DBA harus mencegah menjatuhkan tabel tertentu oleh pengguna tertentu. Seharusnya tidak masalah bagaimana Anda berusaha melakukannya.
JeffO
1
Anda mungkin melihat Mybatis - mungkin menyediakan fitur yang Anda butuhkan. Itu kurang ORM dari kerangka pemetaan. Anda dapat menulis SQL sesuka hati dan beri tahu Mybatis untuk meletakkannya di model objek Anda. Ini akan menangani grafik objek besar dengan beberapa kueri, yang terdengar seperti situasi yang Anda miliki (banyak prosedur tersimpan tipis).
Michael K
1
@ Agustus: Saya telah berada dalam situasi yang sama, bukan karena penggunaan SP, tetapi karena penggunaan kerangka pemetaan berpemilik yang tidak mendukung hubungan objek. Kami menghabiskan berhari-hari menulis kode yang dapat ditulis dalam hitungan menit menggunakan ORM yang tepat. Saya tidak pernah menyelesaikan masalah itu.
kevin cline

Jawaban:

16

Aplikasi Anda masih harus dimodelkan dari prinsip-prinsip desain berbasis domain. Apakah Anda menggunakan ORM, JDBC langsung, memanggil SP (atau apa pun) tidak masalah . Semoga lapisan tipis yang mengabstraksi model Anda dari SP harus melakukan trik dalam kasus ini. Seperti yang dinyatakan poster lain , Anda harus melihat SP dan hasilnya sebagai layanan dan memetakan hasilnya ke model domain Anda.

Martijn Verburg
sumber
Martijn, saya setuju bahwa aplikasi harus dimodelkan dengan menggunakan prinsip DDD, tetapi masalah saya hadapi (dan tolong beritahu saya jika ada solusi !!) adalah bahwa beberapa procs disimpan kembali sangat sedikit informasi untuk instantiante entitas DDD. Silakan lihat komentar ini di mana saya menjelaskan sedikit lebih banyak tentang informasi yang dikembalikan oleh prosedur tersimpan. Aku bisa menghindari ini, dengan menerapkan lebih dari satu proc disimpan, dan misalnya mengambil semua rincian pengguna dan kemudian memanggil satu sama lain untuk mengambil semua info akun, tapi rasanya salah :).
Augusto
1
@Augusto Nah ... Anda pengembang aplikasi sedang, sehingga Anda harus memutuskan apakah masuk akal untuk objek tertentu untuk ada dengan bidang-bidang tertentu diatur ke NULL. Jika masuk akal (untuk tugas tertentu misalnya) maka biarkan saja. Jika tidak, minta penulis SP untuk memberikan lebih banyak data, sehingga Anda dapat membuat objek Anda.
Jacek Prucia
Dan menambahkan komentar Jacek - sebenarnya sangat dapat diterima untuk memanggil 2+ procs yang tersimpan, sekali lagi menganggapnya sebagai dua layanan jarak jauh yang harus Anda panggil untuk membuat model domain Anda, tidak ada yang salah dengan itu :-).
Martijn Verburg
@ Martijn: Dalam pengalaman saya, lapisan tipis tidak cukup. Kode pemetaan mungkin jauh lebih lama daripada logika bisnis yang mendasarinya.
kevin cline
@ Kevin cline - Bagus, telah menempatkan 'mudah-mudahan' dalam jawaban :-)
Martijn Verburg
5

Apakah ada manfaat sebenarnya dari menggunakan prosedur tersimpan?

Di dunia keuangan (dan tempat-tempat di mana kepatuhan Sarbanes-Oxley diperlukan), Anda harus dapat mengaudit sistem untuk memastikan bahwa mereka melakukan apa yang seharusnya mereka lakukan. Dalam kasus ini, jauh lebih mudah untuk memastikan kepatuhan ketika semua akses data melalui prosedur yang tersimpan. Dan ketika semua ad-hoc SQL dihapus, jauh lebih sulit untuk menyembunyikan sesuatu. Untuk contoh mengapa ini akan menjadi "hal yang baik", saya merujuk Anda ke makalah klasik Ken Thompson Reflections on Trusting Trust .

Tangurena
sumber
ya sejuta kali ya! Anda juga perlu memastikan bahwa pengguna tidak dapat melakukan apa pun yang seharusnya tidak mereka lakukan termasuk tidak memiliki hak langsung ke tabel dan procs yang disimpan sangat membantu.
HLGEM
1
Saya bekerja untuk perusahaan publik dan kami SOX patuh. Mungkin pengetahuan saya tentang audit kurang, tetapi saya tidak melihat perbedaan antara melakukan audit di tingkat DB (melalui procs yang disimpan) atau di tingkat aplikasi. Setiap aplikasi harus memiliki skema DB sendiri dan skema itu hanya dapat diakses dari aplikasi, daripada dibagi antara aplikasi yang berbeda.
Augusto
broken link ...
Alex R
@AlexR, tautan tetap
Tangurena
2

Prosedur tersimpan jauh lebih efisien daripada dan kode SQL sisi klien. Mereka pra-kompilasi SQL di DB yang juga memungkinkannya untuk melakukan beberapa optimasi.

Secara arsitektur, SP akan mengembalikan data minimum yang diperlukan untuk suatu tugas, yang bagus karena berarti lebih sedikit data yang ditransfer. Jika Anda memiliki arsitektur seperti itu, Anda harus menganggap DB sebagai layanan (anggaplah itu sebagai layanan web dan setiap SP adalah metode untuk memanggil). Seharusnya tidak menjadi masalah untuk bekerja dengannya seperti ini, sedangkan ORM memandu Anda untuk bekerja dengan data jarak jauh seolah-olah itu lokal, sehingga menipu Anda untuk memperkenalkan masalah kinerja jika Anda tidak hati-hati.

Saya telah berada dalam situasi di mana kami menggunakan SP sepenuhnya, DB menyediakan API data dan kami menggunakannya. Aplikasi khusus itu berskala sangat besar dan berkinerja sangat baik. Saya tidak akan mengatakan hal buruk tentang SP setelah itu!

Ada keuntungan lain - DBA akan menulis semua pertanyaan SQL Anda untuk Anda, dan dengan senang hati akan menangani semua hierarki relasional dalam DB, jadi Anda tidak perlu melakukannya.

gbjbaanb
sumber
3
gbjbaanb, sebagian besar dari apa yang Anda katakan benar untuk database yang lebih lama. Sebagian besar database baru mengkompilasi ulang kueri cukup sering untuk memutuskan optimisasi baru mana yang akan digunakan (bahkan jika mereka dalam penyimpanan yang diproduksi). Saya setuju dengan apa yang Anda katakan tentang menggunakan DB sebagai sistem eksternal, tetapi saya juga melihat bahwa banyak pekerjaan, karena aplikasi memiliki database dan keduanya harus disinkronkan sebanyak mungkin. Misalnya dengan penamaan tabel / kelas dan bidang / kolom. Juga, pendekatan membiarkan DBA menulis prosedur berbau seperti silo pengembangan, daripada memiliki tim multidisiplin.
Augusto
7
SPs tidak selalu selalu lebih efisien dan saya pikir menyerahkan SQL ke DBA adalah cara yang buruk untuk pergi. Sebagai pakar domain, pengembang harus mengetahui data apa yang ingin mereka peroleh dan cara mendapatkannya
Martijn Verburg
1
Ini adalah jawaban yang baik, tetapi dalam pengalaman saya kebanyakan klien tidak benar-benar membutuhkan kinerja keuntungan untuk mengontrol akses data melalui prosedur yang tersimpan versus ketidaknyamanan membuat penuh penggunaan alat ORM Anda pada lapisan aplikasi. Lebih sering daripada tidak saya melihat ini keputusan arsitektur yang dibuat di toko-toko perangkat lunak di mana mereka memiliki kebutuhan untuk membenarkan gaji membengkak dari "abu-abu jenggot" disimpan programmer prosedur yang tidak memiliki keterampilan lain.
maple_shaft
1
@ Agusto the approach of letting the DBAs write the procedures smells like development silos+100 internet kepada Anda untuk permata kebenaran ini. Saya selalu melihat ini sebagai kasus di mana akses data dikendalikan melalui prosedur yang tersimpan.
maple_shaft
1
@maple_shaft: mengapa, bukankah DBA yang menulis SP dianggap sebagai bagian dari tim pengembang? Di mana ia bekerja, mereka adalah coders spesialis yang mengetahui aspek sistem ini dengan sangat baik, jauh lebih baik daripada kebanyakan pengembang tujuan umum. Ini bisa menjadi masalah yang memunculkan popularitas ORM. Maksudku, tidak ada yang akan berpikir dua kali untuk memiliki desainer melakukan GUI, jadi mengapa benci untuk arsitek data yang melakukan skema?
gbjbaanb
2

Yang sering terjadi adalah bahwa pengembang salah menggunakan objek ORM mereka sebagai model domain mereka.

Ini tidak benar, dan mengikat domain Anda langsung ke skema DB Anda.

Apa yang benar-benar harus miliki adalah model domain terpisah sekaya yang Anda suka dan gunakan layer ORM secara terpisah.

Ini berarti Anda akan perlu memetakan antara setiap set objek.

ozz
sumber
1
Ini adalah ide yang bagus tetapi untuk proyek-proyek kecil itu benar-benar mulai terasa seperti berlebihan. Pendekatan ini juga membutuhkan lapisan terjemahan antara lapisan persistensi ORM dan model domain.
maple_shaft
@maple_shaft setuju, dan itulah yang saya maksud dengan "mapping" :-)
ozz
@ Ozz, cara saya bekerja adalah persis seperti itu, kelas entitas ADALAH model domain (dan saya mungkin menambahkan dengan cukup banyak keberhasilan). Saya setuju bahwa itu mengikat model domain ke skema, tapi itulah yang saya inginkan, karena saya menggunakan konvensi lebih dari konfigurasi, dan efek samping yang bagus adalah bahwa jika saya melihat bidang pada suatu entitas, saya tidak perlu berpikir keras tentang nama tabel dan kolom tempat informasi itu disimpan.
Augusto
@ Agustus Saya sudah melakukannya juga! dan seperti yang dikatakan maple_shaft, itu bagus untuk aplikasi gaya CRUD kecil, tetapi ada banyak masalah saat OP mengetahuinya. Salah satu contoh mungkin adalah di mana Anda memiliki banyak tabel pemetaan misalnya: StudentClasses, yang memetakan Siswa ke kelas mereka dan hanya berisi StudentID dan classID, Anda tidak perlu ingin memetakan ini di domain Anda. Itu hanya contoh singkat dari atas kepala saya.
ozz
2
@ Ozz: Komentar Anda tampaknya bertentangan dengan gagasan ORM. ORM tidak "mengikat domain Anda langsung dengan skema DB Anda". ORM memetakan domain Anda ke skema DB, tanpa perlu lapisan DAO terpisah. Itulah inti dari ORM. Dan sebagian besar ORM menangani pemetaan banyak ke banyak dengan baik, tanpa model domain yang diperlukan untuk tabel pemetaan.
kevin cline
1

Objek domain Anda dapat diisi sesuka Anda, tidak perlu menggunakan Hibernate. Saya pikir istilah yang tepat adalah data-mapper . Sangat mungkin bahwa data bertahan Anda akan struktur yang sama sekali berbeda dengan objek domain Anda.

NimChimpsky
sumber
Kami saat ini menggunakan pemetaan data, tetapi masalahnya adalah mereka menyimpan procs mengembalikan set minimal data, yang kadang-kadang tidak cukup untuk mengisi objek (mungkin kita harus membiarkan prosedur tersimpan mengembalikan informasi lebih lanjut). Misalnya, satu toko proc mungkin mengembalikan email pengguna, nama kecil, nama keluarga; sementara yang lain menambahkan userid dan alamat. Karena data berbeda, kami menggunakan objek yang berbeda untuk menyimpan data, yang berarti kami memiliki kelas 'Pengguna' yang berbeda. Saya mencoba untuk menghindari menggunakan warisan di sini, karena saya pikir itu salah menggunakannya.
Augusto
@ Agugo: Antarmuka?
Kramii Reinstate Monica
@ Karmii, saya tidak berpikir antarmuka membantu di sini, karena kita kemudian perlu menduplikasi logika di kelas yang berbeda. Atau kita bisa menggunakan antarmuka dan kemudian mendelegasikan pemrosesan ke kelas pembantu, tapi itu tidak benar-benar OO :(.
Augusto
1
@ Agustus Saya tidak mengerti masalah: "procs yang disimpan mengembalikan set minimal data, yang kadang-kadang tidak cukup untuk mengisi objek" Jadi Anda mengubah sproc atau membuat yang lain, dan kemudian biarkan mapper data melakukan pemetaan
NimChimpsky