Saya menyelam di desain berbasis domain (DDD) dan sementara saya masuk lebih dalam di dalamnya ada beberapa hal yang saya tidak dapatkan. Seperti yang saya pahami, poin utama adalah untuk memisahkan Logika Domain (Logika Bisnis) dari Infrastruktur (DB, Sistem File, dll.).
Yang saya bertanya-tanya adalah, apa yang terjadi ketika saya memiliki pertanyaan yang sangat kompleks seperti Permintaan Perhitungan Sumber Daya Material? Dalam kueri semacam itu Anda bekerja dengan operasi set berat, jenis hal yang dirancang untuk SQL. Melakukan perhitungan tersebut di dalam Lapisan Domain dan bekerja dengan banyak set di dalamnya seperti membuang teknologi SQL.
Melakukan perhitungan ini dalam infrastruktur tidak dapat terjadi juga, karena pola DDD memungkinkan untuk perubahan infrastruktur tanpa mengubah Layer Domain dan mengetahui bahwa MongoDB tidak memiliki kemampuan yang sama seperti misalnya SQL Server, yang tidak dapat terjadi.
Apakah itu jebakan dari pola DDD?
sumber
... is like throwing away the SQL technology
Hanya karena teknologi tertentu dapat melakukan sesuatu tidak berarti itu adalah pilihan terbaik. Ini bukti anekdotal, tetapi saya telah bertemu terlalu banyak bisnis yang dulu menyimpan logika bisnis dalam database dan bermigrasi jauh darinya karena sakit kepala yang dapat dipelihara dalam jangka panjang. Menyederhanakan terlalu banyak, tetapi basis data dimaksudkan untuk menyimpan data dan bahasa pemrograman dimaksudkan untuk mengubah data. Saya tidak ingin menggunakan DB untuk logika bisnis lagi daripada saya ingin mencoba menggunakan aplikasi saya untuk menyimpan data saya secara langsung.Jawaban:
Saat ini, Anda cenderung melihat pembacaan (kueri) ditangani secara berbeda dari penulisan (perintah). Dalam sistem dengan kueri yang rumit, kueri itu sendiri tidak mungkin melewati model domain (yang terutama bertanggung jawab untuk menjaga konsistensi penulisan ).
Anda benar bahwa kami harus memberikan kepada SQL apa yang merupakan SQL. Jadi kami akan merancang model data yang dioptimalkan di sekitar bacaan, dan kueri model data itu biasanya akan mengambil jalur kode yang tidak termasuk model domain (dengan kemungkinan pengecualian dari beberapa validasi input - memastikan bahwa parameter dalam kueri masuk akal).
sumber
Ini adalah dasar dari kesalahpahaman: tujuan DDD bukan untuk memisahkan hal-hal di sepanjang garis keras seperti "ini di server SQL, jadi tidak boleh BL", tujuan DDD adalah untuk memisahkan domain dan menciptakan hambatan antara mereka yang memungkinkan internal suatu domain untuk sepenuhnya terpisah dari internal domain lain, dan untuk mendefinisikan eksternal yang dibagi di antara mereka.
Jangan menganggap "berada di SQL" sebagai penghalang BL / DL — bukan itu masalahnya. Sebaliknya, pikirkan "ini adalah akhir dari domain internal" sebagai penghalang.
Setiap domain harus memiliki API yang menghadap eksternal yang memungkinkannya untuk bekerja dengan semua domain lain : dalam hal lapisan penyimpanan data , itu harus memiliki tindakan baca / tulis (CRUD) untuk objek data yang disimpannya. Ini berarti SQL itu sendiri tidak benar-benar penghalang,
VIEW
danPROCEDURE
komponennya. Anda tidak boleh membaca langsung dari tabel: itu adalah detail implementasi yang dikatakan DDD kepada kita bahwa, sebagai konsumen eksternal, kita tidak perlu khawatir.Pertimbangkan contoh Anda:
Inilah yang seharusnya ada di SQL, dan itu bukan pelanggaran DDD. Untuk itulah kami membuat DDD . Dengan perhitungan dalam SQL, itu menjadi bagian dari BL / DL. Apa yang akan Anda lakukan adalah menggunakan tampilan terpisah / prosedur tersimpan / apa pun yang Anda miliki, dan menjaga logika bisnis terpisah dari lapisan data, karena itu adalah API eksternal Anda. Bahkan, lapisan data Anda harus menjadi DDD Domain Layer lain, di mana lapisan data Anda memiliki abstraksi sendiri untuk bekerja dengan lapisan domain lainnya.
Itu kesalahpahaman lain: ia mengatakan detail implementasi secara internal dapat berubah tanpa mengubah lapisan domain lainnya . Tidak dikatakan Anda hanya bisa mengganti seluruh infrastruktur.
Sekali lagi, perlu diingat, DDD adalah tentang menyembunyikan internal dengan API eksternal yang terdefinisi dengan baik. Di mana letak API itu adalah pertanyaan yang sama sekali berbeda, dan DDD tidak mendefinisikannya. Itu hanya mendefinisikan bahwa API ini ada, dan tidak boleh berubah .
DDD tidak diatur untuk memungkinkan Anda mengganti ad-hoc MSSQL dengan MongoDB — keduanya adalah komponen infrastruktur yang sama sekali berbeda.
Sebagai gantinya, mari kita gunakan analogi untuk apa yang didefinisikan oleh DDD: gas vs mobil listrik. Kedua kendaraan memiliki dua metode yang sama sekali berbeda untuk membuat propulsi, tetapi mereka memiliki API yang sama: on / off, throttle / rem, dan roda untuk mendorong kendaraan. DDD mengatakan bahwa kita harus dapat mengganti mesin (gas atau listrik) di mobil kita. Itu tidak mengatakan kita dapat mengganti mobil dengan sepeda motor, dan itulah MSSQL → MongoDB.
sumber
Jika Anda pernah berada di sebuah proyek di mana organisasi yang membayar untuk menjadi tuan rumah aplikasi memutuskan bahwa lisensi lapisan basis data terlalu mahal, Anda akan menghargai kemudahan yang Anda dapat memigrasi penyimpanan database / data Anda. Semua hal dipertimbangkan, sementara ini terjadi, itu tidak sering terjadi .
Anda bisa mendapatkan yang terbaik dari kedua dunia sehingga untuk berbicara. Jika Anda mempertimbangkan melakukan fungsi kompleks dalam basis data sebagai pengoptimalan, maka Anda dapat menggunakan antarmuka untuk menyuntikkan implementasi alternatif perhitungan. Masalahnya adalah Anda harus mempertahankan logika di beberapa lokasi.
Menyimpang dari pola arsitektur
Ketika Anda menemukan diri Anda berselisih dengan menerapkan suatu pola murni, atau menyimpang di beberapa area, maka Anda harus mengambil keputusan. Sebuah pola hanyalah cara templated untuk melakukan sesuatu untuk membantu mengatur proyek Anda. Pada titik ini perlu waktu untuk mengevaluasi:
Anda akan menemukan bahwa beberapa pola arsitektur cocok untuk 80-90% aplikasi Anda, tetapi tidak terlalu banyak untuk bit yang tersisa. Penyimpangan sesekali dari pola yang ditentukan berguna untuk kinerja atau alasan logistik.
Namun, jika Anda menemukan bahwa penyimpangan kumulatif Anda berjumlah lebih dari 20% dari arsitektur aplikasi Anda, itu mungkin hanya cocok.
Jika Anda memilih untuk terus menggunakan arsitektur, maka bantulah diri Anda sendiri dan dokumentasikan di mana dan mengapa Anda menyimpang dari cara yang ditentukan dalam melakukan sesuatu. Ketika Anda mendapatkan anggota baru yang antusias di tim Anda, Anda dapat mengarahkan mereka ke dokumentasi yang mencakup pengukuran kinerja, dan justifikasi. Itu akan mengurangi kemungkinan permintaan ulang untuk memperbaiki "masalah". Dokumentasi itu juga akan membantu melemahkan penyimpangan yang merajalela.
sumber
Set manipulasi logika yang baik di SQL dapat diintegrasikan dengan DDD tidak ada masalah.
Katakan misalnya saya perlu tahu beberapa nilai agregat, jumlah total produk berdasarkan jenis. Mudah dijalankan dalam sql, tetapi lambat jika saya memuat setiap produk ke dalam memori dan menambahkan semuanya.
Saya cukup memperkenalkan objek Domain baru,
dan metode di repositori saya
Tentu, mungkin sekarang saya mengandalkan DB saya memiliki kemampuan tertentu. Tetapi saya masih memiliki pemisahan secara teknis dan selama logikanya sederhana, saya dapat berargumen bahwa itu bukan 'logika bisnis'
sumber
Query
parameter.repository.find(query);
. Saya telah membaca yang sama tetapi denganSpecs. That opens a door to leave
Query` sebagai abstraksi danQueryImpl
atau implementasi spesifik-permintaan ke lapisan infrastruktur.I know some people do that
beberapa orang sangat penting dan kerangka kerjanya. SpringFramework memiliki banyak hal ini :-). Bagaimanapun, Seperti @VoiceOfUnreason telah menyarankan, kunci di sekitar DDD adalah menjaga konsistensi tulisan. Saya tidak yakin tentang pemaksaan desain dengan model domain yang hanya tujuan kueri atau parametrizing queries. Itu bisa didekati dari domain dengan struktur data (pocos, pojos, dtos, pembuat pemetaan baris, apa pun).Salah satu cara yang mungkin untuk menyelesaikan dilema ini adalah dengan memikirkan SQL sebagai bahasa rakitan: Anda jarang, jika sama sekali, kode langsung di dalamnya, tetapi di mana kinerja penting, Anda harus dapat memahami kode yang dihasilkan oleh C Anda. / C ++ / Golang / Rust compiler dan mungkin bahkan menulis snippet kecil di assembly, jika Anda tidak dapat mengubah kode dalam bahasa tingkat tinggi Anda untuk menghasilkan kode mesin yang diinginkan.
Demikian pula, dalam bidang basis data dan SQL, berbagai pustaka SQL (beberapa di antaranya adalah ORM ), misalnya SQLAlchemy dan Django ORM untuk Python, LINQ untuk .NET, memberikan abstraksi tingkat yang lebih tinggi namun menggunakan kode SQL yang dihasilkan di mana memungkinkan untuk mencapai kinerja. Mereka juga menyediakan portabilitas untuk DB yang digunakan, mungkin memiliki kinerja yang berbeda, misalnya pada Postgres dan MySQL, karena beberapa operasi menggunakan beberapa SQL spesifik DB yang lebih optimal.
Dan seperti halnya bahasa tingkat tinggi, sangat penting untuk memahami cara kerja SQL, bahkan jika itu hanya untuk mengatur ulang pertanyaan yang dilakukan dengan pustaka SQL yang disebutkan di atas, untuk dapat mencapai efisiensi yang diinginkan.
PS Saya lebih suka berkomentar tapi saya tidak punya reputasi yang cukup untuk itu.
sumber
Seperti biasa, ini adalah salah satu hal yang tergantung pada sejumlah faktor. Memang benar bahwa ada banyak yang dapat Anda lakukan dengan SQL. Ada juga tantangan dengan menggunakannya dan beberapa keterbatasan praktis dari basis data relasional.
Seperti yang dicatat Jared Goguen dalam komentar, SQL bisa sangat sulit untuk diuji dan diverifikasi. Faktor utama yang menyebabkan hal ini adalah bahwa ia tidak dapat (secara umum) diuraikan menjadi komponen-komponen. Dalam praktiknya, kueri yang kompleks harus dipertimbangkan dalam toto. Faktor rumit lainnya adalah perilaku dan kebenaran SQL sangat tergantung pada struktur dan konten data Anda. Ini berarti bahwa pengujian semua skenario yang mungkin (atau bahkan menentukan apa skenario itu) seringkali tidak layak atau tidak mungkin. Refactoring SQL dan modifikasi struktur database juga bermasalah.
Faktor besar lainnya yang menyebabkan pindah dari SQL adalah database relasional cenderung hanya skala secara vertikal. Sebagai contoh, ketika Anda membangun perhitungan kompleks dalam SQL untuk dijalankan di SQL Server, mereka akan mengeksekusi pada database. Itu berarti semua pekerjaan itu menggunakan sumber daya pada database. Semakin banyak yang Anda lakukan dalam SQL, semakin banyak sumber daya yang dibutuhkan oleh database Anda baik dari segi memori maupun CPU. Seringkali kurang efisien untuk melakukan hal-hal ini pada sistem lain, tetapi tidak ada batasan praktis untuk jumlah mesin tambahan yang dapat Anda tambahkan ke solusi seperti itu. Pendekatan ini lebih murah dan lebih toleran daripada membangun server database monster.
Masalah-masalah ini mungkin atau mungkin tidak berlaku untuk masalah yang dihadapi. Jika Anda dapat memecahkan masalah Anda dengan sumber daya database yang tersedia, mungkin SQL baik untuk ruang masalah Anda. Namun, Anda perlu mempertimbangkan pertumbuhan. Mungkin baik-baik saja hari ini tetapi beberapa tahun ke depan, biaya penambahan sumber daya mungkin menjadi masalah.
sumber
Biarkan saya membersihkan beberapa kesalahpahaman.
DDD bukan sebuah pola. Dan itu tidak benar-benar menentukan pola.
Kata pengantar buku DDD Eric Evan menyatakan:
Jadi, ini adalah cara untuk mendekati pengembangan perangkat lunak dan pemodelan domain, ditambah beberapa kosakata teknis yang mendukung kegiatan tersebut (kosakata yang mencakup berbagai konsep dan pola). Itu juga bukan sesuatu yang sepenuhnya baru.
Hal lain yang perlu diingat adalah bahwa model domain bukan implementasi OO yang dapat ditemukan di sistem Anda - itu hanya satu cara untuk mengekspresikannya, atau untuk mengekspresikan beberapa bagian dari itu. Model domain adalah cara Anda berpikir tentang masalah yang Anda coba selesaikan dengan perangkat lunak. Begitulah cara Anda memahami dan memahami berbagai hal, bagaimana Anda membicarakannya. Itu konseptual . Tapi tidak dalam arti yang kabur. Ini dalam dan halus, dan merupakan hasil kerja keras dan pengumpulan pengetahuan. Lebih lanjut disempurnakan dan kemungkinan berkembang dari waktu ke waktu, dan itu melibatkan pertimbangan implementasi (beberapa di antaranya dapat menghambat model). Itu harus dibagikan oleh semua anggota tim (dan melibatkan ahli domain), dan itu harus mengarahkan bagaimana Anda menerapkan sistem, sehingga sistem mencerminkannya dengan cermat.
Tidak ada yang secara inheren pro atau anti-SQL, meskipun pengembang OO mungkin umumnya lebih baik dalam mengekspresikan model dalam bahasa OO, dan ekspresi banyak konsep domain lebih baik didukung oleh OOP. Tetapi kadang-kadang bagian dari model harus diekspresikan dalam paradigma yang berbeda.
Nah, secara umum ada dua skenario di sini.
Dalam kasus pertama, beberapa aspek dari suatu domain benar-benar membutuhkan kueri yang kompleks, dan mungkin aspek tersebut paling baik diungkapkan dalam paradigma SQL / relasional - jadi gunakan alat yang sesuai untuk pekerjaan itu. Cerminkan aspek-aspek tersebut dalam pemikiran domain Anda dan bahasa yang digunakan dalam mengkomunikasikan konsep. Jika domainnya kompleks, mungkin ini adalah bagian dari subdomain dengan konteks terikatnya sendiri.
Skenario lain adalah bahwa kebutuhan yang dirasakan untuk mengekspresikan sesuatu dalam SQL adalah hasil dari pemikiran yang terbatas. Jika seseorang atau tim selalu berorientasi pada basis data dalam pemikiran mereka, mungkin sulit bagi mereka, hanya karena inersia, untuk melihat cara berbeda dalam mendekati sesuatu. Ini menjadi masalah ketika cara lama gagal memenuhi kebutuhan baru, dan membutuhkan beberapa pemikiran di luar kotak. DDD, sebagai pendekatan untuk desain, sebagian tentang cara untuk menemukan jalan keluar dari kotak itu dengan mengumpulkan dan menyaring pengetahuan tentang domain. Tetapi semua orang tampaknya mengabaikan bagian buku itu, dan berfokus pada beberapa kosa kata dan pola teknis yang tercantum.
sumber
Sekuel menjadi populer ketika memori mahal, karena model data relasional memberikan kemungkinan untuk menormalkan data Anda dan secara efektif menyimpannya dalam sistem file.
Sekarang memori relatif murah, sehingga kita dapat melewati normalisasi dan menyimpan dalam format yang kita gunakan atau bahkan menduplikasi banyak data yang sama demi kecepatan.
Pertimbangkan database sebagai perangkat IO sederhana , yang bertanggung jawab untuk menyimpan data dalam sistem file - ya saya tahu sulit membayangkannya, karena kami menulis banyak aplikasi dengan logika bisnis penting yang ditulis ke dalam query SQL - tetapi coba bayangkan SQL Server itu hanyalah printer lain.
Apakah Anda menanamkan generator PDF ke driver printer atau menambahkan pemicu yang akan mencetak halaman log untuk setiap pesanan penjualan yang dicetak dari printer kami?
Saya berasumsi jawabannya tidak, karena kami tidak ingin aplikasi kami digabungkan ke jenis perangkat tertentu (bahkan tidak berbicara tentang efisiensi ide semacam itu)
Dalam 70-an -90-an database SQL efisien, sekarang? - Tidak yakin, dalam beberapa skenario, kueri data asinkron akan mengembalikan data yang diperlukan lebih cepat dari beberapa gabungan dalam kueri SQL.
SQL tidak dirancang untuk kueri yang rumit, ia dirancang untuk menyimpan data dengan cara yang efisien dan kemudian menyediakan antarmuka / bahasa untuk permintaan data yang disimpan.
Saya akan mengatakan membangun aplikasi Anda di sekitar model data relasional dengan pertanyaan rumit adalah penyalahgunaan mesin basis data. Tentu saja penyedia mesin basis data senang ketika Anda menggabungkan bisnis Anda dengan produk mereka - mereka akan sangat senang untuk memberikan lebih banyak fitur yang membuat ikatan ini semakin kuat.
sumber