Hari ini saya terlibat perdebatan sengit dengan pengembang lain di organisasi saya tentang di mana dan bagaimana cara menambahkan metode ke kelas yang dipetakan basis data. Kami menggunakan sqlalchemy
, dan bagian utama dari basis kode yang ada dalam model database kami sedikit lebih dari sekumpulan properti yang dipetakan dengan nama kelas, terjemahan yang hampir mekanis dari tabel database ke objek python.
Dalam argumen, posisi saya adalah bahwa nilai utama menggunakan ORM adalah Anda dapat melampirkan perilaku tingkat rendah dan algoritma ke kelas yang dipetakan. Model adalah kelas pertama, dan persisten kedua (mereka bisa gigih menggunakan xml dalam sistem file, Anda tidak perlu peduli). Pandangannya adalah bahwa setiap perilaku sama sekali adalah "logika bisnis", dan harus milik di mana saja tetapi dalam model persisten, yang hanya akan digunakan untuk kegigihan basis data.
Saya tentu saja berpikir bahwa ada perbedaan antara apa itu logika bisnis, dan harus dipisahkan, karena memiliki beberapa isolasi dari tingkat yang lebih rendah tentang bagaimana yang diterapkan, dan logika domain, yang saya percaya adalah abstraksi yang diberikan oleh kelas model membantah dalam paragraf sebelumnya, tetapi saya mengalami kesulitan meletakkan jari saya pada apa itu. Saya memiliki perasaan yang lebih baik tentang apa yang mungkin menjadi API (yang, dalam kasus kami, adalah HTTP "ReSTful"), di mana pengguna memohon API dengan apa yang ingin mereka lakukan , berbeda dari apa yang mereka boleh lakukan, dan bagaimana selesai.
tl; dr: Hal-hal apa saja yang dapat atau harus dilakukan dalam suatu metode dalam kelas yang dipetakan saat menggunakan ORM, dan apa yang harus ditinggalkan, untuk hidup dalam lapisan abstraksi lain?
sumber
Jawaban:
Aku sebagian besar bersamamu; kolega Anda tampaknya berdebat baik untuk antipattern model domain anemis atau untuk menduplikasi model dalam "model persistensi" tanpa manfaat yang jelas (saya sedang mengerjakan proyek Java di mana ini dilakukan, dan itu adalah sakit kepala pemeliharaan yang besar, karena itu berarti tiga kali pekerjaan setiap kali ada perubahan dalam model).
Rule of thumb: kelas harus mengandung logika yang menggambarkan fakta dasar tentang data yang benar dalam semua keadaan. Logika yang khusus untuk use case harus berada di tempat lain. Contohnya adalah validasi, ada artikel menarik dari Martin Fowler di mana ia menekankan bahwa itu harus dianggap tergantung pada konteks.
sumber
Ini adalah panggilan penilaian yang sangat tergantung pada ukuran dan skala yang Anda perkirakan dari apa yang Anda kembangkan. Pendekatan yang paling kaku adalah membatasi tipe ORM ke komponen akses data dan menggunakan POCO di perpustakaan umum sebagai tipe yang dirujuk dan digunakan oleh semua lapisan. Ini akan memungkinkan pemisahan fisik di masa depan serta pemisahan logis. Anda juga bisa memutuskan bahwa lapisan tambahan harus ada antara UI dan lapisan logika bisnis. Ini biasanya disebut lapisan Fasad atau Antarmuka Bisnis. Lapisan tambahan ini adalah tempat tinggal "kode kasus penggunaan" Anda. Kode yang digabungkan secara individu disebut oleh lapisan Fasad / BI (misalnya Fasad memiliki fungsi ProcessOrder () yang memanggil ke logika bisnis 1: M kali untuk melakukan semua langkah yang diperlukan untuk benar-benar memproses pesanan).
Namun, semua itu dikatakan: berkali-kali jumlah arsitektur ini tidak perlu berlebihan. Misalnya, kode khusus untuk situs Web sederhana di mana Anda tidak memiliki niat untuk mengemas komponennya untuk digunakan kembali. Sangat valid untuk membuat situs web MVC dan menggunakan objek EF untuk jenis solusi ini. Jika situs perlu diubah nantinya, Anda dapat melihat pengelompokan atau proses yang sering hilang yang disebut "refactoring."
sumber
Hanya ingatkan kolega Anda bahwa Anda tidak perlu merancang arsitektur secara berlebihan seolah-olah ini adalah proyek Java. Maksud saya, membandingkan dua objek yang bertahan adalah perilaku, tapi tidak ada yang ditentukan oleh lapisan kegigihan. Jadi pertanyaan 6 bir adalah: mengapa kelas yang benar-benar tidak berhubungan menggambarkan sesuatu tentang hal yang sama? Tentu, ketekunan adalah aspek besar yang cukup dari model untuk diperlakukan secara terpisah, tetapi tidak cukup untuk menjamin bahwa itu diperlakukan berbeda dari yang lainnya. Jika Anda mengendarai mobil, mencucinya, atau merusaknya, Anda memanipulasi mobil Anda sepanjang waktu.
Jadi mengapa tidak hanya menyusun semua aspek yang berbeda ini menjadi kelas model tunggal? Anda memerlukan banyak metode kelas yang berhubungan dengan objek yang ada - letakkan mereka dalam satu kelas; Anda memiliki banyak metode instan yang berhubungan dengan validasi - letakkan di yang lain. Akhirnya, campur keduanya menjadi dan voila! Anda mendapatkan representasi model yang cerdas, sadar diri, dan lengkap di sana.
sumber
Selain jawaban lain, perhatikan peringatan tersembunyi saat menggunakan model domain kaya dengan ORM.
Saya mengalami masalah dalam menyuntikkan layanan polimorfik di kelas model yang bertahan saat mencoba mencapai sesuatu seperti kodesemu berikut:
Dalam hal ini, Organisasi mungkin memerlukan
HRService
dependensi sebagai konstruktor (misalnya). Anda biasanya tidak dapat dengan mudah mengontrol instanciation kelas model Anda saat menggunakan ORM.Saya menggunakan Doktrin ORM dan wadah layanan dari Symfony. Saya harus monkeypatch ORM dengan cara yang tidak begitu elegan dan tidak punya pilihan selain untuk memisahkan ketekunan dan model bisnis. Saya belum mencoba dengan sqlachemy, pikir. Python mungkin terbukti lebih fleksibel daripada PHP untuk hal ini.
sumber