Mari kita mulai dengan tinjauan singkat tentang ruang masalah: Salah satu prinsip dasar DDD adalah menempatkan aturan bisnis sedekat mungkin ke tempat-tempat di mana mereka perlu ditegakkan. Ini adalah konsep yang sangat penting karena membuat sistem Anda lebih "kohesif". Memindahkan aturan "ke atas" umumnya merupakan tanda model anemia; di mana objek hanya kantong data dan aturan disuntikkan dengan data yang akan ditegakkan.
Model anemia dapat membuat banyak akal bagi pengembang baru memulai dengan DDD. Anda membuat User
model dan EmailMustBeUnqiueRule
yang disuntikkan dengan informasi yang diperlukan untuk memvalidasi email. Sederhana. Anggun. Masalahnya adalah bahwa "pemikiran" semacam ini pada dasarnya bersifat prosedural. Bukan DDD. Apa yang akhirnya terjadi adalah Anda dibiarkan dengan modul dengan puluhan Rules
dibungkus rapi dan dikemas, tetapi mereka benar-benar tanpa konteks ke titik di mana mereka tidak lagi dapat diubah karena tidak jelas kapan / di mana mereka ditegakkan. Apakah itu masuk akal? Ini mungkin menjadi jelas bahwa EmailMustBeUnqiueRule
akan diterapkan pada penciptaan User
, tapi bagaimana UserIsInGoodStandingRule
?. Perlahan tapi pasti, grainularisasi mengekstraksiRules
di luar konteksnya membuat Anda memiliki sistem yang sulit dipahami (dan karenanya tidak dapat diubah). Aturan harus dienkapsulasi hanya ketika crunching / eksekusi aktual begitu bertele-tele sehingga model Anda mulai kehilangan fokus.
Sekarang ke pertanyaan spesifik Anda: Masalah dengan memiliki Service
/ CommandHandler
membuang Exception
adalah bahwa logika bisnis Anda mulai bocor ("ke atas") dari domain Anda. Mengapa Anda Service
/ CommandHandler
kebutuhan untuk mengetahui email harus unik? Lapisan layanan aplikasi umumnya digunakan untuk koordinasi daripada implementasi. Alasan untuk ini dapat diilustrasikan hanya jika kita menambahkan ChangeEmail
metode / perintah ke sistem Anda. Sekarang KEDUA metode / penangan perintah perlu menyertakan cek unik Anda. Di sinilah pengembang mungkin tergoda untuk "mengekstrak" suatu EmailMustBeUniqueRule
. Seperti yang dijelaskan di atas, kami tidak ingin menempuh rute itu.
Beberapa tambahan pengetahuan bisa membawa kita ke jawaban DDD yang lebih banyak. Keunikan email adalah invarian yang harus diberlakukan di kumpulan User
objek. Apakah ada konsep di domain Anda yang mewakili "kumpulan User
objek"? Saya pikir Anda mungkin bisa melihat ke mana saya pergi ke sini.
Untuk kasus khusus ini (dan banyak lagi melibatkan penegakan invarian di koleksi) tempat terbaik untuk mengimplementasikan logika ini ada di Anda Repository
. Ini sangat nyaman karena Anda Repository
juga "tahu" infrastruktur tambahan yang diperlukan untuk menjalankan validasi semacam ini (penyimpanan data). Dalam kasus Anda, saya akan menempatkan cek ini di add
metode. Ini masuk akal bukan? Secara konseptual, metode inilah yang benar-benar menambah User
sistem Anda. Menyimpan data adalah detail implementasi.