Saya sedang mengerjakan sistem yang memungkinkan Administrator untuk mendefinisikan Formulir yang berisi Bidang. Formulir yang ditentukan kemudian digunakan untuk memasukkan data ke sistem. Kadang-kadang Formulir diisi oleh manusia melalui GUI, kadang-kadang Formulir diisi berdasarkan nilai yang dilaporkan oleh sistem lain.
Untuk setiap Bidang, Administrator dapat menetapkan Aturan Validasi yang membatasi nilai yang diizinkan untuk Bidang tersebut. Aturan Validasi dapat berupa apa saja mulai dari "nilai yang dimasukkan di Bidang harus Benar atau Salah" hingga "nilai yang dimasukkan di Bidang harus ada di kolom A dari tabel B dalam database". Administrator dapat setiap saat mengubah Aturan Validasi untuk Bidang.
Dalam skenario ini, menurut Anda, tempat apa yang paling cocok untuk memvalidasi bahwa setiap Field diisi dengan benar? Saat ini saya memiliki dua pendekatan utama dalam pikiran:
Opsi # 1: Validasi dalam Model Domain
Setiap objek bidang akan berisi Aturan Validasi yang ditentukan oleh Administrator. Objek Field juga akan memiliki referensi ke IValidator. Ketika upaya dilakukan untuk mengatur nilai Field, Field akan meneruskan nilai yang diberikan dan Aturan Validasi ke IValidator. Jika nilai yang diberikan tidak valid, ValidationException akan dibuang dan ditangani dengan benar di GUI / antarmuka ke sistem lain.
Pro:
- Perlindungan yang kuat terhadap Fields yang secara tidak sengaja diberi nilai yang melanggar Aturan Validasi
Cons:
Layer Akses Data harus dapat mem-bypass validasi dan membuat Fields yang melanggar Aturan Validasi saat ini. Meskipun Administrator mengubah Aturan Validasi untuk Bidang, kami masih harus dapat membangun objek Bidang berdasarkan data lama misalnya ketika membuat Formulir yang diisi tahun lalu. Ini berpotensi diselesaikan dengan menyimpan Aturan Validasi saat ini setiap kali kita menyimpan Field.
Dalam desain ini, model Field memiliki tautan tidak langsung ke Lapisan Akses Data / Repositori melalui IValidator. Injeksi Layanan / Repositori ke Model Domain tampaknya umumnya disukai .
Opsi # 2: Validasi dalam Layanan
Cobalah untuk memastikan bahwa semua upaya untuk menetapkan nilai Field lulus melalui Layanan yang memastikan Aturan Validasi berlaku. Jika Aturan Validasi dilanggar, lemparkan ValidationException.
Tentu saja, Lapisan Akses Data tidak akan menggunakan Layanan saat membuat objek Bidang yang sebelumnya telah ada dalam DB.
Pro:
Tidak melanggar "jangan menyuntikkan Layanan / Repositori ke dalam Model Domain Anda" - berpikir.
Tidak perlu mempertahankan Aturan Validasi saat ini saat bertahan di Lapangan. Layanan dapat dengan mudah mencari Aturan Validasi saat ini untuk Lapangan; saat melihat data riwayat, nilai Field tidak akan berubah.
Cons:
- Tidak ada jaminan bahwa semua logika yang harus menggunakan Layanan untuk mengatur nilai Field benar-benar melakukannya. Saya melihat ini sebagai kelemahan utama; yang diperlukan hanyalah seseorang yang menulis "thisField.setValue (thatField.getValue ())" dan Aturan Validasi thisField mungkin dilanggar tanpa ada yang lebih bijak. Ini dapat berpotensi dimitigasi dengan memastikan bahwa nilai Field cocok dengan Aturan Validasi ketika Layer Akses Data akan tetap bertahan Field.
Saat ini saya lebih suka Opsi # 1 daripada Opsi # 2, terutama karena saya melihat ini sebagai logika bisnis dan merasa bahwa Opsi # 2 memiliki risiko lebih besar untuk memperkenalkan data buruk ke sistem. Opsi mana yang Anda sukai, atau adakah desain lain yang sesuai dengan skenario ini lebih baik daripada dua opsi yang dijelaskan?
Edit (Kompleksitas validasi)
Kasus validasi yang muncul untuk saat ini relatif sederhana; nilai Field harus berupa numerik, tanggal, tanggal dengan waktu, atau menjadi nilai yang ada di kolom database. Namun, saya menduga kompleksitas meningkat secara bertahap dari waktu ke waktu. Misalnya, solusi validasi perlu dibangun dengan mempertimbangkan internasionalisasi - hal-hal seperti Tanggal dapat dimasukkan dalam sintaksis khusus-lokal.
Saya telah memutuskan untuk melanjutkan dengan Opsi # 1 untuk saat ini, berusaha berhati-hati untuk tidak memberikan terlalu banyak tanggung jawab pada Model Domain. Mereka yang menghadapi situasi serupa mungkin juga ingin memeriksa pertanyaan terkait Validasi dan otorisasi dalam arsitektur berlapis dan validasi input data - Di mana? Berapa banyak? .