Di lapisan mana validasi harus ditempatkan?

18

Saya membuat API Istirahat menggunakan Boot Spring dan saya menggunakan Hibernate Validation untuk memvalidasi input permintaan.

Tetapi saya juga memerlukan jenis validasi lain, misalnya ketika data pembaruan perlu diperiksa, jika id perusahaan tidak ada, saya ingin melempar pengecualian khusus.

Haruskah validasi ini ditempatkan di lapisan layanan atau lapisan pengontrol?

Lapisan Layanan:

 public Company update(Company entity) {
    if (entity.getId() == null || repository.findOne(entity.getId()) == null) {
        throw new ResourceNotFoundException("can not update un existence data with id : " 
            + entity.getId());
    }
    return repository.saveAndFlush(entity);
}

Lapisan Pengontrol:

public HttpEntity<CompanyResource> update(@Valid @RequestBody Company companyRequest) {
    Company company = companyService.getById(companyRequest.getId());
    Precondition.checkDataFound(company, 
        "Can't not find data with id : " + companyRequest.getId());

    // TODO : extract ignore properties to constant

    BeanUtils.copyProperties(companyRequest, company, "createdBy", "createdDate",
            "updatedBy", "updatedDate", "version", "markForDelete");
    Company updatedCompany = companyService.update(company);
    CompanyResource companyResource = companyAssembler.toResource(updatedCompany);
    return new ResponseEntity<CompanyResource>(companyResource, HttpStatus.OK);
}
fdarmanto
sumber

Jawaban:

8

Lapisan pengontrol dan lapisan layanan memperlihatkan antarmuka tertentu. Antarmuka menentukan kontrak tentang bagaimana antarmuka harus digunakan. Kontrak biasanya berarti argumen mana (dan jenis serta nilainya) yang diharapkan, pengecualian yang dapat dilemparkan, efek samping mana yang dibuat, dll.

Sekarang, validasi Anda pada dasarnya adalah penerapan metode kontrak pembaruan kontroler () dan metode pembaruan lapisan layanan (). Keduanya memiliki kontrak yang sangat mirip sehingga wajar jika validasi (penegakan kontrak) juga biasa.

Salah satu cara yang mungkin untuk melakukan itu adalah dengan memisahkan validasi kontrak ini dan meminta itu disebut di kedua lapisan. Ini biasanya paling jelas - setiap kelas / metode menegakkan kontrak mereka sendiri, tetapi seringkali tidak taktis karena kinerja (mengakses database) atau alasan lain.

Kemungkinan lain adalah mendelegasikan validasi ini ke lapisan layanan sementara secara eksplisit mendefinisikan perilaku jika validasi gagal dalam kontrak lapisan layanan. Lapisan layanan biasanya akan mengembalikan beberapa kesalahan validasi umum (atau melempar pengecualian) dan lapisan pengontrol akan ingin bereaksi dengan cara tertentu terhadap kesalahan - dalam hal ini kami akan mengembalikan 400 permintaan buruk untuk memberi sinyal, bahwa permintaan yang masuk tidak valid.

Dalam desain ini, ada bahaya terlalu banyak penggabungan antara logika bisnis di lapisan layanan (yang seharusnya cukup umum) dan pengontrol (yang menangani logika integrasi).

Bagaimanapun, ini adalah pertanyaan yang cukup kontroversial dan 100 orang akan menjawab dengan 100 jawaban. Ini hanya pendapat saya.

qbd
sumber
1

Input harus diperiksa di lapisan layanan.

Dan "Tidak dapat menemukan id" adalah kondisi kesalahan logis. Jadi harus dibuang dari lapisan pengontrol.

Ini lagi tergantung pada layering / desain Anda.
Apa yang seharusnya dilakukan oleh lapisan layanan dan apa yang diharapkan dari lapisan pengontrol.

Tanpa kertas
sumber
Sebuah jawaban seharusnya tidak mencari klarifikasi tambahan dari pertanyaan. Jika pertanyaan itu perlu diklarifikasi, pertanyaan itu harus dikomentari dan mungkin ditandai untuk ditutup jika terlalu tidak jelas. Ya, saya sadar Anda tidak memiliki reputasi untuk tindakan tersebut.
"Pemeriksaan input" tidak jelas. Misalnya, saya mungkin meletakkan atribut yang diperlukan pada bidang untuk menunjukkan bahwa itu harus diisi, tetapi juga saya mungkin menempatkan atribut khusus yang kompleks yang memeriksa, misalnya, bahwa satu nilai bidang lebih besar dari yang lain. IMHO, Bandingkan validasi "bau" lebih banyak lapisan layanan bisnis daripada lapisan pengontrol.
JustAMartin
1

Validasi Hibernate adalah pemeriksaan integritas data. Untuk menghindari RuntimeExceptions dari bbdd. Mereka hampir sama dengan validasi yang harus Anda kontrol dengan Constrains . Karena hanya lapisan bisnis yang seharusnya memberi makan lapisan ketekunan, Anda mungkin (atau tidak, terserah Anda) mempercayai kebenaran data yang berasal dari lapisan bisnis Anda

Saya tidak memasukkan validasi dalam DAO. Saya mengharapkan data yang valid dari lapisan atas. Dalam hal terjadi kesalahan, saya mendelegasikan kepada bbdd tanggung jawab untuk mengetahui isinya.

Kemudian datang validasi di lapisan bisnis. Semua validasi bisnis fokus pada menjaga koherensi data, bukan integritasnya .

Akhirnya saya melakukan validasi sebelumnya pada lapisan kontrol. Yang terkait hanya dengan lapisan tersebut.

Anda akan segera melihat validasi mana yang dimaksudkan untuk diterapkan pada lapisan bisnis. Yang paling umum: kontrol id. Yang ini dapat dengan mudah diimplementasikan di kedua lapisan. Jika Anda berharap memiliki banyak pengontrol atau klien yang menggunakan lapisan bisnis Anda, alih-alih mengulangi validasi yang sama di mana-mana, itu akan menjadi kandidat yang sangat baik untuk ditempatkan di lapisan bisnis.

Kadang-kadang pengendali memiliki aturan dan ketentuan mereka sendiri yang tidak akan direproduksi di fasad lain. Maka itu adalah kandidat untuk dimasukkan ke dalam pengontrol seperti itu.

Pikirkan tentang apa yang Anda validasi dan jika Anda ingin menerapkannya untuk semua orang, apa pun yang terjadi. Atau jika itu adalah validasi kontekstual ("Saya memvalidasi sesuatu yang hanya terjadi pada fasad kontrol / tampilan tertentu).

Laiv
sumber
0

Di toko Java kami, kami sengaja membagi validasi widget web menjadi tiga operasi terpisah.

  1. Pemformatan dasar - angka harus berupa angka; tanggal harus tanggal yang valid dll. Biasanya validasi ini datang secara gratis - kerangka web akan melakukannya untuk Anda saat mengikat konten widget ke model.
  2. Validasi widget tunggal - tanggal harus di masa lalu; bilangan bulat harus antara 1 dan 100; customerId harus ada dalam database dll. Ini termasuk dalam lapisan pengontrol dalam banyak kasus, tetapi mungkin memerlukan dukungan dari repositori data.
  3. Validasi lintas-widget - tanggal checkout harus setelah tanggal check-in; tanggal kematian tidak boleh sebelum tanggal lahir dll. Ini jelas merupakan validasi aturan bisnis. Kami cenderung untuk meletakkan ini di lapisan pengontrol juga, tetapi Anda mungkin ingin mengubahnya menjadi validator bisnis sehingga dapat digunakan kembali.

Jika layer 1 gagal, kami tidak memeriksa 2 atau 3. Demikian pula jika 1 berhasil dan 2 gagal kami tidak melakukannya 3. Ini menghentikan pesan kesalahan palsu yang dihasilkan.

Anda bertanya tentang nilai-nilai dalam panggilan REST daripada konten widget, tetapi prinsip yang sama berlaku.

kiwiron
sumber
-1

Uji coba pendekatan didorong teduh pada ini ,, setelah semua tidak ada controller dan Anda harus memilih opsi lain. Jelas aturan bisnis harus di satu tempat, dan ini adalah kendala lain dalam keputusan Anda.

Hans Poo
sumber