Одна идея этого урока: у каждого факта в системе должно быть ровно одно место, где он хранится по-настоящему. Всё остальное – производные копии.
Знакомая ситуация
На лендинге школы написано «1240 учеников». В админке – 1174. Телеграм-бот в приветствии говорит «нас уже 1310». Просишь агента разобраться – и выясняется: лендинг обновляли вручную в марте, админка считает по базе, а бот хранит свой счётчик и увеличивает его на каждого подписчика, включая отписавшихся.
Один факт – «сколько у нас учеников» – живёт в трёх местах, и все три врут по-своему. Никто не решил, где этот факт хранится по-настоящему.
У каждого факта в системе должен быть ровно один владелец – единственный источник правды (single source of truth, SSOT). Все остальные места, где этот факт встречается, – производные копии, которые можно стереть и пересчитать заново.
Состояние и его копии – простыми словами
Состояние (state) – это всё, что система помнит: кто оплатил, у кого какой доступ, сколько учеников в потоке. Проблемы начинаются, когда одно и то же знание оказывается записано в нескольких местах: в базе, в кэше, в настройках бота, руками на лендинге.
Копии опасны не сами по себе, а тем, что расходятся: обновил в одном месте – забыл в другом. С этого момента система «помнит» две разные версии реальности, и каждый экран показывает свою.
1
Источник правды source of truthМесто, где факт живёт по-настоящему. Число учеников потока – это записи о доступах в базе. Не счётчик, не текст на лендинге – сами записи.
2
Производные данные derived dataВсё, что вычислено из источника: счётчик на лендинге, список в отчёте, цифра в боте. Тест простой: можно стереть и пересчитать без потерь? Значит, производное.
3
Кэш cacheЧастный случай производных данных: копия, которую держат рядом ради скорости. Кэш имеет право устаревать – но должен знать, когда обновиться, и никогда не становится источником.
Отсюда главный вопрос сеньора о любых данных: «кто владелец этого факта?» (who owns this fact?). Один факт – один владелец. Если владельцев два, то правды нет ни у кого.
Ловушка синхронизации
Когда копии расходятся, первый рефлекс – «давай синхронизировать»: пусть бот раз в час подтягивает число из базы, а лендинг – из бота. Заметь, что произошло: к трём копиям добавился механизм их согласования, который сам может сломаться. Сложность выросла, причина осталась.
Решение сеньора скучнее и сильнее: убрать лишние копии. Лендинг и бот не хранят число учеников – они каждый раз спрашивают его у владельца (или у кэша, который честно объявлен производным). Факт один, владелец один, расходиться нечему.
Как думают три уровня
Джун · копирует туда, где удобноНужна цифра на лендинге – вписал на лендинг. Нужна в боте – завёл счётчик в боте. Каждая копия появляется по месту надобности, без хозяина. Расхождения обнаруживают ученики.
Мидл · замечает рассинхрон и пишет синхронизациюВидит, что цифры разошлись, и строит мостики: скрипты сверки, обновление по расписанию, «пересчитать всё» по кнопке. Копии остаются, к ним добавляется машинерия согласования – ещё один слой сложности, который тоже ломается.
Сеньор · устраняет копию или объявляет её производнойСначала спрашивает: «кто владелец факта?» Потом либо убирает копию совсем, либо явно помечает: это кэш, вот его источник, вот правило обновления. Правда одна, всё остальное пересчитываемо.
Проверь себя
1. Email ученика хранится в базе школы, в списке рассылки и в CRM. Ученик сменил адрес. Что здесь главная проблема с точки зрения сеньора?
Ручная работа – мелочь, а вот отсутствие владельца – системная беда: рано или поздно адрес обновят в одном месте из трёх, и никто не узнает, какой из них настоящий. Решение – назначить владельца (например, базу школы), а рассылка и CRM пусть получают адрес от него. Держать данные в нескольких системах можно – если копии объявлены производными.
2. Агент предлагает: «Чтобы страница потока открывалась быстрее, буду хранить число мест в потоке прямо на странице и обновлять его при каждой продаже». Что тут скажет сеньор?
Кэшировать можно и часто нужно – запрет «любого дублирования» парализовал бы работу. Важно другое: копия должна быть честно объявлена производной, с понятным источником и способом пересчёта. Вариант «и так будет точным» – самообман: возвраты, ручные правки в админке и сбои обязательно случатся, а правила пересчёта нет.
3. Цена курса разошлась: на лендинге одна, в боте другая. Агент предлагает скрипт, который раз в сутки сверяет цены и шлёт тебе отчёт о расхождениях. Что не так с этим планом?
Это мышление мидла: рассинхрон замечен, и к нему пристроен механизм согласования. Частота сверки не спасает – хоть каждую минуту, копии всё равно ничьи, а машинерии стало больше. Решение сеньора: цена хранится в одном месте, лендинг и бот берут её оттуда. Тогда сверять нечего.
Что говорить агенту уже сегодня
Про любой факт: кто владелец этого факта? где он хранится по-настоящему, а где – копии?
Аудит проекта: найди данные, которые хранятся в нескольких местах, и предложи для каждого единственный источник правды
При добавлении кэша: это кэш: укажи его источник и правило обновления; при расхождении прав всегда источник
Вместо синхронизации: не пиши синхронизацию копий – предложи, как убрать саму копию или сделать её пересчитываемой из источника