Saya masuk ke Domain Driven Design dan beberapa konsep yang saya temui sangat masuk akal, tetapi ketika saya memikirkannya lebih banyak, saya harus bertanya-tanya apakah itu benar-benar ide yang bagus.
Konsep Agregat, misalnya masuk akal. Anda membuat domain kepemilikan kecil sehingga Anda tidak harus berurusan dengan seluruh model domain.
Namun, ketika saya memikirkan hal ini dalam konteks aplikasi web, kita sering menekan basis data untuk menarik sebagian kecil bagian data. Misalnya, sebuah halaman hanya dapat mencantumkan jumlah pesanan, dengan tautan untuk mengklik untuk membuka pesanan dan melihat nomor pesanannya.
Jika aku pemahaman Agregat benar, saya biasanya akan menggunakan pola repositori untuk mengembalikan OrderAggregate yang akan berisi para anggota GetAll
, GetByID
, Delete
, dan Save
. Ok, kedengarannya bagus. Tapi...
Jika saya memanggil GetAll untuk mendaftar semua pesanan saya, tampaknya bagi saya bahwa pola ini akan membutuhkan seluruh daftar informasi agregat untuk dikembalikan, menyelesaikan pesanan, memesan baris, dll ... Ketika saya hanya memerlukan sebagian kecil dari informasi itu (hanya informasi tajuk).
Apakah saya melewatkan sesuatu? Atau ada beberapa tingkat optimasi yang akan Anda gunakan di sini? Saya tidak dapat membayangkan bahwa seseorang akan menganjurkan mengembalikan seluruh agregat informasi ketika Anda tidak membutuhkannya.
Tentu saja, orang bisa membuat metode seperti repositori Anda GetOrderHeaders
, tetapi itu tampaknya mengalahkan tujuan menggunakan pola seperti repositori.
Adakah yang bisa menjelaskan ini untuk saya?
EDIT:
Setelah penelitian lebih lanjut, saya pikir pemutusan di sini adalah bahwa pola Repositori murni berbeda dari apa yang kebanyakan orang pikirkan tentang Repositori.
Fowler mendefinisikan repositori sebagai penyimpan data yang menggunakan semantik koleksi, dan umumnya disimpan dalam memori. Ini berarti membuat grafik seluruh objek.
Evans mengubah Repositori untuk memasukkan Agregat Roots, dan repositori diamputasi untuk hanya mendukung objek dalam Agregat.
Kebanyakan orang tampaknya menganggap repositori sebagai Objek Akses Data yang dimuliakan, di mana Anda hanya membuat metode untuk mendapatkan data apa pun yang Anda inginkan. Itu tampaknya tidak menjadi maksud seperti yang dijelaskan dalam Pola Arsitektur Aplikasi Perusahaan Fowler.
Yang lain lagi menganggap repositori sebagai abstraksi sederhana yang digunakan terutama untuk membuat pengujian dan ejekan lebih mudah, atau untuk memisahkan kegigihan dari sisa sistem.
Saya kira jawabannya adalah bahwa ini adalah konsep yang jauh lebih kompleks daripada yang saya pikirkan sebelumnya.
sumber
Jawaban:
Jangan gunakan Model Domain Anda dan agregat untuk kueri.
Sebenarnya, apa yang Anda tanyakan adalah pertanyaan yang cukup umum bahwa seperangkat prinsip dan pola telah ditetapkan untuk menghindari hal itu. Itu disebut CQRS .
sumber
Saya berjuang, dan masih berjuang, dengan cara terbaik menggunakan pola repositori dalam Desain Domain Driven. Setelah menggunakannya sekarang untuk pertama kalinya, saya menemukan praktik berikut:
Repositori harus sederhana; itu hanya bertanggung jawab untuk menyimpan objek domain dan mengambilnya. Semua logika lain harus di objek lain, seperti pabrik dan layanan domain.
Repositori berperilaku seperti koleksi seolah-olah itu adalah kumpulan memori dari akar agregat.
Repositori bukan DAO generik, masing-masing repositori memiliki antarmuka yang unik dan sempit. Repositori sering memiliki metode pencari spesifik yang memungkinkan Anda untuk mencari koleksi dalam hal domain (misalnya: beri saya semua pesanan terbuka untuk pengguna X). Repositori itu sendiri dapat diimplementasikan dengan bantuan DAO generik.
Idealnya metode finder hanya akan mengembalikan akar agregat. Jika itu tidak efisien, ia juga dapat mengembalikan objek nilai hanya baca daripada berisi apa yang Anda butuhkan (meskipun ini merupakan nilai tambah jika objek nilai ini juga dapat dinyatakan dalam domain). Sebagai upaya terakhir repositori juga dapat digunakan untuk mengembalikan himpunan bagian atau koleksi himpunan bagian dari agregat root.
Pilihan seperti ini bergantung pada teknologi yang digunakan, karena Anda perlu menemukan cara untuk paling efisien mengekspresikan model domain Anda dengan teknologi yang digunakan.
sumber
Saya tidak berpikir metode GetOrderHeaders Anda mengalahkan tujuan repositori sama sekali.
DDD prihatin (antara lain) dengan memastikan bahwa Anda mendapatkan apa yang Anda butuhkan melalui agregat root (misalnya, Anda tidak akan memiliki Repositori OrderDetailsRepository), tetapi itu tidak membatasi Anda dengan cara yang Anda sebutkan.
Jika OrderHeader adalah konsep Domain, maka Anda harus mendefinisikannya dan memiliki metode penyimpanan yang tepat untuk mengambilnya. Pastikan saja Anda melakukan root agregat yang benar saat melakukannya.
sumber
Penggunaan DDD saya mungkin tidak dianggap DDD "murni" tapi saya telah mengadaptasi strategi dunia nyata berikut menggunakan DDD terhadap penyimpanan data DB.
** Anda tidak perlu mengembalikan seluruh agregat. Namun, jika Anda menginginkan lebih, Anda harus menanyakan root, bukan layanan atau repositori lain. Ini adalah pemuatan malas dan dapat dilakukan secara manual dengan pemuatan malas orang miskin (menyuntikkan repositori / layanan yang sesuai ke root) atau menggunakan dan ORM yang mendukung ini.
Dalam contoh Anda, saya mungkin akan menyediakan panggilan repositori yang hanya membawa header pesanan jika saya ingin memuat detail pada panggilan terpisah. Perhatikan bahwa dengan memiliki "OrderHeader" kami sebenarnya memperkenalkan konsep tambahan ke dalam domain.
sumber
Model domain Anda berisi logika bisnis Anda dalam bentuk yang paling murni. Semua hubungan dan operasi yang mendukung operasi bisnis. Apa yang Anda lewatkan dari peta konseptual Anda adalah gagasan tentang Layanan Lapisan Aplikasi lapisan layanan membungkus model domain dan memberikan tampilan yang disederhanakan dari domain bisnis (proyeksi jika Anda mau) yang memungkinkan model Domain untuk mengubah sesuai kebutuhan tanpa secara langsung memengaruhi aplikasi menggunakan lapisan layanan.
Melangkah lebih jauh Gagasan agregat adalah bahwa ada satu objek, akar agregat, yang bertanggung jawab untuk menjaga konsistensi agregat. Dalam contoh Anda, pesanan akan bertanggung jawab untuk memanipulasi garis pesanannya.
Sebagai contoh Anda, lapisan layanan akan memaparkan operasi seperti GetOrdersForCustomer yang hanya akan mengembalikan apa yang diperlukan untuk melihat daftar ringkasan pesanan (seperti Anda menyebutnya OrderHeaders).
Akhirnya, pola Repositori tidak hanya koleksi, tetapi juga memungkinkan untuk permintaan deklaratif. Dalam C # Anda dapat menggunakan LINQ sebagai Obyek Kueri , atau sebagian besar O / RM lainnya menyediakan spesifikasi Obyek Kueri juga.
Melihat bahwa Anda dapat membuat kueri terhadap repositori, masuk akal juga untuk memberikan metode kenyamanan yang menangani kueri umum. Yaitu jika Anda hanya ingin header pesanan Anda, Anda dapat membuat kueri yang mengembalikan hanya header dan mengeksposnya dari metode kenyamanan di repositori Anda.
Semoga ini bisa membantu memperjelas hal-hal.
sumber
Saya tahu ini adalah pertanyaan lama, tetapi saya tampaknya memiliki jawaban yang berbeda.
Ketika saya membuat Repositori, umumnya ia membungkus beberapa kueri yang di- cache .
Simpan repositori itu di ram server Anda. Mereka tidak hanya melewati objek ke database!
Jika saya dalam aplikasi web dengan pesanan daftar halaman, yang dapat Anda klik untuk melihat detailnya, kemungkinan saya ingin halaman daftar pesanan saya memiliki detail tentang pesanan (ID, Nama, Jumlah, Tanggal) untuk membantu pengguna memutuskan mana yang ingin mereka lihat.
Pada titik ini Anda memiliki dua opsi.
Anda dapat melakukan query database dan menarik kembali apa yang Anda butuhkan untuk membuat listing, lalu query lagi untuk menarik detail individual yang perlu Anda lihat pada halaman detail.
Anda dapat membuat 1 kueri yang menarik kembali semua informasi dan menyimpannya. Pada permintaan halaman berikutnya Anda membaca dari ram server bukan dari database. Jika pengguna menekan balik atau memilih halaman berikutnya Anda masih melakukan nol perjalanan ke database.
Pada kenyataannya bagaimana Anda menerapkannya hanya itu, dan detail implementasi. Jika pengguna terbesar saya memiliki 10 pesanan, saya mungkin ingin menggunakan opsi 2. Jika saya berbicara 10.000 pesanan maka opsi 1 diperlukan. Dalam kedua kasus di atas dan dalam banyak kasus lain saya ingin repositori menyembunyikan detail implementasi itu.
Ke depan jika saya mendapatkan tiket untuk memberi tahu pengguna berapa banyak yang telah mereka belanjakan untuk pesanan ( data teragregasi ) pada bulan lalu di halaman daftar pesanan, apakah saya lebih suka menulis logika untuk menghitungnya dalam SQL dan melakukan perjalanan bolak-balik lagi ke DB atau Anda lebih suka menghitungnya menggunakan data yang sudah ada di server ram?
Dalam pengalaman saya, agregat domain menawarkan manfaat besar.
sumber