Bagikan melalui


Mendesain layanan mikro berorientasi DDD

Petunjuk / Saran

Konten ini adalah kutipan dari eBook, Arsitektur Layanan Mikro .NET untuk Aplikasi .NET Kontainer, tersedia di .NET Docs atau sebagai PDF gratis yang dapat diunduh yang dapat dibaca secara offline.

Arsitektur Layanan Mikro .NET untuk Aplikasi .NET Dalam Kontainer: gambar kecil sampul eBook.

Desain berbasis domain (DDD) menganjurkan pemodelan berdasarkan realitas bisnis yang relevan dengan kasus penggunaan Anda. Dalam konteks membangun aplikasi, DDD berbicara tentang masalah sebagai domain. Ini menjelaskan area masalah independen sebagai Konteks Terikat (setiap Konteks Terikat berkorelasi dengan layanan mikro), dan menekankan bahasa umum untuk berbicara tentang masalah ini. Ini juga menyarankan banyak konsep dan pola teknis, seperti entitas domain dengan model yang kaya (tidak ada model domain anemik), objek nilai, agregat, dan aturan agregat akar (atau entitas akar) untuk mendukung implementasi internal. Bagian ini memperkenalkan desain dan implementasi pola internal tersebut.

Terkadang aturan dan pola teknis DDD ini dianggap sebagai hambatan yang memiliki kurva pembelajaran yang curam untuk menerapkan pendekatan DDD. Tetapi bagian pentingnya bukan pola itu sendiri, tetapi mengatur kode sehingga selaras dengan masalah bisnis, dan menggunakan istilah bisnis yang sama (bahasa di mana-mana). Selain itu, pendekatan DDD harus diterapkan hanya jika Anda menerapkan layanan mikro yang kompleks dengan aturan bisnis yang signifikan. Tanggung jawab yang lebih sederhana, seperti layanan CRUD, dapat dikelola dengan pendekatan yang lebih sederhana.

Tempat menggambar batasan adalah tugas utama saat merancang dan menentukan layanan mikro. Pola DDD membantu Anda memahami kompleksitas di domain. Untuk model domain untuk setiap Konteks Terikat, Anda mengidentifikasi dan menentukan entitas, objek nilai, dan agregat yang memodelkan domain Anda. Anda membangun dan memperbaiki model domain yang terkandung dalam batas yang menentukan konteks Anda. Dan itu eksplisit dalam bentuk layanan mikro. Komponen dalam batas-batas tersebut akhirnya menjadi layanan mikro Anda, meskipun dalam beberapa kasus SM atau layanan mikro bisnis dapat terdiri dari beberapa layanan fisik. DDD adalah tentang batasan dan begitu juga layanan mikro.

Jaga batas konteks layanan mikro yang relatif kecil

Menentukan penempatan batas antara Konteks Terikat melibatkan penyeimbangan dua tujuan yang saling bersaing. Pertama, Anda awalnya ingin membuat layanan mikro sekecil mungkin, meskipun itu seharusnya bukan pendorong utama; Anda harus membuat batas di sekitar hal-hal yang membutuhkan kohesi. Kedua, Anda ingin menghindari komunikasi cerewet antara layanan mikro. Tujuan ini dapat bertentangan satu dengan yang lain. Anda harus menyeimbangkannya dengan menguraikan sistem menjadi layanan mikro kecil sebanyak yang Anda bisa sampai Anda melihat batas komunikasi tumbuh dengan cepat dengan setiap upaya tambahan untuk memisahkan Konteks Terikat baru. Kohesi adalah kunci dalam satu konteks terikat.

Ini mirip dengan bau kode Intim yang Tidak Pantas saat mengimplementasikan kelas. Jika dua layanan mikro perlu banyak berkolaborasi satu sama lain, mereka mungkin harus menjadi layanan mikro yang sama.

Cara lain untuk melihat aspek ini adalah otonomi. Jika layanan mikro harus mengandalkan layanan lain untuk secara langsung melayani permintaan, itu tidak benar-benar otonom.

Lapisan dalam layanan mikro DDD

Sebagian besar aplikasi perusahaan dengan kompleksitas bisnis dan teknis yang signifikan didefinisikan oleh beberapa lapisan. Lapisan adalah artefak logis, dan tidak terkait dengan penyebaran layanan. Mereka ada untuk membantu pengembang mengelola kompleksitas dalam kode. Lapisan yang berbeda (seperti lapisan model domain versus lapisan presentasi, dll.) mungkin memiliki jenis yang berbeda, yang mengamanatkan terjemahan di antara jenis tersebut.

Misalnya, entitas dapat dimuat dari database. Kemudian bagian dari informasi tersebut, atau agregasi informasi termasuk data tambahan dari entitas lain, dapat dikirim ke UI klien melalui REST Web API. Intinya di sini adalah bahwa entitas domain terkandung dalam lapisan model domain dan tidak boleh disebarluaskan ke area lain yang bukan miliknya, seperti lapisan presentasi.

Selain itu, Anda harus memiliki entitas yang selalu valid (lihat validasi Desain di bagian lapisan model domain ) yang dikontrol oleh akar agregat (entitas akar). Oleh karena itu, entitas tidak boleh terikat pada tampilan klien, karena pada tingkat UI beberapa data mungkin masih belum divalidasi. Inilah alasan mengapa ViewModel ada. ViewModel adalah model data khusus untuk kebutuhan lapisan presentasi. Entitas domain tidak termasuk langsung ke ViewModel. Sebagai gantinya, Anda perlu menerjemahkan antara ViewModels dan entitas domain dan sebaliknya.

Saat mengatasi kompleksitas, penting untuk memiliki model domain yang dikontrol oleh akar agregat yang memastikan bahwa semua invarian dan aturan yang terkait dengan grup entitas tersebut (agregat) dilakukan melalui satu titik masuk atau gerbang, akar agregat.

Gambar 7-5 menunjukkan bagaimana desain berlapis diimplementasikan dalam aplikasi eShopOnContainers.

Diagram memperlihatkan lapisan dalam layanan mikro desain berbasis domain.

Gambar 7-5. Tingkatan DDD dalam layanan mikro pemesanan di eShopOnContainers

Tiga lapisan dalam layanan mikro DDD seperti Pemesanan. Setiap lapisan adalah proyek VS: Lapisan aplikasi adalah Ordering.API, Lapisan domain adalah Ordering.Domain dan lapisan Infrastrukturnya adalah Ordering.Infrastructure. Anda ingin merancang sistem sehingga setiap lapisan hanya berkomunikasi dengan lapisan tertentu lainnya. Pendekatan tersebut mungkin lebih mudah diterapkan jika lapisan diimplementasikan sebagai pustaka kelas yang berbeda, karena Anda dapat dengan jelas mengidentifikasi dependensi apa yang diatur di antara pustaka. Misalnya, lapisan model domain tidak boleh mengambil dependensi pada lapisan lain (kelas model domain harus Objek Kelas Lama Biasa, atau POCO, kelas). Seperti yang ditunjukkan pada Gambar 7-6, pustaka lapisan Ordering.Domain hanya memiliki dependensi pada pustaka .NET atau paket NuGet, tetapi tidak pada pustaka kustom lainnya, seperti pustaka data atau pustaka persistensi.

Cuplikan layar ketergantungan di Ordering.Domain.

Gambar 7-6. Lapisan yang diimplementasikan sebagai pustaka memungkinkan kontrol dependensi antar lapisan yang lebih baik

Lapisan Domain Model

Buku luar biasa Eric Evans Domain Driven Design mengatakan hal berikut tentang lapisan model domain dan lapisan aplikasi.

Lapisan Model Domain: Bertanggung jawab untuk mewakili konsep bisnis, informasi tentang situasi bisnis, dan aturan bisnis. Status yang mencerminkan situasi bisnis dikendalikan dan digunakan di sini, meskipun detail teknis penyimpanannya didelegasikan ke infrastruktur. Lapisan ini adalah inti dari perangkat lunak bisnis.

Lapisan model domain adalah tempat bisnis diekspresikan. Saat Anda menerapkan lapisan model domain layanan mikro di .NET, lapisan tersebut dikodekan sebagai pustaka kelas dengan entitas domain yang menangkap data ditambah perilaku (metode dengan logika).

Mengikuti prinsip Persistence Ignorance dan Infrastructure Ignorance , lapisan ini harus sepenuhnya mengabaikan detail persistensi data. Tugas persistensi ini harus dilakukan oleh lapisan infrastruktur. Oleh karena itu, lapisan ini tidak boleh mengambil dependensi langsung pada infrastruktur, yang berarti bahwa aturan penting adalah bahwa kelas entitas model domain Anda harus POCO.

Entitas domain tidak boleh memiliki dependensi langsung (seperti berasal dari kelas dasar) pada kerangka kerja infrastruktur akses data apa pun seperti Entity Framework atau NHibernate. Idealnya, entitas domain Anda tidak boleh berasal dari atau menerapkan jenis apa pun yang ditentukan dalam kerangka kerja infrastruktur apa pun.

Sebagian besar kerangka kerja ORM modern seperti Entity Framework Core memungkinkan pendekatan ini, sehingga kelas model domain Anda tidak digabungkan dengan infrastruktur. Namun, memiliki entitas POCO tidak selalu dimungkinkan saat menggunakan database dan kerangka kerja NoSQL tertentu, seperti Actor dan Reliable Collections di Azure Service Fabric.

Bahkan ketika penting untuk mengikuti prinsip Ketidaktahuan Persistensi dalam model Domain Anda, Anda tidak boleh mengabaikan kendala persistensi. Masih penting untuk memahami model data fisik dan cara memetakan ke model objek entitas Anda. Jika tidak, Anda dapat membuat desain yang tidak mungkin.

Selain itu, aspek ini tidak berarti Anda dapat mengambil model yang dirancang untuk database relasional dan langsung memindahkannya ke NoSQL atau database berorientasi dokumen. Dalam beberapa model entitas, model mungkin cocok, tetapi biasanya tidak. Masih ada kendala yang harus dipatuhi model entitas Anda, baik berdasarkan teknologi penyimpanan maupun teknologi ORM.

Lapisan aplikasi

Beralih ke lapisan aplikasi, kita dapat kembali mengutip buku Eric Evans Domain Driven Design:

Lapisan Aplikasi: Mendefinisikan pekerjaan yang seharusnya dilakukan perangkat lunak dan mengarahkan objek domain ekspresif untuk mengatasi masalah. Tugas yang bertanggung jawab untuk lapisan ini bermakna bagi bisnis atau diperlukan untuk interaksi dengan lapisan aplikasi sistem lain. Lapisan ini tetap tipis. Ini tidak berisi aturan atau pengetahuan bisnis, tetapi hanya mengoordinasikan tugas dan mendelegasikan pekerjaan untuk kolaborasi objek domain di lapisan berikutnya di bawah. Ini tidak memiliki status yang mencerminkan situasi bisnis, tetapi dapat memiliki status yang mencerminkan kemajuan tugas untuk pengguna atau program.

Lapisan aplikasi layanan mikro di .NET biasanya dikodekan sebagai proyek ASP.NET Core Web API. Proyek ini mengimplementasikan interaksi layanan mikro, akses jaringan jarak jauh, dan API Web eksternal yang digunakan dari UI atau aplikasi klien. Ini termasuk kueri jika menggunakan pendekatan CQRS, perintah yang diterima oleh layanan mikro, dan bahkan komunikasi berbasis peristiwa antara layanan mikro (peristiwa integrasi). API Web ASP.NET Core yang mewakili lapisan aplikasi tidak boleh berisi aturan bisnis atau pengetahuan domain (terutama aturan domain untuk transaksi atau pembaruan); ini harus dimiliki oleh pustaka kelas model domain. Lapisan aplikasi hanya boleh mengoordinasikan tugas dan tidak boleh menahan atau menentukan status domain apa pun (model domain). Ini mendelegasikan eksekusi aturan bisnis ke kelas model domain itu sendiri (agregat akar dan entitas domain), yang pada akhirnya akan memperbarui data dalam entitas domain tersebut.

Pada dasarnya, logika aplikasi adalah tempat Anda menerapkan semua kasus penggunaan yang bergantung pada antarmuka depan tertentu. Misalnya, implementasi yang terkait dengan layanan API Web.

Tujuannya adalah bahwa logika domain dalam lapisan model domain, invariannya, model data, dan aturan bisnis terkait harus sepenuhnya independen dari lapisan presentasi dan aplikasi. Yang terpenting, lapisan model domain tidak boleh secara langsung bergantung pada kerangka kerja infrastruktur apa pun.

Lapisan infrastruktur

Lapisan infrastruktur adalah bagaimana data yang awalnya disimpan di entitas domain (dalam memori) dipertahankan dalam database atau penyimpanan persisten lainnya. Contohnya adalah menggunakan kode Entity Framework Core untuk mengimplementasikan kelas pola Repositori yang menggunakan DBContext untuk mempertahankan data dalam database relasional.

Sesuai dengan prinsip Persistence Ignorance dan Infrastructure Ignorance yang disebutkan sebelumnya, lapisan infrastruktur tidak boleh "mencemari" lapisan model domain. Anda harus menjaga kelas entitas model domain tetap agnostik terhadap infrastruktur yang Anda gunakan untuk menyimpan data (EF atau kerangka kerja lainnya) dengan tidak mengambil ketergantungan kuat pada kerangka kerja. Pustaka kelas lapisan model domain Anda seharusnya hanya memiliki kode domain Anda, hanya kelas entitas POCO yang mengimplementasikan inti perangkat lunak Anda dan sepenuhnya dipisahkan dari teknologi infrastruktur.

Dengan demikian, lapisan atau pustaka dan proyek kelas Anda pada akhirnya harus bergantung pada lapisan model domain Anda (pustaka), bukan sebaliknya, seperti yang ditunjukkan pada Gambar 7-7.

Diagram memperlihatkan dependensi yang ada di antara lapisan layanan DDD.

Gambar 7-7. Dependensi antara lapisan dalam DDD

Dependensi dalam Layanan DDD, lapisan Aplikasi tergantung pada Domain dan Infrastruktur, dan Infrastruktur tergantung pada Domain, tetapi Domain tidak bergantung pada lapisan apa pun. Desain lapisan ini harus independen untuk setiap layanan mikro. Seperti disebutkan sebelumnya, Anda dapat menerapkan layanan mikro paling kompleks mengikuti pola DDD, sambil menerapkan layanan mikro berbasis data yang lebih sederhana (CRUD sederhana dalam satu lapisan) dengan cara yang lebih sederhana.

Sumber daya tambahan