На протяжении всего курса, в практической части, мы разрабатывали сценарии, в которых происходило только добавление сущностей. Добавление это наиболее простая операция из всех возможных, потому что в ней отсутствует (почти) изменяемость данных. Но большинство сценариев в реальной жизни обычно связано с изменением:
- Обновление расписания
- Возврат билета
- Удаление кинозала
- Изменение конфигурации кинозала
И вот тут начинаются настоящие проблемы. Попробуйте ответить себе на следующие вопросы:
- Можно ли безопасно удалить из системы кинозал?
- Можно ли безопасно изменить конфигурацию зала в любой момент времени?
- Простая ли операция возврата билета?
На все эти (и многие другие) вопросы ответ: нет. Возврат билета затрагивает множество связанных сущностей. Например, в зале нужно освободить место для возможности перепродажи. Удаление кинозала из системы приведёт к тому, что все предыдущие просмотры фильмов в этом зале станут не консистентными, мы потеряем историю операций. Изменение конфигурации зала приведёт к поломке старых покупок. Удаление сеанса связано с возвратом билетов, а эта операция, в свою очередь, порождает цепочку других изменений.
Итак, чем же нам грозит изменяемость:
- Сложное обновление связанных сущностей;
- Отсутствие истории;
- Рассинхронизация;
- Повреждение старых связей.
В связи с этим хочется сформулировать первое правило изменяемости:
Не изменяй!
И действительно, на практике часто можно и нужно проектировать систему так,
чтобы изменяющие действия превращались в append only
. Проницательный читатель вероятно
заметил, что эта идея очень сильно коррелирует с главным принципом функционального программирования,
а именно отсутствием изменений. Это действительно так, проблема изменяемого состояния – это
не проблема кода и программирования, это особенность физической реальности. И на
практике гораздо лучше пытаться уйти от изменений, чем пытаться создать систему,
которая консистентно обновляет все нужные связи, что в общем случае невозможно и рождает
очень много случайной сложности.
Разберём несколько простых примеров.
Изменение конфигурации зала
В такой ситуации правильно создать новый зал с другой конфигурацией, а предыдущий архивировать.
То есть перевести конечный автомат жизненного цикла зала в состояние archived
. Соответственно,
все старые данные остаются в согласованном виде. У нас появляется история, и мы можем отследить
момент, в который произошла физическая перепланировка зала.
Возврат билетов
При возврате билета, правильно не удалять записи о том, что был приход денег. Правильно создать
новую запись, в которой отражается расход. Кроме стандартных плюсов, мы получаем возможность
проводить глубокий бизнес-анализ ситуации с возвратами. Сам билет также может быть переведён
в состояние (везде конечные автоматы) возвращён
.
Current
Ещё один подход для ухода от изменений связан с тем, что вводится понятие current
. Например,
на Хекслете есть понятие "Упражнение". Это задание, которое выполняется в нашей ide
. Перед
тем как новая версия упражнения попадает на сайт, она проходит этап сборки и верификации.
На этом этапе происходит упаковка всех зависимостей и кода упражнения в Docker-образ, а также
выполнение различных проверок на работоспособность, в первую очередь, конечно же, тестов.
Исправлять упражнение ни в коем случае нельзя. Потому что всегда есть пользователи, которые
проходят старую версию упражнения. И если бы мы делали изменение текущей версии, то у части
пользователей упражнение перестало бы работать. Выход из ситуации очень простой. Мы разделяем понятия
Exercise
и Exercise::Build
. И после того, как успешно пройдёт новый Exercise::Build
,
в Exercise
будет записан Current Exercise Build
. После этого все новые старты будут
использовать эту сборку, а старые — ту, которая была актуальна на момент старта. Для функционирования
такого механизма нужно всегда записывать Current Exercise Build
в объект, представляющий
собой запущенную практику, тогда всё будет работать даже если появится новая сборка.
На практике это очень простая тактика. Хекслет использует её просто повсеместно, и, таким образом, мы сильно снижаем затраты на синхронизацию данных.
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
- Статья «Как учиться и справляться с негативными мыслями»
- Статья «Ловушки обучения»
- Статья «Сложные простые задачи по программированию»
- Вебинар «Как самостоятельно учиться»
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.