Saya akan mengawali pertanyaan ini dengan mengatakan bahwa saya relatif baru di DDD jadi saya mungkin membuat beberapa kesalahan mendasar di sini!
Saya mengerjakan proyek yang melibatkan konsep Akun dan Transaksi (dalam arti finansial). Akun dapat memiliki banyak Transaksi yang dimasukkan.
Sepertinya saya bahwa Akun dan Transaksi adalah dua Entitas, dan Akun itu adalah akar Agregat yang mengandung Transaksi karena Transaksi tidak dapat terjadi tanpa Akun.
Namun ketika saya datang untuk menerapkan ini dalam kode saya langsung mendapat masalah. Dalam banyak situasi, sangat tidak berguna bagi saya untuk memiliki daftar setiap Transaksi dalam Akun setiap saat. Saya tertarik untuk dapat melakukan hal-hal seperti menghitung saldo Akun dan memberlakukan invarian seperti batas kredit, tetapi saya juga ingin dapat dengan mudah bekerja dengan himpunan bagian dari Transaksi (misalnya menampilkan yang termasuk dalam rentang tanggal).
Dalam kasus terakhir, jika saya menggunakan TransactionRepository
saya dapat secara efisien mengakses objek-objek yang saya butuhkan tanpa memuat seluruh daftar (berpotensi sangat besar). Namun ini akan memungkinkan hal selain Akun untuk bekerja dengan Transaksi yang berarti saya telah melanggar konsep Akun sebagai akar agregat.
Bagaimana orang menangani situasi seperti ini? Apakah Anda hanya menerima memori dan implikasi kinerja dari memuat sejumlah besar anak-anak yang berpotensi menjadi root agregat?
sumber
tl; dr - langgar aturan jika perlu. DDD tidak bisa menyelesaikan semua masalah; sebenarnya ide-ide objek yang diberikannya adalah nasihat yang baik dan awal yang baik, tetapi pilihan yang sangat buruk untuk beberapa masalah bisnis. Anggap itu petunjuk bagaimana melakukan sesuatu.
Untuk masalah memuat semua anak (transaksi) dengan orang tua (akun) - Sepertinya Anda mengalami masalah n +1 (sesuatu ke google) yang telah diselesaikan banyak ORM.
Anda dapat menyelesaikannya dengan malas memuat anak-anak (transaksi) - hanya jika diperlukan.
Tetapi sepertinya Anda sudah tahu bahwa dengan menyebutkan bahwa Anda dapat menggunakan TransactionRepository untuk menyelesaikan masalah.
Untuk 'menyembunyikan' data itu sehingga hanya Akun yang dapat menggunakannya, Anda bahkan tidak perlu menyimpannya di tempat yang orang lain tidak bisa membatalkan deserialisasi, seperti tabel hubungan publik. Anda bisa menyimpannya dengan 'dokumen' akun di dokumen DB. Either way jika seseorang berusaha cukup keras mereka masih bisa melihat data. Dan 'bekerja' dengannya. Dan ketika Anda tidak melihat, mereka akan melihatnya!
Jadi Anda bisa mengatur izin, tetapi kemudian, Anda harus menjalankan 'akun' sebagai proses terpisah.
Apa yang Anda benar-benar sadari di sini adalah bahwa DDD dan penggunaan murni model objek kadang-kadang akan mengembalikan Anda ke sudut. Sejujurnya, tentu saja, Anda tidak harus menggunakan 'komposisi' / akar agregat untuk mendapatkan manfaat dari prinsip-prinsip desain DDD. Hanya satu hal yang dapat Anda gunakan ketika Anda memiliki situasi yang sesuai dengan kendala-kendala yang ada.
Seseorang mungkin mengatakan 'jangan mengoptimalkan awal'. Namun, di sini dalam kasus ini, Anda tahu jawabannya - akan ada cukup banyak transaksi untuk menghentikan suatu metode yang akan menyimpan semuanya selamanya dengan akun tersebut.
Jawaban sebenarnya adalah mulai berdiri SOA. Di tempat kerja saya, kami menonton video 'komputasi terdistribusi' Udi Dahan dan membeli nServiceBus (hanya pilihan kami). Buat layanan untuk akun - dengan prosesnya sendiri, antrian pesan, akses ke database relasi yang hanya dapat dilihatnya, dan ... viola, Anda dapat meng-hardcode pernyataan SQL dalam program dan bahkan memasukkan beberapa skrip transaksi Cobol (bercanda tentu saja) tetapi secara serius memiliki lebih banyak pemisahan kekhawatiran daripada yang bisa diimpikan oleh sombong OO / Jawa terpandai.
Saya akan merekomendasikan pemodelan dengan baik; Anda bisa mendapatkan manfaat dari agregat root di sini tanpa masalah dengan memperlakukan layanan sebagai countext mini-bounded.
Ini memiliki kekurangan, tentu saja. Anda tidak bisa hanya RPC (layanan web, SOAP, atau REST) masuk dan keluar dari layanan dan di antara mereka atau Anda mendapatkan antipattern SOA yang disebut 'simpul' karena penggabungan sementara. Anda harus menggunakan inversi pola komunikasi, alias 'Pub-Sub' yang sama seperti event handler dan event raiser, tetapi (1) antar proses (yang bisa Anda pakai di mesin terpisah jika mereka kelebihan beban di satu).
masalah sebenarnya adalah Anda tidak ingin layanan yang perlu mendapatkan data dari layanan lain untuk 'memblokir' atau menunggu - Anda harus memecat dan melupakan pesan dan membiarkan pawang di tempat lain dalam program Anda mengambilnya untuk menyelesaikan pemrosesan. Ini berarti Anda harus melakukan logika secara berbeda. nServicebus mengotomatiskan pola 'saga' untuk membantu beberapa hal ini, tetapi pada akhirnya, Anda harus mengembangkan gaya pengkodean yang berbeda. Anda masih dapat melakukan semuanya, hanya harus melakukannya secara berbeda!
Buku "Pola SOA" oleh Arnon Rotem-Gal-Oz menjawab banyak pertanyaan tentang ini. Termasuk penggunaan 'pola layanan aktif' untuk secara berkala mereplikasi data dari layanan luar ke layanan Anda saat diperlukan (banyak RPC dibutuhkan, atau tautan tidak dapat diandalkan / tidak ada dalam ekosistem publikasi / berlangganan).
Hanya untuk pratinjau, UIS jangan harus RPC ke layanan. Laporan dihasilkan dari basis data pelaporan yang diumpankan oleh basis data layanan. Beberapa orang mengatakan laporan tidak diperlukan dan masalahnya harus diselesaikan dengan cara lain. Bersikap skeptis terhadap pembicaraan itu.
Pada akhirnya, tidak semua hal dapat digolongkan ke dalam satu layanan. Dunia tidak berjalan dengan kode ravioli! Jadi, Anda harus melanggar aturan. Bahkan jika Anda tidak perlu melakukannya, pengembang baru untuk proyek akan melakukannya ketika Anda meninggalkannya. Tapi jangan khawatir, jika Anda melakukan apa yang Anda bisa, 85% yang mengikuti aturan akan membuat program yang jauh lebih mudah dikelola.
Wow, itu panjang.
sumber