Penangan perintah dan DDD

10

Saya memiliki aplikasi ASP.NET MVC, yang menggunakan layanan kueri untuk mendapatkan data dan layanan perintah untuk mengirim perintah. Pertanyaan saya adalah tentang bagian perintah.

Jika permintaan masuk, layanan perintah menggunakan dispatcher perintah yang akan merutekan perintah ke penangan perintah yang ditunjuk. Penangan perintah ini memvalidasi perintah terlebih dahulu dan jika semuanya dapat diterima, itu menjalankan perintah.

Contoh nyata: AddCommentToArticleCommandHandler menerima AddCommentToArticleCommand, yang memiliki ArticleId, CommentText dan EmailAddress.

Pertama; validasi harus terjadi, seperti: - periksa apakah artikel ada - periksa apakah artikel tidak ditutup - periksa apakah teks komentar diisi dan antara 20 dan 500 karakter - periksa apakah alamat email diisi dan memiliki format yang valid.

Saya ingin tahu di mana harus meletakkan validasi ini?

1 / di command handler itu sendiri. Tapi kemudian, itu tidak dapat digunakan kembali di penangan perintah lainnya.

2 / dalam entitas domain. Tetapi karena entitas domain tidak tahu tentang repositori atau layanan, ia tidak dapat melakukan validasi yang diperlukan (tidak dapat memeriksa apakah ada artikel). Tetapi di sisi lain, jika entitas tidak mengandung logika, maka itu akan menjadi wadah data sederhana, yang tidak mengikuti prinsip-prinsip DDD.

3 / penangan perintah menggunakan validator, sehingga validasi dapat digunakan kembali di penangan perintah lainnya.

4 / Mekanisme lainnya?

Saya mencari rantai tanggung jawab untuk contoh khusus ini dan objek apa (entitas, repositori, ...) yang berperan di dalamnya.

Apakah Anda memiliki ide tentang bagaimana Anda akan mengimplementasikan ini, mulai dari penangan perintah hingga repositori?

L-Empat
sumber
"Tetapi karena entitas domain tidak tahu tentang repositori atau layanan, ia tidak dapat melakukan validasi yang diperlukan"? Kenapa tidak? Prinsip DDD apa yang mensyaratkan ini?
S.Lott
Saya membaca di mana-mana bahwa suatu entitas tidak boleh tahu tentang repositori atau apa pun.
L-Four
Dapatkah Anda memberikan penawaran, tautan atau contoh dari apa - khususnya - yang telah Anda baca? Kami tidak tahu deskripsi DDD apa yang Anda baca.
S.Lott
Jimmy Bogard berbagi pandangan tentang topik ini ... lostechies.com/jimmybogard/2009/02/15/validation-in-a-ddd-world
Mayo

Jawaban:

4

Saya pikir Anda perlu memisahkan dua jenis validasi dalam kasus ini; validasi domain dan validasi aplikasi .

Validasi aplikasi adalah apa yang Anda miliki ketika Anda memverifikasi bahwa properti teks perintah 'adalah antara 20 dan 200 karakter; jadi Anda memvalidasi ini dengan GUI dan dengan view-model-validator yang juga dijalankan di server setelah POST. Hal yang sama berlaku untuk e-mail (btw, saya harap Anda menyadari bahwa e-mail seperti `32.d +" Hello World .42 "@ mindomän.local" adalah valid menurut RFC).

Kemudian Anda memiliki validasi lain; periksa artikel itu ada - Anda harus bertanya pada diri sendiri pertanyaan mengapa artikel itu seharusnya tidak ada jika memang ada perintah yang dikirim dari GUI yaitu tentang melampirkan komentar padanya. Apakah GUI Anda akhirnya konsisten dan Anda memiliki root agregat, artikel, yang dapat dihapus secara fisik dari penyimpanan data? Dalam hal ini Anda hanya memindahkan perintah ke antrian kesalahan karena penangan perintah gagal memuat akar agregat.

Dalam kasus di atas, Anda akan memiliki infrastruktur yang menangani pesan racun - mereka misalnya akan mencoba lagi pesan 1-5 kali dan kemudian memindahkannya ke antrian poision di mana Anda bisa secara manual memeriksa koleksi pesan dan mengirim kembali yang relevan. Ini hal yang baik untuk dipantau.

Jadi sekarang kita sudah membahas:

  • Validasi aplikasi

    • Dengan javascript di GUI
    • Dengan validasi MVC di server web
  • Antrean agregat root + racun tidak ada

Bagaimana dengan perintah yang tidak sinkron dengan domain? Mungkin Anda memiliki aturan dalam logika domain Anda yang mengatakan bahwa setelah 5 komentar ke sebuah artikel, hanya komentar di bawah 400 karakter yang diperbolehkan, tetapi satu orang sudah terlambat dengan komentar ke-5 dan menjadi yang ke-6 - GUI tidak menangkapnya karena itu tidak konsisten dengan domain pada saat dia mengirimkan perintahnya - dalam hal ini Anda memiliki 'kegagalan validasi' sebagai bagian dari logika domain Anda dan Anda akan mengembalikan peristiwa kegagalan yang sesuai.

Acara tersebut bisa dalam bentuk pesan ke pialang pesan atau pengirim kustom Anda. Server web, jika aplikasinya monolitik, dapat secara sinkron mendengarkan acara sukses dan kegagalan yang disebutkan dan menampilkan tampilan yang sesuai / sebagian.

Seringkali Anda memiliki acara khusus yang berarti kegagalan untuk banyak jenis perintah, dan ini adalah acara yang Anda ikuti dari perspektif server web.

Dalam sistem yang sedang kami kerjakan, kami melakukan permintaan-respons dengan perintah / acara melalui broker pesan + broker MassTransit + RabbitMQ dan kami memiliki acara di domain khusus ini (memodelkan alur kerja sebagian) yang dinamai InvalidStateTransitionError. Sebagian besar perintah yang mencoba bergerak di sepanjang sisi dalam grafik keadaan dapat menyebabkan peristiwa ini terjadi. Dalam kasus kami, kami memodelkan GUI setelah paradigma yang akhirnya konsisten, dan karenanya kami mengirim pengguna ke halaman 'perintah diterima' dan kemudian membiarkan tampilan server web diperbarui secara pasif melalui langganan acara. Harus disebutkan bahwa kita juga melakukan event-sourcing di akar agregat (dan akan melakukan juga untuk kisah-kisah).

Jadi Anda lihat, banyak validasi yang Anda bicarakan sebenarnya adalah validasi tipe aplikasi, bukan logika domain aktual. Tidak ada masalah dalam memiliki model domain sederhana jika domain Anda sederhana tetapi Anda sedang melakukan DDD. Namun, saat Anda terus memodelkan domain Anda, Anda akan menemukan bahwa domain tersebut mungkin tidak sesederhana yang pertama kali terjadi. Dalam banyak kasus, agregat root / entitas mungkin hanya menerima pemanggilan metode yang disebabkan oleh perintah dan mengubah beberapa statusnya tanpa melakukan validasi apa pun - terutama jika Anda memercayai perintah Anda seperti yang akan Anda lakukan jika Anda memvalidasinya di server web yang kamu mengendalikan.

Saya dapat merekomendasikan menonton dua presentasi tentang DDD dari Norwegian Developer Conference 2011 dan juga presentasi Greg di Öredev 2010 .

Cheers, Henke

Henrik
sumber
Terima kasih! Satu hal tentang validasi: saat ini, validasi ini dipicu oleh UI (dengan mengeluarkan permintaan Validasi (perintah) ke layanan), yang menggunakan Validasi () dari entitas Komentar itu sendiri. Kemudian, jika perintah itu valid, klien mengeluarkan perintah Execute, yang akan lagi menjalankan Validasi () untuk memastikan, dan jika valid perintah yang sebenarnya dijalankan. Jadi validasi utama dilakukan oleh entitas Comment, karena dalam setiap konteks validasi akan sama (email selalu harus valid, teks komentar tidak terlalu panjang, dll.) Apakah ini pendekatan yang baik?
L-Four
Validasi yang tampaknya Anda uraikan tampaknya tidak bagi saya untuk menjamin pemodelannya dengan protokol validasi 2 fase - tentu saja, validasikan parameter pemanggilan metode pada entitas seperti yang akan Anda uji dalam unit test, tetapi selain itu; lapisan aplikasi / GUI dapat dengan mudah memvalidasi aturan yang Anda uraikan tanpa mengirim perintah ke domain. Imo. Kecuali jika klien berbahaya maka perintah harus bekerja. Jika klien jahat maka perintah gagal dan model baca Anda tidak pernah mendapatkan acara yang sesuai dan Anda dapat memeriksa perintah bermasalah dalam antrian kesalahan.
Henrik
Di UI (ASP.NET MVC) saya menggunakan atribut validasi untuk melakukan semua validasi. Jadi jika validasi ini berhasil, saya tidak perlu memvalidasi lagi pada domain itu, tetapi jalankan saja perintahnya?
L-Four
1
Ya, Anda menjalankan perintah tetapi pastikan bahwa perintah tersebut tidak valid baik di lapisan aplikasi dan domain.
Henrik
0

EDIT: WaybackMachine tautan: http://devlicio.us/blogs/billy_mccafferty/archive/2009/02/17/a-response-to-validation-in-a-ddd-world.aspx

Tidak ada jawaban tepuk.

Ada dua skenario proyek yang jelas yang muncul di benak saya ketika saya mencoba menjawab di mana validasi harus dijalani. Yang pertama adalah di mana lapisan DTO digunakan untuk mentransfer informasi antara tampilan dan lapisan domain. Misalnya, Anda mungkin memiliki objek Pelanggan di lapisan domain Anda dan DTO Pelanggan terkait di lapisan lain tempat Anda memetakan informasi Pelanggan, untuk kemudian memberikan tampilan untuk menyajikan informasi Pelanggan kepada pengguna.

Skenario kedua adalah proyek di mana entitas dalam lapisan domain dibagikan secara langsung dengan tampilan untuk menyajikan data kepada pengguna. Misalnya, alih-alih mempertahankan lapisan DTO terpisah dan memetakan objek domain ke DTO untuk diberikan kepada tampilan, tampilan dapat diberikan objek Pelanggan secara langsung. Jadi, alih-alih berbicara melalui DTO yang dikelola secara terpisah untuk menunjukkan nama Pelanggan, tampilan hanya akan meminta informasi objek Pelanggan sendiri.

S.Lott
sumber