Технари любят точность — особенно программисты, живущие в мире нулей и единиц. Они привыкли работать с двоичными решениями: один/ноль, истина/ложь, да/нет. Всё четко и последовательно, от неожиданностей защищают ограничения внешних ключей, атомарные транзакции и контрольные суммы.
К сожалению, реальный мир не столь упорядочен. Клиенты оформляют заказы, а через секунду отменяют их. Чеки отклоняются, письма теряются, платежи задерживаются, а обещания нарушаются. Ошибки ввода данных происходят чаще, чем нам хотелось бы. Пользователи предпочитают «плоские» («shallow») интерфейсы, которые предоставляют одновременный доступ ко многим функциям, а не длинный и узкий коридор «процесса» ввода данных, который проще реализуется и кажется многим разработчикам более «логичным». Ходом выполнения программы управляет уже не стек вызовов, а пользователь.
Распределенные системы только усугубляют положение, потому что в игру вступает уйма новых несогласованностей. Службы бывают недоступны, изменяются без предварительного уведомления и не предоставляют транзакционных гарантий. При выполнении приложения на тысячах компьютеров вопрос уже не в том, произойдет ли сбой, а в том, когда он произойдет. Такие системы обладают слабой связанностью (loosely coupled), асинхронностью и параллелизмом и не соответствуют традиционной транзакционной семантике… Не желаете принять синюю таблетку?!
Дивный новый мир компьютерных технологий трещит по швам — так что же нам делать? Как это часто бывает, осознание проблемы становится первым важным шагом к ее решению.
Распрощайтесь со старой доброй детерминированной архитектурой стека вызовов, в которой вы сами определяли, что, когда и в каком порядке происходит. Вместо этого будьте готовы реагировать на события в любое время и в любом порядке, восстанавливая состояние системы по мере необходимости. Выдавайте асинхронные запросы параллельно вместо последовательного вызова методов. Чтобы избежать полного хаоса, моделируйте свое приложение, используя управляемые событиями цепочки процессов или модели состояний. Нейтрализуйте ошибки посредством коррекции, повторных попыток или тестовых операций.
Звучит слишком устрашающе? Вы на такое не рассчитывали? К счастью, в реальном мире с похожими проблемами имеют дело уже давно: задержки писем, нарушенные обещания, перепутанные сообщения, платежи не на те счета — примеров не счесть. Соответственно люди вынуждены посылать письма заново, списывать некорректные заказы и игнорировать напоминания об уже произведенных платежах. Не вините реальный мир в своих проблемах — лучше используйте его, чтобы подсмотреть решения. В конце концов, Starbucks тоже не использует протокол двухфазной фиксации.[29] Добро пожаловать в реальный мир!
Грегор Хоп (Gregor Hohpe) — архитектор ПО в компании Google, Inc. Грегор является общепризнанным экспертом в области асинхронных архитектур для систем обмена сообщениями и сервис-ориентированных архитектур. Он является соавтором книги «Enterprise Integration Patterns»[30] (Addison-Wesley Professional), регулярно выступает на технических конференциях по всему миру.