Saya harus berkompromi: KERING, atau Command-Query-Separation?

10

Saya baru-baru ini refactoring metode yang merupakan perintah dan metode permintaan.

Setelah memisahkannya menjadi metode satu perintah dan satu metode kueri, saya menemukan bahwa sekarang ada beberapa tempat dalam kode tempat saya memanggil perintah lalu mendapatkan nilai dari kueri, yang sepertinya merupakan pelanggaran prinsip KERING.

Tetapi jika saya harus membungkus kode umum itu ke dalam suatu metode, metode itu akan menjadi perintah dan permintaan. Apakah ini dapat diterima?

Kris Welsh
sumber
oke, saya tidak tahu apakah komunitas itu sepakat, dan saya tidak dapat menemukan diskusi tentang topik ini.
Kris Welsh
Ini lebih umum disebut CQRS google.com.au/...
Daniel Little
@DanielLittle - tidak, tidak. CQS dan CQRS adalah subjek yang sangat berbeda. CQRS adalah pola arsitektur yang jauh lebih terlibat sementara CQS lebih merupakan pola desain dan lebih mudah dipahami dan diimplementasikan. Lihat codebetter.com/gregyoung/2009/08/13/command-query-saration
Erik Funkenbusch
@Erik Funkenbusch Anda benar
Daniel Little

Jawaban:

11

Selalu ada trade off untuk dipertimbangkan antara prinsip-prinsip desain yang saling bertentangan. Cara mengatasinya adalah dengan melihat alasan yang mendasari di balik prinsip-prinsip tersebut. Dalam kasus ini, tidak dapat menjalankan kueri tanpa menjalankan perintah bermasalah, tetapi tidak dapat menjalankan perintah tanpa menjalankan kueri umumnya tidak berbahaya. Selama ada cara untuk menjalankan kueri mandiri, saya tidak melihat alasan untuk tidak menambahkan hasil kueri ke perintah, terutama jika melakukan sesuatu seperti ini:

QueryResult command()
{
   // do command stuff
   return query();
}
Karl Bielefeldt
sumber
4

Saya belum pernah mendengar Command-Query-Separation (CQS) sebelumnya, tetapi tampaknya itu berhubungan dengan Prinsip Tanggung Jawab Tunggal (SRP), yang menyatakan bahwa fungsi / kelas idealnya harus bertanggung jawab untuk melakukan satu hal dan satu hal saja .

Jika kode perintah Anda adalah 20 baris kode dan kode kueri adalah 30 baris lainnya dan semuanya berada dalam satu fungsi, jelas Anda melanggar SRP dan saya akan menganggap CQS juga dan kedua potongan logika tersebut harus dipisahkan satu sama lain .

Namun, sesuai dengan contoh hipotetis Anda, saya kemungkinan besar akan membuat metode pembungkus yang akan menggabungkan perintah dan permintaan Anda sehingga KERING tidak dilanggar di banyak tempat dalam kode. Saya juga tidak akan menganggap ini sebagai pelanggaran SRP (dan mungkin CQS), karena pembungkus masih hanya memiliki satu tanggung jawab: untuk menggabungkan perintah dengan kueri dan membuat abstraksi tingkat yang lebih tinggi yang lebih mudah dikonsumsi.

Saya pikir metode pembungkus adalah solusi yang dapat diterima dan untuk menggambarkan itu, mari kita ambil contoh Anda selangkah lebih maju. Bagaimana jika Anda harus menjalankan 2 kueri alih-alih 1 dan kemudian melakukan tindakan perintah berdasarkan itu. Jadi 2 baris kode Anda akan menjadi 6 atau 8. Bagaimana jika ada beberapa validasi data / memeriksa antara satu dan yang lain, jadi sekarang Anda memiliki 15 baris kode. Apakah Anda berpikir dua kali tentang membuat pembungkus yang melakukan semua itu, daripada menaburkan 15 baris dalam beberapa file?

DXM
sumber
Saya pikir "prinsip tunggal" pembungkus harus menjaga metode lain yang membutuhkan perintah dan permintaan bersama-sama KERING.
Droogans
Google CQRS: google.com.au/…
Daniel Little
Sementara solusi Karl untuk masalah ini lebih baik, saya menemukan elaborasi Anda pada fungsi wrapper yang lebih lama menjadi poin yang sangat baik.
Kris Welsh
-3

KERING lebih penting, karena itu memecahkan kebutuhan yang jauh lebih mendasar - menghindari upaya yang sia-sia dan sia-sia. Ini adalah hal mendasar - seseorang tidak perlu menjadi programmer untuk memahaminya.

CQS merupakan respons terhadap kesulitan, dalam bahasa yang tidak mendukung efek pelacakan, untuk memahami kode yang dieksekusi baik untuk hasil maupun dampaknya. Namun:

  1. Perlunya mengeksekusi kode untuk hasilnya tidak dapat dihindari, karena ini adalah dasar untuk menyusun program besar dari unit kecil.

  2. Perlunya mengeksekusi kode untuk efeknya tidak dapat dihindari, karena, di luar matematika dan ilmu komputer teoretis, nilai menjalankan sebuah program terletak pada apa yang diamati dapat dilakukan untuk kita.

  3. Perlunya menimbulkan efek dan menghasilkan hasil dalam kode yang sama tidak dapat dihindari, karena, dalam praktiknya, kita membutuhkan efek dan komposisionalitas, bukan hanya satu atau yang lain.

Solusi aktual untuk masalah pelacakan efek yang terlalu sulit bagi manusia tanpa bantuan, tentu saja, memiliki komputer yang membantu kita manusia ! Hal serupa dapat dikatakan tentang melacak hubungan rumit antara nilai runtime (seperti validitas indeks array), yang pengecualian dan kontrak yang dijalankan runtime merupakan solusi (non-).

Kesimpulannya, "solusi" seperti CQS hanya menghalangi cara merancang program sesuai dengan prinsip-prinsip yang kuat berdasarkan kenyataan. Pergi untuk KERING.

ular sanca
sumber
Terkadang Anda perlu menghindari pemasangan untuk mengurangi kerumitan. Anda harus melihat CQRS.
Daniel Little
@ Lavinski: Alat terbaik untuk menghindari kompleksitas (tidak menguranginya, itu sia-sia) adalah abstraksi - memisahkan esensi generik dari masalah yang kita selesaikan dari perincian khusus dari contoh masalah generik tersebut. Resep ajaib (atau "pola desain" seperti yang saya dengar disebut) paling baik dapat mencegah Anda dari menyebabkan terlalu banyak kerusakan ketika Anda salah desain, tetapi mereka tidak dapat mengubah desain yang salah menjadi yang benar.
pyon
@ Lavinski: Sehubungan dengan CQRS secara khusus, solusi alternatif yang benar secara konseptual adalah 1. memahami model data (tidak ada jumlah lapisan objek yang dapat menghilangkan kebutuhan untuk ini), 2. menyandikan sebanyak mungkin properti kebenaran dalam skema basis data. (Sayangnya, RDBMSes paling populer memberikan dukungan yang agak terbatas untuk yang terakhir, belum lagi yang NoSQL, yang membuat ini lebih salah lagi. Penelitian saya saat ini memberikan solusi yang lebih baik untuk ini.)
pyon
CQRS bekerja sepenuhnya sejalan dengan Desain Domain Driven. Saya sarankan Anda melakukan sedikit riset. Domain di dalam aplikasi harus menegakkan kebenaran, bukan penyimpanan data Anda.
Daniel Little
1
@ EduardoLeón: Jika Anda ingin membuktikan desain Anda benar, maka cobalah untuk menulis tes untuk program Anda. Saya dapat menjamin Anda bahwa membuang CQS hanya akan menghambat upaya Anda dalam hal itu.
Stefan Billiet