Кожного разу, коли я можу, я намагаюся обмежити спілкування між об'єктами моделлю "запит і відповідь". Існує мається на увазі часткове впорядкування об'єктів у моїй програмі таким чином, що між будь-якими двома об'єктами A і B може бути спосіб, щоб A прямо чи опосередковано викликав метод B або B, щоб прямо чи опосередковано викликати метод A , але А і В ніколи не можна взаємно називати методи один одного. Іноді, звичайно, хочеться мати зворотній зв'язок з абонентом того чи іншого методу. Мені подобається це робити пару способів, і жоден з них не є зворотним.
Один із способів полягає у включенні додаткової інформації у зворотне значення виклику методу, що означає, що клієнтський код повинен вирішити, що робити з ним після того, як процедура поверне йому контроль.
Інший спосіб - викликати взаємний дочірній предмет. Тобто, якщо A викликає метод на B, а B потрібно передавати деяку інформацію A, B називає метод на C, де A і B можуть обидва викликати C, але C не може викликати A або B. відповідальний за отримання інформації від C після того, як B повертає контроль до А. Зауважте, що це насправді принципово не відрізняється від першого запропонованого мною способу. Об'єкт A все ще може отримати інформацію лише із поверненого значення; жоден з методів об'єкта A не викликається B або C. Варіантом цього фокусу є передача C як параметра методу, але обмеження щодо відношення C до A і B все ще застосовуються.
Тепер важливим питанням є те, чому я наполягаю робити такі дії. Є три основні причини:
- Це тримає мої предмети більш вільно з'єднані. Мої об'єкти можуть інкапсулювати інші об'єкти, але вони ніколи не залежатимуть від контексту виклику, а контекст ніколи не залежатиме від інкапсульованих об'єктів.
- Це міг міркувати про мій потік управління. Приємно бачити, що єдиний код, який може змінити внутрішній стан
self
при виконанні методу, - це один метод, а не інший. Це той самий вид міркувань, який може призвести до нанесення мутексів на паралельні об'єкти.
- Він захищає інваріантів на інкапсульованих даних моїх об’єктів. Публічні методи можуть залежати від інваріантів, і ці інваріанти можуть бути порушені, якщо один метод можна викликати зовні, а інший вже виконувати.
Я не проти всіх застосувань зворотних дзвінків. Відповідно до моєї політики щодо того, щоб ніколи не "викликати абонента", якщо об'єкт A викликає метод на B і передає йому зворотний виклик, зворотний виклик може не змінити внутрішній стан A, і це включає об'єкти, інкапсульовані A і об'єкти в контексті А. Іншими словами, зворотний виклик може викликати лише методи на об'єктах, наданих йому В. Зворотний виклик, по суті, знаходиться під тими ж обмеженнями, що і B.
Останнім нескінченним кінцевим завданням є те, що я дозволять викликати будь-яку чисту функцію, незалежно від цього часткового впорядкування, про який я говорив. Чисті функції дещо відрізняються від методів тим, що вони не можуть змінюватись або залежати від стану, що змінюється, або побічних ефектів, тому не варто турбуватися про те, що вони заплутують питання.