Apa pola desain "Perbaiki Semuanya"?

74

Dalam artikel 2003 oleh Stephen Figgins di linuxdevcenter.com , BitTorrent dari Bram Cohen digambarkan menggunakan pola desain "Perbaiki Semuanya".

Pendekatan yang kurang umum yang keduanya membuat BitTorrent lebih sulit untuk dipahami, tetapi layak untuk dipelajari, adalah penggunaan idempoten Cohen. Suatu proses idempoten ketika menerapkannya lebih dari sekali tidak menyebabkan perubahan lebih lanjut. Cohen mengatakan ia menggunakan pola desain yang ia sebut "Perbaiki Semuanya," sebuah fungsi yang dapat bereaksi terhadap sejumlah perubahan tanpa benar-benar memperhatikan apa yang mungkin berubah. Dia menjelaskan, "Anda perhatikan peristiwa yang terjadi, lalu panggil fungsi fix everything yang ditulis dengan cara yang sangat idempoten ini, dan bersihkan apa pun yang sedang terjadi dan hitung ulang semuanya dari awal." Sementara idempotensi membuat beberapa perhitungan sulit lebih mudah, itu membuat hal-hal sedikit berbelit-belit. Tidak selalu jelas apa panggilan akan berubah, jika ada. Anda tidak perlu tahu sebelumnya. Anda bebas memanggil fungsinya,

Ini kedengarannya cukup bagus di wajahnya.

Namun, bagi saya tampaknya memanggil fungsi "memperbaiki semuanya" yang idempoten akan meningkatkan ketahanan sistem dengan biaya efisiensi dan berpotensi mengacaukan sistem yang berisi (yang mungkin lebih suka proses yang hati-hati merencanakan dan mengeksekusi.).

Saya tidak bisa mengatakan bahwa saya pernah menggunakannya sebelumnya. Saya juga tidak dapat menemukan sumber untuk aplikasi online-nya (tapi saya memang menemukan ini yang mengklaim berdasarkan itu.). Saya juga tidak dapat menemukan referensi di luar artikel ini (dan saya menganggap google-fu saya cukup bagus) tetapi saya menemukan entri untuk "Kemampuan Idempoten" di SOApatterns.org .

Apakah ide ini lebih dikenal dengan nama lain?

Apa pola desain "Perbaiki Semuanya"? Apa kelebihan dan kekurangannya?

Aaron Hall
sumber
4
Saya menduga nama juga merupakan referensi ke ide titik tetap suatu fungsi, x = f (x). Tidak peduli berapa kali Anda menerapkan f to x , hasilnya tetap sama. Setelah Anda mencapai hasil yang benar, memproses ulang hasil yang benar mengembalikan hasil yang benar sama.
9000
7
Perhatikan bahwa siapa pun dapat memberikan nama apa pun untuk apa pun yang mereka inginkan, tetapi itu tidak menjadikannya pola perangkat lunak yang terkenal. Idempotency adalah konsep yang terkenal dengan caranya sendiri; sepertinya digunakan secara kreatif di sini.
Robert Harvey
1
Ini mengingatkan saya pada bagaimana Loop Peristiwa Utama diimplementasikan pada Mac OS. Itu adalah fungsi tunggal yang menanggapi setiap Acara dan umumnya disusun untuk menguji keadaan semua kontrol dan memperbarui seluruh UI sesuai kebutuhan. Idempoten, memang.
Lucas
3
This sounds quite nice on the face of it. Benarkah? Kedengarannya mengerikan bagiku!
Michael
3
@Michael Anda tidak suka manajer paket? Mereka bekerja dengan konsep yang sama, hanya pada skala yang lebih kecil: Tandai apa yang Anda ingin sistem terlihat, jalankan "memperbaiki semuanya", itu menginstal / menghapus / memutakhirkan yang sesuai, tetapi hanya memiliki sesuatu untuk dilakukan jika ada perubahan.
Izkata

Jawaban:

100

Katakanlah Anda memiliki halaman HTML yang cukup rumit - jika Anda memilih sesuatu dalam satu dropdown, kontrol lain mungkin muncul, atau nilai-nilai dalam kontrol ketiga mungkin berubah. Ada dua cara Anda bisa mendekati ini:

  1. Tulis pengendali terpisah, untuk masing-masing dan setiap kontrol, yang merespons peristiwa pada kontrol itu, dan memperbarui kontrol lainnya sesuai kebutuhan.

  2. Tulis satu pawang yang melihat keadaan semua kontrol pada halaman dan perbaiki semuanya .

Panggilan kedua adalah "idempoten" karena Anda dapat memanggilnya berulang kali dan kontrol akan selalu diatur dengan benar. Sedangkan panggilan pertama mungkin memiliki masalah jika panggilan hilang atau diulang, misalnya jika salah satu penangan melakukan toggle.

Logika untuk panggilan kedua akan sedikit lebih kabur, tetapi Anda hanya perlu menulis satu penangan.

Dan Anda selalu dapat menggunakan kedua solusi, memanggil fungsi "memperbaiki semuanya" sesuai kebutuhan "hanya untuk berada di sisi yang aman."

Pendekatan kedua sangat baik ketika keadaan dapat berasal dari sumber yang berbeda, misalnya dari input pengguna dibandingkan yang diberikan dari server. Di ASP.NET, teknik ini bermain sangat baik dengan konsep postback karena Anda hanya menjalankan fungsi fix everything setiap kali Anda membuat halaman.

Sekarang saya telah menyebutkan peristiwa yang hilang atau berulang, dan mendapatkan status dari sumber yang berbeda, saya pikir sudah jelas bagaimana pendekatan ini memetakan dengan baik ke ruang masalah seperti BitTorrent.

Kontra? Nah yang jelas adalah bahwa ada hit kinerja karena kurang efisien untuk membahas semuanya sepanjang waktu. Tetapi solusi seperti BitTorrent dioptimalkan untuk ditingkatkan, bukan ditingkatkan, jadi itu bagus untuk hal semacam itu. Tergantung pada masalah yang Anda coba selesaikan, itu mungkin tidak cocok untuk Anda.

John Wu
sumber
9
Menurut saya MVC adalah tipikal dari "Memperbaiki Segalanya": ketika Anda memodifikasi model kemudian menggambar ulang tampilan dari awal, tampilan hanya digambar ulang sepenuhnya, tanpa berusaha untuk mengetahui bagian mana dari tindakan yang berpotensi mempengaruhi.
Matthieu M.
3
Ini pada dasarnya terdengar seperti prinsip di balik sistem seperti Saltstack, Ansible, dan Nix. Diberikan deskripsi konfigurasi, Anda secara teoritis dapat membawa beberapa sistem yang beragam ke kondisi akhir yang sama.
kojiro
1
@ MatthieuM. React , yang cukup populer pada pengembangan frontend, adalah seperti itu kecuali ia melakukan virtual dom diffing sehingga hanya memperbarui dom sebenarnya dengan perubahan yang sebenarnya
Izkata
2
@Izkata Bahkan lebih dari Bereaksi, jawaban ini membuat saya berpikir tentang Redux.
Kevin
2
Mungkin bermanfaat untuk menunjukkan bahwa "memperbaiki semuanya" dan idempoten adalah hal yang berbeda: "memperbaiki semuanya" biasanya idempoten (tetapi tidak perlu), dan operasi idempoten tidak perlu memperbaiki semuanya atau bahkan memiliki kinerja penalti - cukup berikan hasil yang sama saat dieksekusi dua kali.
Hans-Peter Störr
15

Saya pikir artikel ini sedikit ketinggalan jaman karena ketika saya membacanya, ini sebenarnya bukan ide yang tidak lazim atau baru. Ide ini disajikan sebagai pola terpisah ketika itu benar-benar hanya sebuah implementasi Pengamat sederhana. Memikirkan kembali apa yang saya lakukan pada saat itu, saya ingat bekerja pada logika untuk duduk di belakang antarmuka yang agak rumit dengan sejumlah panel berbeda dengan data yang saling bergantung. Pengguna dapat mengubah nilai dan / atau menjalankan rutin optimasi dan berdasarkan pada tindakan-tindakan itu, peristiwa dihasilkan bahwa UI akan mendengarkan dan memperbarui sesuai kebutuhan. Ada sejumlah masalah selama pengembangan di mana panel tertentu tidak akan memperbarui kapan mereka seharusnya. Cara mengatasinya (tetap dalam desain) adalah untuk menghasilkan acara dari acara lain. Pada akhirnya, pada saat semuanya bekerja dengan baik, hampir setiap perubahan menghasilkan semua panel untuk di-refresh. Semua kerumitan mencoba mengisolasi ketika panel tertentu perlu menyegarkan tidak ada gunanya. Lagi pula itu tidak masalah. Itu efektif optimasi prematur. Saya akan menghemat banyak waktu dan upaya dengan hanya menciutkan semuanya menjadi satu peristiwa yang menyegarkan segalanya.

Ada banyak sekali sistem yang dirancang dalam "memperbaiki semuanya" atau menyegarkan segalanya dengan cara apa pun. Pikirkan semua antarmuka CRUD yang menambah / memperbarui satu baris dan kemudian meminta DB. Ini bukan pendekatan yang eksotis, itu hanya solusi yang tidak cerdas. Anda harus menyadari bahwa pada tahun 2003, itu adalah puncak 'demam pola'. Dari apa yang bisa saya katakan, orang-orang berpikir penamaan pola baru akan menjadi jalan mereka menuju ketenaran dan kekayaan. Jangan salah paham, saya pikir konsep suatu pola sangat berguna untuk menggambarkan solusi secara abstrak. Hal-hal seperti agak keluar dari rel sedikit. Sangat disayangkan karena menciptakan banyak sinisme tentang konsep pola pada umumnya. Hanya dalam konteks ini masuk akal untuk membicarakan ini sebagai solusi 'tidak lazim'. Saya t' Mirip dengan ortodoksi di sekitar ORM atau wadah DI. Tidak menggunakan mereka dipandang sebagai tidak lazim meskipun orang telah membangun perangkat lunak jauh sebelum alat ini ada dan dalam banyak kasus alat tersebut berlebihan.

Jadi kembalilah ke 'perbaiki semuanya'. Contoh sederhana adalah cara menghitung. Solusi sederhana adalah dengan menjumlahkan angka dan membaginya dengan kardinalitas nilai-nilai tersebut. Jika Anda menambah atau memodifikasi angka, Anda cukup melakukannya lagi, dari awal. Anda bisa melacak jumlah dan jumlah angka dan ketika seseorang menambahkan angka, Anda menambah jumlah dan menambahkannya ke jumlah. Sekarang Anda tidak menambahkan kembali semua angka lagi. Jika Anda pernah bekerja dengan Excel dengan rumus yang mereferensikan rentang dan mengubah nilai tunggal dalam rentang itu, Anda memiliki contoh pola 'perbaiki semuanya' yaitu rumus apa pun yang memiliki referensi ke rentang itu akan dihitung ulang terlepas dari apakah nilai itu relevan (misalnya menggunakan sesuatu seperti sumif ()).

Ini bukan untuk mengatakan ini bukan pilihan cerdas dalam konteks yang diberikan. Dalam contoh rata-rata, katakanlah sekarang kita perlu mendukung pembaruan. Sekarang saya perlu tahu nilai lama entah bagaimana dan hanya mengubah jumlah dengan delta. Tidak satu pun dari ini yang benar-benar menantang sampai Anda mempertimbangkan untuk mencoba melakukan ini dalam lingkungan yang didistribusikan atau bersamaan. Anda sekarang harus menangani semua jenis masalah waktu berduri dan Anda mungkin akan akhirnya menciptakan kemacetan besar yang memperlambat segalanya jauh lebih banyak daripada menghitung ulang.

Hasilnya di sini adalah bahwa pendekatan 'memperbaiki semuanya' atau 'menyegarkan semuanya' jauh lebih mudah untuk diperbaiki. Anda dapat membuat pendekatan yang lebih canggih bekerja tetapi jauh lebih rumit dan karena itu lebih cenderung cacat. Selain itu dalam banyak konteks, pendekatan 'menyegarkan semuanya' bisa lebih efisien. Sebagai contoh, salin pada pendekatan menulis umumnya lebih lambat untuk pendekatan single-threaded tetapi ketika Anda memiliki konkurensi tinggi, itu dapat memungkinkan Anda untuk menghindari kunci dan karenanya memberikan kinerja yang lebih baik. Dalam kasus lain, ini dapat memungkinkan Anda untuk mengumpulkan perubahan secara efisien. Jadi untuk sebagian besar masalah, Anda mungkin ingin memulai dengan pendekatan refresh segalanya kecuali Anda memiliki alasan spesifik mengapa Anda tidak dapat melakukannya dan kemudian khawatir tentang melakukan sesuatu yang lebih kompleks setelah Anda membutuhkannya.

JimmyJames
sumber
2
Saya cukup yakin Excel bermaksud hanya menghitung ulang sel yang tergantung pada perubahan, itulah sebabnya ada cara untuk memicu semua sel untuk menghitung ulang: superuser.com/questions/448376/… (yang saya kira akan menjadi "perbaiki semuanya" )
Aaron Hall
@ AaronHall Jika ya, ini implementasi yang sangat buruk. Saya secara teratur menontonnya mengkonsumsi 100% dari 7 CPU selama 15-30 menit untuk menghitung misalnya 60.000 sel. Perhitungannya tidak rumit. Saya sudah sering menulis program Python yang dapat melakukan semuanya di sheet dalam beberapa detik termasuk memulai Python. Ini adalah tebakan terbaik saya tentang bagaimana hal itu bisa berlangsung begitu lama. Bisa jadi itu hal lain yang kurasa. Ada juga beberapa bug yang sangat tua di Excel yang mungkin menjadi alasan untuk fitur itu.
JimmyJames
1
@ AaronHall mungkin juga dengan pengguna itu bahwa penghitungan otomatis dinonaktifkan pada sheet. Saya sering melakukan ini di buku kerja besar karena saya tidak punya waktu 15 menit untuk cadangan setiap kali saya menekan enter.
JimmyJames
@ Harun, saya pikir sedikit lagi dan Anda ada benarnya. Asumsi saya sepertinya terlalu luas. Saya memperbarui jawaban kepada saya lebih fokus pada sesuatu yang saya lebih percayai.
JimmyJames
2
@JimmyJames: Poin yang ingin saya sampaikan adalah bahwa pendekatan terbaik dapat sangat bervariasi tergantung pada keadaan, dan "perbaiki semuanya" dapat dibagi lagi menjadi "dengan bersemangat memperbaiki segala sesuatu pada setiap perubahan individu" dan "memperbaiki segala sesuatunya dengan malas setelah semua perubahan selesai ".
supercat
4

Tidak yakin itu adalah "pola desain", tapi saya akan mengklasifikasikan jenis perilaku itu sebagai konfigurasi kondisi akhir atau konfigurasi keadaan yang diinginkan , dalam nada Puppet, Chef atau Powershell DSC.

Solusi-solusi tersebut biasanya beroperasi pada level manajemen sistem, bukan pada level logika bisnis seperti dijelaskan oleh pertanyaan, tetapi ini adalah paradigma yang secara efektif sama, dan meskipun alat-alat tersebut biasanya bersifat deklaratif, prinsip-prinsip yang sama dapat diterapkan dalam kode atau skrip prosedural.

Dan1701
sumber
1

Saya sebagian besar menggunakan ini dalam antarmuka pengguna. Yang menyenangkan adalah Anda menulisnya sekali, dan menangani semuanya dari yang paling sederhana hingga yang paling sulit sama baiknya (misalnya jika pengguna memutar layar, atau pada laptop / desktop jika pengguna mengubah ukuran jendela, dan hampir semuanya berubah ).

Tidak banyak alasan untuk mengkhawatirkan efisiensi. Di antarmuka pengguna, hal-hal yang mahal adalah hal-hal seperti menggambar ulang item yang telah dipindahkan. Perhitungan di mana setiap item berjalan dan seberapa besar biasanya cukup cepat. Yang harus Anda pastikan adalah bahwa setiap kali Anda menemukan bahwa suatu barang harus tetap persis di tempat barang itu berada, tidak ada kode yang dijalankan untuk memindahkannya. Perubahan nyata adalah semua hal yang harus Anda lakukan.

gnasher729
sumber
0

Kedengarannya seperti prinsip pemrograman reaktif. "Perbaiki semuanya" melihat keadaan "inti" saat ini dan menyebarkan segala hal lain yang harus terpengaruh - "keadaan terkomputasi". Jika Anda mengoptimalkan derivasi ini, ia mungkin mencapai efisiensi tinggi, a-la React, jika dilakukan secara naif, kinerja mungkin tidak optimal walaupun masih bisa cukup cepat.

orip
sumber