Який шаблон дизайну "Виправити все"?


74

У цій статті про Стівена Фіггінса на linuxdevcenter.com від 2003 року , BitTorrent Брема Коена описаний як використання шаблону дизайну "Виправити все".

Менш поширеним підходом, який обох робить BitTorrent важче зрозуміти, але гідний вивчення, є використання Коеном ідентифікації. Процес ідентичний, коли застосовувати його не раз не викликає подальших змін. Коен каже, що використовує схему дизайну, яку він називає "Виправити все", функцію, яка може реагувати на ряд змін, не зазначаючи, що все це може змінитися. Він пояснює: "Ви відзначаєте подію, що сталася, потім зателефонуйте на функцію виправити все, що написано дуже невміло, і просто очищає все, що може бути, і перераховує все з нуля". Незважаючи на те, що ідентифікація полегшує деякі складні обчислення, вона робить дещо заплутаною. Не завжди зрозуміло, який дзвінок буде змінено, якщо що. Вам не потрібно знати заздалегідь. Ви можете зателефонувати у цю функцію,

Це дуже добре звучить на обличчі.

Однак мені здається, що виклик idempotent функції «виправити все» поліпшив би надійність системи за рахунок ефективності та, можливо, перекрутить систему, що містить (що, можливо, віддасть перевагу процесам, які ретельно планують та виконують.)

Я не можу сказати, що раніше я ним користувався. Я також не можу знайти джерело його програми в Інтернеті (але я знайшов це, яке стверджує, що базується на ньому.). Я також не можу знайти посилання на нього поза цією статтею (і я вважаю, що мій google-fu є досить хорошим), але я знайшов запис на "Idempotent Capability" на SOApatterns.org .

Чи відома ця ідея іншою назвою?

Що таке шаблон дизайну "Виправити все"? Які його плюси і мінуси?


4
Я підозрюю, що назва також є посиланням на ідею фіксованої точки функції, x = f (x). Незалежно від того, скільки разів ви застосовуєте f до x , результат однаковий. Після досягнення правильного результату повторна обробка правильного результату повертає той самий правильний результат.
9000

7
Зауважте, що кожен може дати будь-яке ім’я будь-що, що хоче, але це не робить його відомим програмним зразком. Idempotency - це відоме саме по собі поняття; це просто схоже на те, що його тут творчо використовують.
Роберт Харві

1
Це нагадує мені про те, як основний цикл подій був реалізований у Mac OS. Це була єдина функція, яка відповідала на будь-яку подію і, як правило, була структурована для тестування стану всіх елементів управління та оновлення всього інтерфейсу користувача за потребою. Дійсно, справді.
Лукас

3
This sounds quite nice on the face of it. Дійсно? Це мені жахливо звучить!
Майкл

3
@Michael Вам не подобаються менеджери пакунків? Вони працюють за тією ж концепцією, лише в меншому масштабі: Позначте, на що ви хочете, щоб система виглядала, запустіть «виправити все», вона встановить / видаляє / оновить у відповідних випадках, але має щось робити, якщо були зміни.
Ізката

Відповіді:


100

Скажімо, у вас є досить складна HTML-сторінка - якщо ви виберете щось в одному спадному меню, може з’явитись інший елемент керування або зміни в третьому елементі управління. Ви можете підійти до цього двома способами:

  1. Напишіть окремий обробник для кожного елемента керування, який реагує на події на цьому контролі, та оновіть інші елементи керування, якщо потрібно.

  2. Напишіть один обробник, який розглядає стан усіх елементів керування на сторінці і просто все виправляє .

Другий дзвінок - "ідентичний", тому що ви можете його дзвонити знову і знову, і елементи керування завжди будуть розташовані належним чином. Тоді як перший дзвінок може мати проблеми, якщо виклик втрачений або повторний, наприклад, якщо один з обробників виконує перемикання.

Логіка другого дзвінка була б дещо незрозумілою, але вам потрібно написати лише один обробник.

І ви завжди можете використовувати обидва рішення, називаючи функцію "виправити все" за потребою "лише для того, щоб бути в безпечній стороні".

Другий підхід особливо приємний, коли стан може надходити з різних джерел, наприклад, із введення користувача та порівняно з рендерінгом. В ASP.NET ця технологія дуже добре поєднується з концепцією постбекбеку, оскільки ви просто запускаєте функцію виправити все, коли ви рендерируете сторінку.

Тепер, коли я згадав про те, що події втрачаються або повторюються і отримують стан з різних джерел, я думаю, що очевидно, наскільки цей підхід добре поєднується з проблемним простором на зразок BitTorrent.

Мінуси? Добре очевидним є те, що є хіт продуктивності, тому що менш ефективно перебирати все за весь час. Але таке рішення, як BitTorrent, оптимізоване для масштабування, а не масштабування, тому це добре для подібних речей. Залежно від проблеми, яку ви намагаєтеся вирішити, вона може не підійти вам.


9
Мені здається, що MVC є типовим для "Виправити все": коли ви модифікуєте модель, потім перемальовуєте погляд з нуля, погляд просто повністю перемальовується, не намагаючись заробити, на які частини потенційно може вплинути дія.
Маттьє М.

3
Це по суті схоже на принцип, що стоїть за такими системами, як Saltstack, Ansible і Nix. З огляду на конфігурацію, теоретично можна привести декілька різноманітних систем в один і той же кінцевий стан.
kojiro

1
@MatthieuM. Реакт , який є досить популярним у розробці інтерфейсу, такий, що, за винятком того, що віртуальний дім відрізняється, тому він лише оновлює реальний дім фактичними змінами
Izkata

2
@Izkata Навіть більше, ніж React, ця відповідь змусила мене думати про Redux.
Кевін

2
Можливо, буде корисно зазначити, що "виправити все" і idempotent - це різні речі: "виправити все", як правило, ідентично (але не потрібно), і idempotent операціям не потрібно все виправляти або навіть мати продуктивність штраф - просто дайте однаковий результат при виконанні двічі.
Ганс-Пітер Штерр

15

Я думаю, що стаття трохи датована, тому що, як я читав, це насправді не є неортодоксальною чи новою ідеєю. Ця ідея подається як окремий зразок, коли вона справді є простою реалізацією спостерігача. Роздумуючи над тим, що я робив у той час, я пам’ятаю, що працював над логікою, щоб сидіти за дещо складним інтерфейсом із низкою різних панелей із взаємозалежними даними. Користувач може змінити значення та / або запустити процедуру оптимізації, і на основі цих дій були створені події, які інтерфейс користувача прослухав би та оновив за потреби. Під час розробки виникла низка питань, де певні панелі не оновлювались, коли слід. Виправлення (перебування в дизайні) полягало в генеруванні подій з інших подій. Зрештою, до того часу, як все працювало правильно, майже кожна зміна призвела до оновлення всіх панелей. Вся складність спроби ізолювати, коли дану панель потрібно оновити, була нанівець. І це все одно не мало значення. Це була фактично передчасна оптимізація. Я б заощадив багато часу і сил, просто зібравши все це в одну подію, яка все оновила.

Існує незліченна кількість систем, розроблених в режимі "виправити все" або оновити все. Подумайте про всі інтерфейси CRUD, які додають / оновлюють рядок, а потім запитують БД. Це не екзотичний підхід, це лише очевидне нерозумне рішення. Ви повинні усвідомити, що в 2003 році це був розпал «зразкової лихоманки». З того, що я міг сказати, люди думали, що називання нових зразків стане їхнім шляхом до слави та багатства. Не зрозумійте мене неправильно, я думаю, що концепція візерунка є надзвичайно корисною для опису рішень у рефераті. Речі просто трохи пішли з рейок. Це прикро, оскільки це створило багато цинізму щодо концепції візерунка загалом. Лише в цьому контексті є сенс говорити про це як про "неортодоксальне" рішення. Це ' s подібний до ортодоксальності навколо контейнерів ORM або DI. Не використовувати їх розглядають як неортодоксальні, хоча люди розробляли програмне забезпечення задовго до того, як ці інструменти існували, і в багатьох випадках ці інструменти є надмірними.

Тож назад до "все виправити". Простий приклад - обчислення засобів. Просте рішення - підсумовувати числа і ділити на кардинальність значень. Якщо ви додасте чи зміните число, ви просто зробите це ще раз, з початку. Ви можете відслідковувати суму та кількість підрахунків чисел, і коли хтось додає число, ви збільшуєте кількість та додаєте її до суми. Тепер ви знову не додаєте всі номери. Якщо ви коли-небудь працювали з Excel з формулою, яка посилається на діапазон і змінила одне значення в цьому діапазоні, у вас є приклад шаблону "виправити все", тобто будь-яка формула, яка має посилання на цей діапазон, буде перерахувати незалежно від того це значення було релевантним (наприклад, використовуючи щось на кшталт sumif ()).

Це не означає, що це не розумний вибір у даному контексті. У середньому прикладі скажемо, що зараз нам потрібно підтримувати оновлення. Тепер мені потрібно якось знати старе значення і лише змінити суму на дельту. Ніщо з цього насправді не таке складне, поки ви не спробуєте зробити це в розподіленому або одночасному середовищі. Тепер вам доведеться вирішувати всі види тернистих проблем з тимчасовим терміном, і ви, ймовірно, в кінцевому підсумку створите велике вузьке місце, яке сповільнить речі набагато більше, ніж перерахунок.

Підсумок тут полягає в тому, що підхід «виправити все» або «оновити все» набагато простіше вийти правильно. Можна зробити більш складний підхід до роботи, але це набагато складніше і, отже, більше шансів на помилку. Крім того, у багатьох контекстах підхід «оновити все» може бути більш ефективним. Наприклад, підходи до копіювання при записі, як правило, повільніші для однопотокових підходів, але коли у вас є велика одночасність, це дозволяє вам уникнути блокування і, таким чином, забезпечити кращу ефективність. В інших випадках це може дозволяти ефективно збирати зміни разом. Тож для більшості проблем ви, мабуть, хочете почати з підходу до оновлення всього, якщо у вас немає конкретної причини, чому ви не можете цього зробити, а потім переймаєтесь тим, що зробите щось складніше, коли у вас виникне потреба.


2
Я впевнений, що Excel має намір лише перерахувати комірки, які залежать від змін, і саме тому існує спосіб запустити всі клітини для перерахунку: superuser.com/questions/448376/… (що, напевно, було б "виправити все" )
Аарон Холл

@AaronHall Якщо це так, це реально погана реалізація. Я регулярно спостерігаю, як вона споживає 100% 7 процесорів протягом 15-30 хвилин, щоб розрахувати, наприклад, 60 000 комірок. Розрахунки не складні. Я часто писав програми Python, які можуть зробити все на аркуші за кілька секунд, включаючи запуск Python. Це була моя найкраща здогадка про те, як це може зайняти так довго. Я думаю, це може бути щось інше. Також в Excel є ряд дійсно старих помилок, які можуть бути причиною цієї функції.
JimmyJames

1
@AaronHall з цим користувачем також можливо, що автоматичний обчислення було відключено на аркуші. Я часто роблю це у великих робочих книгах, тому що у мене немає часу, щоб запастися щоразу, коли я натискаю на Enter.
JimmyJames

@AaronHall Я подумав ще трохи, і ти маєш точку. Мої припущення, ймовірно, занадто широкі. Я оновив відповідь, щоб я більше зосередився на тому, в чому я впевнений більше.
JimmyJames

2
@JimmyJames: Точка, яку я хотів зробити, полягає в тому, що найкращий підхід може сильно відрізнятися залежно від обставин, а "виправити все" можна підрозділити на "охоче виправити все на кожній окремій зміні" і "ліниво виправити все після завершення всіх змін ".
supercat

4

Не впевнений, що це «модель дизайну», але я класифікував би такий тип поведінки як конфігурацію кінцевого стану або конфігурацію потрібного стану , в дусі DSC Puppet, Chef або Powershell.

Ці рішення, як правило, діють на рівні системного управління, а не на рівні бізнес-логіки, як описано в питанні, але це фактично та ж парадигма, і хоча такі інструменти, як правило, мають декларативний характер, ті ж принципи можуть застосовуватися і в процедурному коді, або в сценаріях.


1

Я в основному використовував це в інтерфейсах користувача. Приємно, що ви пишете це один раз, і він обробляє все, від найпростішого до найважчого випадку однаково добре (наприклад, якщо користувач обертає екран, або на ноутбуці / робочому столі, якщо користувач змінює розмір вікна, і практично все змінюється ).

Причин для занепокоєння за ефективність не так вже й багато. В інтерфейсі користувача дорогі речі - це такі речі, як перемальовування предмета, який перемістили. Розрахунок, куди йде кожен предмет і наскільки він великий, зазвичай досить швидкий. Все, що вам потрібно переконатися, - це те, що коли ви виявите, що предмет повинен залишатися там, де він належить, жодного коду не виконується для його переміщення. Справжні зміни - це все, що вам довелося зробити у будь-якому випадку.


0

Звучить як принципи реактивного програмування. "Виправити все" дивиться на поточний стан "основного" та розповсюджує все інше, на що має вплинути - "обчислені стани". Якщо ви оптимізуєте цю деривацію, вона може досягти високої ефективності, a-la React, якщо зроблено наївно, продуктивність може бути не оптимальною, хоча вона все ще може бути досить швидкою.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.