Model tebal Vs. Logika Bisnis, Di mana Anda menggambar perbedaan?

16

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?

SingleNegationElimination
sumber
Menurut saya itu adalah dua masalah yang dibahas pada saat yang sama, masalah Model persisten adalah kelas pertama, dan kedua gigih (mereka bisa gigih menggunakan xml dalam sistem file, Anda tidak perlu peduli). dan alasan kodenya. Biasanya hal-hal yang jelas, setidaknya bagi saya, ketika saya bertanya pada diri sendiri mengapa kode ini ditulis, persyaratan apa yang memaksa kode ini. Apakah itu persyaratan pelanggan tentang bagaimana program akan bekerja atau dari mana kita memilih untuk mengimplementasikannya. Bagi saya yang pertama adalah logika bisnis dan kedua apa yang Anda sebut logika domain. Bagaimana ini membantu.

Jawaban:

10

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).

Apa saja hal-hal 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?

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.

Michael Borgwardt
sumber
+1, untuk bagian kedua dari jawaban Anda. Adapun bagian pertama, saya yakin mengapa Anda mengatakan bahwa model domain anemia membutuhkan banyak pekerjaan 'ekstra' jika terjadi perubahan. Pemahaman saya adalah perubahan akan terjadi bagaimanapun juga di beberapa kelas yang berbeda (yang agak buruk) tetapi jumlah perubahannya hampir sama; Saya kira?
NoChance
1
@Emmad Kareem: Komentarnya adalah tentang memiliki ketekunan spearate dan model domain. Menambahkan properti ke model kemudian memerlukan menambahkannya ke dua kelas model (bukan satu) serta ke peta apa pun di antara mereka (yang secara teori bisa otomatis, tetapi biasanya asshat yang berpikir itu ide yang baik untuk memiliki terpisah "persistence model" memutuskan untuk membenarkan pemisahan itu dengan membuatnya berbeda, mis. memiliki tipe data yang lebih cocok dengan model tipe DB) sehingga itu 2 + X kali jumlah perubahan, dengan X bervariasi antara 0 dan jam dari hilangnya produktivitas karena tidak jelas masalah pemetaan.
Michael Borgwardt
3

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."

Sean Chase
sumber
3

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.

Filip Dupanović
sumber
1

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:

Person john = new Person('John Doe')
Organisation company = organisation_repository.find('some id')
Employee our_collegue_john = company.hire(john)

Dalam hal ini, Organisasi mungkin memerlukan HRServicedependensi 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.

abstrus
sumber