Menggunakan DDD taktis untuk merancang layanan mikro

Azure Migrate

Selama fase strategis desain berbasis domain (DDD), Anda memetakan domain bisnis dan menentukan konteks terikat untuk model domain Anda. DDD taktis adalah ketika Anda menentukan model domain Anda dengan lebih presisi Pola taktis diterapkan dalam satu konteks terbatas. Dalam arsitektur layanan mikro, kami sangat tertarik pada entitas dan pola agregat. Menerapkan pola-pola ini akan membantu kami mengidentifikasi batas-batas alami untuk layanan dalam aplikasi kami (lihat artikel berikutnya dalam seri ini). Sebagai prinsip umum, layanan mikro tidak boleh lebih kecil dari agregat dan tidak lebih besar dari konteks yang terikat. Pertama, kami akan meninjau pola taktis. Kemudian kami akan menerapkannya ke konteks pengiriman yang dibatasi dalam aplikasi Drone Delivery.

Gambaran umum tentang pola taktis

Bagian ini memberikan ringkasan singkat tentang pola DDD taktis, jadi jika Anda sudah terbiasa dengan DDD, Anda mungkin dapat melewati bagian ini. Pola-pola tersebut dijelaskan secara lebih rinci dalam bab 5 - 6 dari buku Eric Evans, dan dalam Menerapkan Domain-Driven Design oleh Vaughn Vernon.

Diagram pola taktis dalam desain berbasis domain

Entitas. Entitas adalah objek dengan identitas unik yang bertahan dari waktu ke waktu. Misalnya, dalam aplikasi perbankan, pelanggan dan akun akan menjadi entitas.

  • Entitas memiliki pengidentifikasi unik dalam sistem, yang dapat digunakan untuk mencari atau mengambil entitas. Itu tidak berarti pengidentifikasi selalu diekspos langsung ke pengguna. Ini bisa menjadi GUID atau kunci utama dalam database.
  • Identitas dapat mencakup beberapa konteks terbatas, dan dapat bertahan di luar masa aplikasi. Misalnya, nomor rekening bank atau ID yang dikeluarkan pemerintah tidak terkait dengan masa pakai aplikasi tertentu.
  • Atribut entitas dapat berubah dari waktu ke waktu. Misalnya, nama atau alamat seseorang mungkin berubah, tetapi mereka masih orang yang sama.
  • Entitas dapat menyimpan referensi ke entitas lain.

Objek nilai. Objek nilai tidak memiliki identitas. Ini hanya ditentukan oleh nilai-nilai atributnya. Objek nilai juga tidak berubah. Untuk memperbarui objek nilai, Anda selalu membuat instans baru untuk menggantikan yang lama. Objek nilai dapat memiliki metode yang merangkum logika domain, tetapi metode tersebut seharusnya tidak memiliki efek samping pada keadaan objek. Contoh umum dari nilai objek termasuk warna, tanggal dan waktu, dan nilai mata uang.

Mengagregasi. Agregat mendefinisikan batas konsistensi di sekitar satu atau lebih entitas. Tepat satu entitas dalam agregat adalah akar. Pencarian dilakukan menggunakan pengidentifikasi entitas root. Setiap entitas lain dalam agregat adalah turunan dari akar, dan dirujuk dengan mengikuti pointer dari akar.

Tujuan agregat adalah untuk memodelkan invarian transaksional. Hal-hal di dunia nyata memiliki jaringan hubungan yang kompleks. Pelanggan membuat pesanan, pesanan berisi produk, produk memiliki pemasok, dan sebagainya. Jika aplikasi memodifikasi beberapa objek terkait, bagaimana cara menjamin konsistensi? Bagaimana kita melacak invarian dan menegakkannya?

Aplikasi tradisional sering menggunakan transaksi database untuk menegakkan konsistensi. Namun, dalam aplikasi terdistribusi, itu seringkali tidak layak. Satu transaksi bisnis dapat menjangkau beberapa penyimpanan data, atau mungkin berjalan lama, atau mungkin melibatkan layanan pihak ketiga. Pada akhirnya terserah pada aplikasi, bukan lapisan data, untuk menegakkan invarian yang diperlukan untuk domain. Itulah yang agregat maksudkan untuk model.

Catatan

Agregat mungkin terdiri dari satu entitas, tanpa entitas turunan. Apa yang membuatnya agregat adalah batas transaksional.

Layanan domain dan aplikasi. Dalam terminologi DDD, layanan adalah objek yang mengimplementasikan beberapa logika tanpa memegang keadaan apa pun. Evans membedakan antara layanan domain, yang merangkum logika domain, dan layanan aplikasi, yang menyediakan fungsionalitas teknis, seperti autentikasi pengguna atau pengiriman pesan SMS. Layanan domain sering digunakan untuk memodelkan perilaku yang mencakup beberapa entitas.

Catatan

Istilah layanan kelebihan beban dalam pengembangan perangkat lunak. Definisi di sini tidak terkait langsung dengan layanan mikro.

Peristiwa domain. Peristiwa domain dapat digunakan untuk memberi tahu bagian lain dari sistem ketika sesuatu terjadi. Seperti namanya, peristiwa domain berarti sebuah kejadian di dalam domain tersebut. Misalnya, "rekaman dimasukkan ke dalam tabel" bukanlah peristiwa domain. "Pengiriman dibatalkan" adalah acara domain. Peristiwa domain sangat relevan dalam arsitektur layanan mikro. Karena layanan mikro didistribusikan dan tidak berbagi penyimpanan data, peristiwa domain menyediakan cara bagi layanan mikro untuk berkoordinasi satu sama lain. Artikel Komunikasi antar layanan membahas pesan asinkron secara lebih rinci.

Ada beberapa pola DDD lain yang tidak tercantum di sini, termasuk pabrik, repositori, dan modul. Ini bisa menjadi pola yang berguna ketika Anda menerapkan layanan mikro, tetapi mereka kurang relevan ketika merancang batas-batas antara layanan mikro.

Drone delivery: Menerapkan pola

Kita mulai dengan skenario yang harus ditangani oleh konteks batas Pengiriman.

  • Pelanggan dapat meminta drone untuk mengambil barang dari bisnis yang terdaftar di layanan pengiriman drone.
  • Pengirim menghasilkan tag (barcode atau RFID) untuk memakai paket.
  • Drone akan mengambil dan mengirimkan paket dari lokasi sumber ke lokasi tujuan.
  • Ketika pelanggan menjadwalkan pengiriman, sistem menyediakan ETA berdasarkan informasi rute, kondisi cuaca, dan data historis.
  • Ketika drone sedang dalam penerbangan, pengguna dapat melacak lokasi saat ini dan ETA terbaru.
  • Sampai drone mengambil paket, pelanggan dapat membatalkan pengiriman.
  • Pelanggan diberi tahu saat pengiriman selesai.
  • Pengirim dapat meminta konfirmasi pengiriman dari pelanggan, dalam bentuk tanda tangan atau sidik jari.
  • Pengguna dapat mencari riwayat pengiriman yang telah selesai.

Dari skenario ini, tim pengembangan mengidentifikasi entitas berikut.

  • Pengiriman
  • Paket
  • Drone
  • Akun
  • Konfirmasi
  • Pemberitahuan
  • Tag

Empat yang pertama, Pengiriman, Paket, Drone, dan Akun, semuanya adalah agregat yang mewakili batas konsistensi transaksional. Konfirmasi dan Pemberitahuan adalah entitas turunan dari Pengiriman, dan Tag adalah entitas turunan dari Paket.

Objek nilai dalam desain ini termasuk Lokasi, ETA, PackageWeight, dan PackageSize.

Sebagai ilustrasi, berikut adalah diagram UML dari agregat Delivery. Perhatikan bahwa ia memegang referensi ke agregat lain, termasuk Akun, Paket, dan Drone.

Diagram UML dari agregat Pengiriman

Ada dua peristiwa domain:

  • Sementara drone sedang dalam penerbangan, entitas Drone mengirimkan peristiwa DroneStatus yang menggambarkan lokasi dan status drone (dalam penerbangan, mendarat).

  • Entitas pengiriman mengirimkan peristiwa DeliveryTracking setiap kali tahapan pengiriman berubah. Ini termasuk DeliveryCreated, DeliveryRescheduled, DeliveryHeadedToDropoff, dan DeliveryCompleted.

Perhatikan bahwa peristiwa ini mendeskripsikan hal-hal yang bermakna dalam model domain. Mereka mendeskripsikan sesuatu tentang domain dan tidak terikat pada konstruksi bahasa pemrograman tertentu.

Tim pengembangan mengidentifikasi satu lagi area fungsionalitas, yang tidak cocok dengan entitas mana pun yang dijelaskan sejauh ini. Beberapa bagian dari sistem harus mengoordinasikan semua langkah yang terlibat dalam penjadwalan atau memperbarui pengiriman. Oleh karena itu, tim pengembangan menambahkan dua layanan domain ke desain: Penjadwal yang mengoordinasikan langkah-langkah, dan Supervisor yang memantau status setiap langkah, untuk mendeteksi apakah ada langkah yang gagal atau tepat waktu. Ini adalah variasi dari pola Pengawas Agen Penjadwal.

Diagram model domain yang direvisi

Langkah berikutnya

Langkah selanjutnya adalah menentukan batas-batas untuk setiap layanan mikro.