Saya sedang mempelajari DDD hari ini, dan saya memiliki beberapa pertanyaan mengenai bagaimana mengelola repositori dengan DDD.
Sebenarnya, saya telah bertemu dua kemungkinan:
Pertama
Cara pertama mengelola layanan yang saya baca adalah menyuntikkan repositori dan model domain dalam layanan aplikasi.
Dengan cara ini, dalam salah satu metode layanan aplikasi, kami memanggil metode layanan domain (memeriksa aturan bisnis) dan jika kondisinya baik, repositori dipanggil pada metode khusus untuk bertahan / mengambil entitas dari database.
Cara sederhana untuk melakukan ini adalah:
class ApplicationService{
constructor(domainService, repository){
this.domainService = domainService
this.repository = repository
}
postAction(data){
if(this.domainService.validateRules(data)){
this.repository.persist(new Entity(data.name, data.surname))
}
// ...
}
}
Kedua
Kemungkinan kedua adalah menyuntikkan repositori di dalam domainService saja, dan hanya menggunakan repositori melalui layanan domain:
class ApplicationService{
constructor(domainService){
this.domainService = domainService
}
postAction(data){
if(this.domainService.persist(data)){
console.log('all is good')
}
// ...
}
}
class DomainService{
constructor(repository){
this.repository = repository
}
persist(data){
if(this.validateRules(data)){
this.repository.save(new Entity(data.name))
}
}
validateRules(data){
// returns a rule matching
}
}
Mulai sekarang, saya tidak dapat membedakan mana yang terbaik (jika ada yang terbaik) atau apa yang mereka maksudkan keduanya dalam konteks mereka.
Bisakah Anda memberi saya contoh di mana yang satu bisa lebih baik dari yang lain dan mengapa?
sumber
Jawaban:
Jawaban singkatnya adalah - Anda dapat menggunakan repositori dari layanan aplikasi, atau layanan domain - tetapi penting untuk mempertimbangkan mengapa, dan bagaimana, Anda melakukannya.
Tujuan Layanan Domain
Layanan Domain harus merangkum konsep / logika domain - dengan demikian, metode layanan domain:
tidak termasuk dalam layanan domain, karena
persist
bukan bagian dari bahasa di mana - mana dan operasi kegigihan bukan bagian dari logika bisnis domain.Secara umum, layanan domain berguna ketika Anda memiliki aturan / logika bisnis yang memerlukan koordinasi atau bekerja dengan lebih dari satu agregat. Jika logika hanya melibatkan satu agregat, harus dalam metode pada entitas agregat itu.
Repositori dalam Layanan Aplikasi
Jadi dalam pengertian itu, dalam contoh Anda, saya lebih suka opsi pertama Anda - tetapi bahkan ada ruang untuk perbaikan, karena layanan domain Anda menerima data mentah dari api - mengapa layanan domain harus tahu tentang struktur
data
? Selain itu, data tampaknya hanya terkait dengan agregat tunggal, jadi ada nilai terbatas dalam menggunakan layanan domain untuk itu - umumnya saya akan meletakkan validasi di dalam konstruktor entitas. misalnyadan melemparkan pengecualian jika tidak valid. Bergantung pada kerangka aplikasi Anda, mungkin sederhana untuk memiliki mekanisme yang konsisten untuk menangkap pengecualian dan memetakannya ke respons yang sesuai untuk jenis api - mis. Untuk api REST, kembalikan kode status 400.
Gudang di Layanan Domain
Terlepas dari hal di atas, kadang-kadang berguna untuk menyuntikkan dan menggunakan repositori dalam layanan domain, tetapi hanya jika repositori Anda diimplementasikan sedemikian rupa sehingga mereka menerima dan mengembalikan akar agregat saja, dan juga di mana Anda mengabstraksi logika yang melibatkan banyak agregat. misalnya
implementasi layanan domain akan terlihat seperti:
Kesimpulan
Kuncinya di sini adalah layanan domain merangkum proses yang merupakan bagian dari bahasa di mana-mana. Untuk memenuhi perannya, ia perlu menggunakan repositori - dan tidak apa-apa untuk melakukannya.
Tetapi menambahkan layanan domain yang membungkus repositori dengan metode yang disebut
persist
menambah sedikit nilai.Atas dasar itu, jika layanan aplikasi Anda mengekspresikan use case yang meminta untuk hanya bekerja dengan agregat tunggal, tidak ada masalah menggunakan repositori langsung dari layanan aplikasi.
sumber
Ada masalah dengan jawaban yang diterima:
Model domain tidak diperbolehkan bergantung pada repositori dan layanan domain adalah bagian dari model domain -> layanan domain tidak boleh bergantung pada repositori.
Yang harus Anda lakukan adalah merakit semua entitas Anda yang diperlukan untuk eksekusi logika bisnis yang sudah ada dalam layanan aplikasi dan kemudian hanya menyediakan model Anda dengan objek yang dipakai.
Berdasarkan contoh Anda itu bisa terlihat seperti ini:
Jadi, aturan praktis: Model domain tidak bergantung pada lapisan luar
Aplikasi vs Layanan domain Dari artikel ini :
Layanan domain sangat granular di mana layanan aplikasi adalah fasad yang bertujuan menyediakan API.
Layanan domain berisi logika domain yang tidak dapat secara alami ditempatkan dalam entitas atau objek nilai sedangkan layanan aplikasi mengatur eksekusi logika domain dan tidak sendiri menerapkan logika domain apa pun.
Metode layanan domain dapat memiliki elemen domain lainnya sebagai operan dan nilai kembali sedangkan layanan aplikasi beroperasi pada operan sepele seperti nilai identitas dan struktur data primitif.
Layanan aplikasi menyatakan ketergantungan pada layanan infrastruktur yang diperlukan untuk mengeksekusi logika domain.
sumber
Tak satu pun dari pola Anda yang baik kecuali layanan dan objek Anda merangkum beberapa tanggung jawab yang koheren.
Pertama-tama katakanlah apa objek domain Anda dan bicarakan apa yang dapat dilakukan dalam bahasa domain. Jika bisa valid atau tidak valid mengapa tidak memiliki ini sebagai properti dari objek domain itu sendiri?
Jika misalnya validitas objek hanya masuk akal dalam hal objek lain maka mungkin Anda memiliki tanggung jawab 'aturan validasi X untuk objek domain' yang dapat.dienkapsulasi dalam satu set layanan.
Apakah memvalidasi objek mengharuskan penyimpanannya dalam aturan bisnis Anda? Mungkin tidak. Tanggung jawab 'menyimpan objek' biasanya berjalan dalam objek repositori terpisah.
Sekarang Anda memiliki operasi yang ingin Anda lakukan yang mencakup berbagai tanggung jawab, membuat objek, memvalidasinya, dan jika valid, simpanlah.
Apakah operasi ini intrinsik ke objek domain? Kemudian Jadikan itu bagian dari objek itu yaitu
ExamQuestion.Answer(string answer)
Apakah itu cocok dengan beberapa bagian lain dari domain Anda? letakkan di sana
Basket.Purchase(Order order)
Apakah Anda lebih suka melakukan layanan ADM REST? Baiklah kalau begitu.
sumber