Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Изменяемость JS: Предметно-ориентированное проектирование

На протяжении всего курса, в практической части, мы разрабатывали сценарии, в которых происходило только добавление сущностей. Добавление это наиболее простая операция из всех возможных, потому что в ней отсутствует (почти) изменяемость данных. Но большинство сценариев в реальной жизни обычно связано с изменением:

  • Обновление расписания
  • Возврат билета
  • Удаление кинозала
  • Изменение конфигурации кинозала

И вот тут начинаются настоящие проблемы. Попробуйте ответить себе на следующие вопросы:

  • Можно ли безопасно удалить из системы кинозал?
  • Можно ли безопасно изменить конфигурацию зала в любой момент времени?
  • Простая ли операция возврата билета?

На все эти (и многие другие) вопросы ответ: нет. Возврат билета затрагивает множество связанных сущностей. Например, в зале нужно освободить место для возможности перепродажи. Удаление кинозала из системы приведёт к тому, что все предыдущие просмотры фильмов в этом зале станут не консистентными, мы потеряем историю операций. Изменение конфигурации зала приведёт к поломке старых покупок. Удаление сеанса связано с возвратом билетов, а эта операция, в свою очередь, порождает цепочку других изменений.

Итак, чем же нам грозит изменяемость:

  • Сложное обновление связанных сущностей;
  • Отсутствие истории;
  • Рассинхронизация;
  • Повреждение старых связей.

В связи с этим хочется сформулировать первое правило изменяемости:

Не изменяй!

И действительно, на практике часто можно и нужно проектировать систему так, чтобы изменяющие действия превращались в append only. Проницательный читатель вероятно заметил, что эта идея очень сильно коррелирует с главным принципом функционального программирования, а именно отсутствием изменений. Это действительно так, проблема изменяемого состояния – это не проблема кода и программирования, это особенность физической реальности. И на практике гораздо лучше пытаться уйти от изменений, чем пытаться создать систему, которая консистентно обновляет все нужные связи, что в общем случае невозможно и рождает очень много случайной сложности.

Разберём несколько простых примеров.

Изменение конфигурации зала

В такой ситуации правильно создать новый зал с другой конфигурацией, а предыдущий архивировать. То есть перевести конечный автомат жизненного цикла зала в состояние archived. Соответственно, все старые данные остаются в согласованном виде. У нас появляется история, и мы можем отследить момент, в который произошла физическая перепланировка зала.

Возврат билетов

При возврате билета, правильно не удалять записи о том, что был приход денег. Правильно создать новую запись, в которой отражается расход. Кроме стандартных плюсов, мы получаем возможность проводить глубокий бизнес-анализ ситуации с возвратами. Сам билет также может быть переведён в состояние (везде конечные автоматы) возвращён.

Current

Ещё один подход для ухода от изменений связан с тем, что вводится понятие current. Например, на Хекслете есть понятие "Упражнение". Это задание, которое выполняется в нашей ide. Перед тем как новая версия упражнения попадает на сайт, она проходит этап сборки и верификации. На этом этапе происходит упаковка всех зависимостей и кода упражнения в Docker-образ, а также выполнение различных проверок на работоспособность, в первую очередь, конечно же, тестов.

Исправлять упражнение ни в коем случае нельзя. Потому что всегда есть пользователи, которые проходят старую версию упражнения. И если бы мы делали изменение текущей версии, то у части пользователей упражнение перестало бы работать. Выход из ситуации очень простой. Мы разделяем понятия Exercise и Exercise::Build. И после того, как успешно пройдёт новый Exercise::Build, в Exercise будет записан Current Exercise Build. После этого все новые старты будут использовать эту сборку, а старые — ту, которая была актуальна на момент старта. Для функционирования такого механизма нужно всегда записывать Current Exercise Build в объект, представляющий собой запущенную практику, тогда всё будет работать даже если появится новая сборка.

На практике это очень простая тактика. Хекслет использует её просто повсеместно, и, таким образом, мы сильно снижаем затраты на синхронизацию данных.


Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»