Dokumen ini merinci foodtruacker, sebuah proyek yang mengimplementasikan Domain-Driven Design (DDD), CQRS, dan Event Sourcing. Ia menggunakan ASP.NET Core dan berfokus pada peningkatan pemeliharaan dalam domain bisnis yang kompleks. Proyek ini menggunakan kasus bisnis fiksi yang disederhanakan untuk tujuan ilustrasi. Penjelasan rinci ini mencakup motivasi, fitur, detail implementasi, dan teknologi yang relevan.
foodtruacker - Implementasi DDD, CQRS dan Sumber Acara
Proyek berbasis peristiwa ini menggunakan prinsip, kerangka kerja, dan arsitektur — semuanya berpusat pada gagasan untuk meningkatkan kemudahan pemeliharaan ketika berhadapan dengan sistem yang mencerminkan domain bisnis yang kompleks. API Web aplikasi dibangun berdasarkan kerangka kerja ASP.NET Core Microsoft dan mengimplementasikan Desain Berbasis Domain, serta pola CQRS dan Sumber Peristiwa. Sebuah kasus bisnis fiktif meletakkan dasar dari proyek ini dan merupakan hasil dari sebuah lokakarya yang penuh badai.
Harap diperhatikan: Domain bisnis fiktif yang diperkenalkan ke proyek ini sangat disederhanakan dan hanya boleh dilihat sebagai penyedia kasus penggunaan yang relevan.
Motivasi
Karena tidak selalu yang terbaik menggunakan operasi CRUD dan objek POCO dalam proyek dengan domain bisnis yang agak kompleks, saya memutuskan untuk membuat proyek ini sebagai implementasi praktis dari penelitian saya tentang — dan minat terhadap — Desain Berbasis Domain (DDD) pendekatan pengembangan perangkat lunak.
Karena kasus bisnis fiktif yang diperkenalkan pada proyek ini sangat didorong oleh peristiwa, saya memutuskan untuk juga menerapkan pola CQRS dan Sumber Acara. Keduanya menarik perhatian saya saat melakukan penelitian untuk proyek ini dan berjalan baik bersama DDD.
Fitur
Ringkasan
Proyek ini terdiri dari satu aplikasi Web API yang dapat dieksekusi dan beberapa komponen fungsional, masing-masing disediakan melalui perpustakaan kelas. Kode ini diatur berdasarkan namespace. Dalam aplikasi ASP.NET Core yang dibuat di Visual Studio, namespace, secara default, secara otomatis dibuat dari struktur folder proyek. Lihat diagram di bawah untuk gambaran umum tentang struktur folder (dan namespace) proyek ini:
Perkenalan
Peristiwa Penyerbuan
Format lokakarya yang fleksibel untuk eksplorasi kolaboratif domain bisnis yang kompleks, ditemukan oleh Alberto Brandolini. Ini adalah metodologi yang sangat ringan untuk meningkatkan, membayangkan, mengeksplorasi, dan merancang alur dan proses bisnis dengan cepat dalam organisasi Anda.
Lokakarya ini terdiri dari sekelompok orang dengan keahlian berbeda menggunakan catatan tempel berwarna untuk secara kolaboratif menyusun tata letak proses bisnis yang relevan. Lokakarya EventStorming wajib dihadiri oleh orang yang tepat dan memiliki luas permukaan yang cukup untuk meletakkan catatan tempel. Orang yang diperlukan biasanya mencakup mereka yang mengetahui pertanyaan yang ingin diajukan (biasanya pengembang) dan mereka yang mengetahui jawabannya (pakar domain, pemilik produk).
Tujuan dari lokakarya ini adalah agar para peserta saling belajar satu sama lain, mengungkapkan dan menyangkal kesalahpahaman dan, misalnya dalam proyek GitHub ini, melakukan landasan untuk pengembangan solusi perangkat lunak berbasis peristiwa yang mencerminkan domain bisnis yang berkorelasi.
Desain Berbasis Domain (DDD)
Suatu pendekatan pengembangan perangkat lunak yang memusatkan pengembangan pada pemrograman model domain yang memiliki pemahaman yang kaya tentang proses dan aturan domain bisnis yang berkorelasi. Istilah "Desain Berbasis Domain" diciptakan oleh Eric Evans dalam bukunya dengan judul yang sama.
DDD bertujuan untuk memudahkan pembuatan aplikasi yang kompleks dan berfokus pada tiga prinsip inti:
Buku Eric Evans menjelaskan beberapa istilah umum untuk Desain Berbasis Domain:
Model Domain
Sebuah sistem abstraksi yang menggambarkan proses dan kebijakan domain bisnis dan digunakan untuk menangani tugas-tugas yang diperlukan terkait dengan domain tersebut.
Bahasa yang Ada di Mana-Mana
Kata-kata dan pernyataan untuk elemen tertentu dari domain bisnis. Untuk menghindari kesalahpahaman, semua anggota tim harus mengadopsi istilah tertentu, biasanya yang digunakan oleh pakar domain.
Konteks yang Dibatasi
Batas konseptual di mana model domain tertentu didefinisikan dan diterapkan. Ini biasanya mewakili subsistem atau bidang pekerjaan. Ini terutama merupakan batasan linguistik, dengan setiap konteks yang dibatasi memiliki Bahasa yang Ada di Mana-Mana (Ubiquitous Language).
Misalnya: Manajemen Pelanggan dimana pengguna disebut "pelanggan".
Buku Eric Evans lebih jauh membedakan bagian-bagian tertentu dari model domain. Untuk beberapa nama:
Kesatuan
Suatu objek yang ditentukan oleh identitasnya, bukan atributnya.
Misalnya: Seseorang akan selalu menjadi orang yang sama, tidak peduli pilihan jaket, warna rambut, atau bahasa yang digunakan pada saat tertentu.
Objek Nilai
Suatu objek yang ditentukan semata-mata oleh nilai atributnya. Objek Nilai tidak dapat diubah dan tidak memiliki identitas unik. Objek Nilai dapat digantikan oleh Objek Nilai lain dengan atribut yang sama.
Misalnya: Saat memusatkan perhatian pada seseorang, kacamata hitam yang rusak dapat dengan mudah diganti dengan kacamata hitam baru yang terlihat sama.
Agregat
Sekelompok satu atau lebih Entitas dan Objek Nilai opsional, disatukan menjadi satu unit transaksional. Satu Entitas akan membentuk basis Agregat dan dengan demikian dinyatakan sebagai akar Agregat. Semua properti Entitas dan Objek Nilai yang berkolaborasi hanya dapat diakses melalui Entitas dasar tunggal ini. Suatu Agregat harus selalu berada dalam kondisi yang konsisten. Dalam pemrograman berorientasi objek, hal ini biasanya dilakukan dengan menggunakan setter pribadi dan pengambil yang dilindungi.
Misalnya: Dalam konteks penjualan mobil, satu mobil (Entitas) ditentukan berdasarkan nomor identifikasi kendaraannya. Mobil ini mungkin memiliki empat roda (Benda Nilai), yang mungkin perlu diganti setelah waktu tertentu.
Acara Domain
Objek yang dibuat sebagai hasil aktivitas dalam Model Domain. Digunakan untuk menampung dan meneruskan informasi terkait kegiatan ini. Peristiwa Domain biasanya dibuat untuk aktivitas yang dianggap relevan oleh pakar domain.
Arsitektur heksagonal (Port & Adaptor)
Pola arsitektur yang digunakan dalam desain perangkat lunak, diusulkan oleh Alistair Cockburn pada tahun 2005. Pola ini bertujuan untuk mencapai tingkat pemeliharaan yang tinggi dan mendeskripsikan aplikasi dalam tiga lapisan. Setiap lapisan berkomunikasi dengan lapisan yang berdekatan menggunakan antarmuka (port) dan implementasi (adaptor):
Aturan utama dalam pola arsitektur ini adalah bahwa ketergantungan hanya dapat mengarah ke dalam. Tidak ada orang di lingkaran dalam yang bisa mengetahui apa pun tentang sesuatu di lingkaran luar. Setiap dependensi yang ingin mengarah ke luar, misalnya memanggil database dari Lapisan Aplikasi, perlu dipakai melalui inversi Kontrol (IoC) atau Injeksi Ketergantungan (DI).
CQRS menggunakan MediatR (kerangka pengiriman pesan bawaan)
CQRS adalah singkatan dari Command/Query Responsibility Segregation dan pertama kali dijelaskan oleh Greg Young pada tahun 2010. CQRS didasarkan pada prinsip Command Query Separation (CQS) dan memungkinkan pemisahan operasi baca dan tulis. CQS menyatakan:
Peningkatan dari CQRS dibandingkan CQS adalah bahwa perintah dan kueri tersebut diperlakukan sebagai model, bukan metode. Model-model ini dapat dikirim sebagai objek di satu titik, untuk kemudian ditangani oleh masing-masing penangan yang diperlukan di titik lain dalam sistem, masing-masing mengembalikan model responsnya untuk pemisahan yang jelas dari setiap tindakan.
Pola mediator memungkinkan penerapan Perintah/Kueri dan Penangan digabungkan secara longgar, memanfaatkan objek mediator. Objek tidak lagi berkomunikasi secara langsung satu sama lain, melainkan berkomunikasi melalui mediator.
Kerangka kerja MediatR adalah implementasi pola mediator open source, yang dibuat oleh Jimmy Bogard. Ini akan digunakan dalam proyek ini untuk komunikasi antara Framework Layer dan Application Layer. Ini juga akan digunakan untuk memproyeksikan data dari database Command ke database Query.
Sumber Acara
Pola desain arsitektur untuk menyimpan setiap perubahan status aplikasi, bukan hanya menyimpan status data saat ini dalam domain. Pola ini diperkenalkan oleh Greg Young dan sejak itu banyak diadopsi.
Pola tersebut bermaksud untuk menangkap setiap perubahan pada keadaan aplikasi sebagai objek peristiwa. Objek peristiwa ini kemudian disimpan, dalam urutan kejadian, dengan cara tambahan saja. Hal ini tidak hanya memungkinkan terciptanya kembali keadaan suatu objek saat ini atas rangkaian peristiwa yang telah terjadi sejauh ini, namun pada akhirnya memungkinkan untuk kembali ke masa lalu dan menciptakan kembali keadaan objek tersebut pada waktu tertentu.
Rekening bank dapat menjadi contoh yang baik dari prinsip Event Sourcing. Setiap kali uang ditarik atau disetorkan, alih-alih hanya memperbarui saldo saat ini, jumlah perubahannya dicatat. Saldo saat ini kemudian dihitung dengan menelusuri urutan kejadian, dengan informasi terkait berapa banyak uang yang ditarik atau disetorkan setiap kali.
Sumber Peristiwa cocok dengan Desain Berbasis Domain, karena sangat cocok untuk menyimpan Peristiwa Domain, yang dipicu oleh Model Domain dengan setiap permintaan perubahan.
Sumber Acara juga mendapat banyak manfaat dari CQRS. Daripada harus membuat Kueri terhadap database Sumber Peristiwa, yang harus menelusuri semua peristiwa yang direkam terkait dengan objek yang diminta untuk membuat ulang keadaan saat ini, Kueri ini dapat dibuat terhadap Basis Data Kueri khusus. Database Kueri ini diperbarui oleh event handlernya sendiri, mendengarkan event yang sama dikirim segera setelah ditambahkan ke Event Sourcing Database. Proses pembaruan ini disebut Proyeksi.
Pemisahan database ini juga memberikan potensi besar dalam skalabilitas dan optimalisasi kinerja. Beberapa contoh database Kueri dapat dibuat dan disinkronkan hanya dengan meminta pengendali kejadian mendengarkan kejadian yang dikirim dari Klien Database Sumber Peristiwa tepat setelah terjadi perubahan yang relevan pada status aplikasi. Pilihan tipe database serta tingkat denormalisasi data, yang dioptimalkan per kueri, dapat meningkatkan kinerja secara signifikan.
Pembaruan model baca yang terus-menerus ini dapat terjadi secara sinkron atau asinkron. Hal terakhir ini mengorbankan konsistensi pada akhirnya, karena model baca tidak sinkron dengan model tulis dalam selisih waktu yang sangat kecil (biasanya milidetik).
Kernel Bersama
Pustaka umum untuk Lapisan Domain, yang berisi kelas dasar khusus Desain Berbasis Domain, Entitas Domain, Objek Nilai, dll. yang umum digunakan di seluruh Konteks Terikat.
Memulai
Untuk menjalankan proyek ini sebagaimana adanya, silakan ikuti langkah-langkah berikut:
Prasyarat
Pengaturan
Luncurkan https://localhost:5001/swagger/index.html di browser Anda untuk melihat dokumentasi Swagger API Anda.
Gunakan Swagger, Postman atau aplikasi lainnya untuk mengirim permintaan POST ke https://localhost:5001/api/Administration/Register untuk mendaftarkan akun admin awal Anda. Kirimkan objek berikut:
Lihat aplikasi konsol atau keluaran mana pun yang dikonfigurasi ulang untuk log aplikasi. Setelah pendaftaran pengguna berhasil, seharusnya ada tautan verifikasi email - yang disediakan oleh Layanan Email - yang ditulis ke dalam log. Salin dan tempel url ini ke browser Anda dan tekan enter untuk menyelesaikan pendaftaran. Jangan ragu untuk mengubah atau mengembangkan penerapan layanan email yang tidak tepat ini ;-)
Anda sudah siap. Masuk selanjutnya.
Luncurkan http://localhost:2113/ di browser Anda untuk melihat GUI EventStoreDB. Buka tab "Stream Browser" untuk melihat semua acara yang disimpan.
Tes dapat dijalankan dengan menjalankan:
Teknologi
Proyek ini menggunakan paket Teknologi/NuGet berikut:
Sumber Daya / Bacaan yang Direkomendasikan
Alberto Brandolini:
https://www.eventstorming.com
Vaughn Vernon:
https://dddcommunity.org/wp-content/uploads/files/pdfarticles/Vernon2011_1.pdf
https://dddcommunity.org/wp-content/uploads/files/pdfarticles/Vernon2011_2.pdf
https://dddcommunity.org/wp-content/uploads/files/pdfarticles/Vernon2011_3.pdf
Alistair Cockburn:
https://web.archive.org/web/20180822100852/http://alistair.cockburn.us/Hexagonal+architecture
Robert C. Martin (Paman Bob):
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
Cesar de la Torre, Bill Wagner, Mike Rousos:
https://docs.microsoft.com/en-us/dotnet/architecture/microservices/
Greg Muda
https://cqrs.files.wordpress.com/2010/11/cqrs_documents.pdf
https://cqrs.wordpress.com/documents/building-event-storage/
https://msdn.microsoft.com/en-us/library/jj591559.aspx
Martin Fowler:
https://www.martinfowler.com/bliki/CQRS.html
Jimmy Bogard:
https://github.com/jbogard/MediatR
https://www.youtube.com/watch?v=SUiWfhAhgQw
Desain Berbasis Domain:
https://dddcommunity.org
https://thedomaindrivendesign.io
https://dotnetcodr.com/2013/09/12/a-model-net-web-service-based-on-domain-driven-design-part-1-introduction/
https://dotnetcodr.com/2015/10/22/domain-driven-design-with-web-api-extensions-part-1-notifications/
Arsitektur Heksagonal:
https://fideloper.com/hexagonal-architecture
https://herbertograca.com/2017/09/14/ports-adapters-architecture/
Kredit
http://www.andreavallotti.tech/en/2018/01/event-sourcing-and-cqrs-in-c/
https://www.Exceptionnotfound.net/real-world-cqrs-es-with-asp-net-and-redis-part-1-overview/
https://buildplease.com/pages/fpc-1/
https://dotnetcoretutorials.com/2019/04/30/the-mediator-pattern-in-net-core-part-1-whats-a-mediator/
https://itnext.io/why-and-how-i-implemented-cqrs-and-mediator-patterns-in-a-microservice-b07034592b6d