Перейти к содержанию

Модель данных подписчика

Подтверждение добавило историю, которую неудобно хранить одним флагом в форме. Теперь разделим контакт, подписку, предпочтения и события. Результатом урока станет срез DATA-01 с четырьмя синтетическими читателями. По нему можно понять, какое состояние актуально и почему часть контактов не участвует в подборке.

В lesson-04 архива серии находится полный локальный subscribers.json. Адреса на professorweb.example вымышлены; записи не импортированы из аккаунта. R001 и R003 продолжают прежние сценарии, R002 и R004 добавляются как явно заданные учебные случаи. Никакие реальные регистрации не совершались.

Разные сущности

Контакт хранит способ связи и устойчивый ID. Подписка хранит цель, обещание и состояние. Предпочтения описывают темы и частоту. События сохраняют допустимые переходы. Запрет отправки отделён от этих объектов: он может блокировать сообщение независимо от желания получать тему. Такое разделение позволяет не путать исправление адреса, изменение интереса и остановку коммуникации.

Для R001 адрес reader001@professorweb.example, цель lesson_updates, состояние confirmed, тема web, частота weekly. У R002 тема seo и частота monthly; подтверждение задано отдельным синтетическим событием при добавлении случая. R003 остаётся expired. R004 имеет unsubscribed после учебной остановки. Пять произвольных флагов не заменяют смысл этих отношений.

ID Подписка Темы Частота Запрет
R001 confirmed web weekly Нет в модели
R002 confirmed seo monthly Нет в модели
R003 expired web weekly Подборка недопустима
R004 unsubscribed Неизвестны Не применяется Остановлено

«Нет запрета в модели» отличается от доказанного отсутствия всех внешних проблем. Мы не проверяли доставку адресов и не знаем их почтовые системы. Данные описывают только условия учебного процесса. У неизвестных тем R004 стоит null, а не пустой список с ложным смыслом «человек выбрал ничего». Неизвестное, отсутствующее и явно отрицательное значение нужно различать.

История и текущий срез

Текущее состояние удобно для отбора, история — для объяснения основания. У R001 события заявки и подтверждения связаны с PROMISE-v1. У R004 есть событие остановки. При обновлении нельзя удалить это событие и оставить только адрес: будущая операция потеряет причину исключения. При этом история не должна хранить бесконечные лишние сведения без задачи; политика хранения определяется отдельно.

В нашем файле события имеют scenario_at и origin: synthetic. Они не похожи на экспорт реальной почтовой платформы и не содержат выдуманные ID отправки. Поле message_state отсутствует, потому что письма ещё не создавались. Когда появится конкретная коммуникация, её запись будет связана с подпиской, но не заменит её состояние. Это предотвращает вывод «письмо подготовлено, значит согласие есть».

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

Адрес может измениться. В модели это отдельное действие контакта, после которого требуется подтверждение нового способа связи. Предпочтения могут сохраниться, но статус доступности нового адреса не наследуется автоматически. Если просто заменить строку у R001, старое подтверждение станет выглядеть основанием для нового ящика. Явные объекты помогают заметить эту ошибку.

Правило отбора

Срез даёт два потенциально активных контакта, но они не обязательно получают один выпуск. Для материала web кандидат R001; R002 выбрал seo и другую частоту. Для общей месячной подборки условий будет больше. R003 и R004 исключаются до проверки интересов. Отбор должен сначала проверять допустимость, затем релевантность, а не наоборот.

Запрет отправки имеет причину и область. В будущем постоянная ошибка адреса может остановить весь способ связи, а отписка от темы — только выбранную подборку. В нашей модели R004 остановил все lesson_updates. Мы не распространяем запрет автоматически на необходимый ответ по отдельному обращению: у такого ответа другое назначение, которое нужно объяснить отдельно. Юридическую допустимость настоящих сообщений нельзя вывести только из структуры файла.

У данных есть версия схемы 1 и дата учебного среза. Если позднее добавится поле часового пояса, неизвестное значение не заменяется догадкой по адресу. Если появятся наблюдаемые действия на сайте, они не становятся автоматически заявленными интересами. Каждое значение должно иметь источник: выбор, событие или редакционная гипотеза. В этом уроке используем только явные синтетические предпочтения.

Не экспортируйте в скачиваемый пример реальные контакты. Здесь файлы полностью учебные и не связаны с рабочим аккаунтом. Это особенно важно для сайта с открытыми приложениями к урокам: архив доступен читателю и не должен становиться копией внутренней адресной книги. Идентификаторы R001 не являются настоящими пользователями ProfessorWeb и не позволяют связать их с личностью.

Предметная сверка

Проверьте запись R004: можно ли понять, почему она исключена? Да, состояние unsubscribed и событие остановки относятся к той же цели. Проверьте R002: можно ли объяснить, почему он не получает web-выпуск? Да, выбранная тема другая. Если оба случая записаны как «неактивен», редакция потеряет различие и не сможет предложить правильный следующий шаг.

В after.json добавляется DATA-01, а полный срез лежит отдельным приложением. Предыдущие решения сохраняются для истории; актуальная модель контактов берётся из нового среза. Это не исполнение миграции базы. Программы, серверы и интеграции отсутствуют, поэтому все результаты являются ожидаемыми состояниями документов.

Измените одну тему R001 с web на seo, сохранив подтверждение и цель. Состояние подписки не должно вернуться в pending только из-за допустимой смены предпочтения. Но изменение адреса потребовало бы другого перехода. Так разделённая модель делает каждую операцию понятной. Следующая глава построит сегменты по этим известным данным, не придумывая интересы читателей.