Владение данными и состоянием — Примеры
Пример 1 — Два сервиса пишут в одну таблицу
Сервис заказов и сервис отчётов обновляют одну таблицу, и цифра, исправленная одним, молча перезаписывается другим. Найдите нарушенное правило владения, затем решите, кто пишет.
orders(total, status) одна общая схема
сервис заказов: вставляет заказы, обновляет статус
сервис отчётов: обновляет total, когда исправляет цифру
на прошлой неделе: ночная синхронизация заказов дважды перезаписала исправление
Решение
владелец: сервис заказов единственный писатель; инварианты живут здесь
читатель: сервис отчётов держит собственную модель чтения, заказы не пишет
сервис заказов --событие--> сервис отчётов --проектор--> reporting.orders_view
С одним писателем правила о том, какой может быть сумма заказа, существуют ровно в одном месте, а об остальном можно рассуждать как о потребителе. Два писателя превращают каждый инвариант в договорённость между командами — чем перезаписанное исправление и было. Копии читателя позволено отставать, но менять источник она не вправе. Если сервису отчётов действительно нужна собственная исправленная цифра, ей место в его модели чтения, помеченной как производная и пересобираемая, а не в таблице владельца.
Пример 2 — Чтение, противоречащее только что сделанной записи
Пользователь переименовывает проект, запись проходит успешно, а следующая страница всё ещё показывает старое имя: объясните, какое окно это вызвало, и выберите, что должно делать чтение.
запись -> владелец проектов (зафиксирована)
чтение -> модель чтения поиска (построена минутами раньше)
итог -> переименования там ещё нет
Решение
// чтения, которым нужна свежесть, идут к владельцу
const project = await projects.get(id);
// чтения, терпящие запаздывание, используют копию, и это сказано в одном месте
const results = await search.query(term); // «достаточно свежего» здесь хватает
Как только копия существует, она устаревает с момента создания, и проектный вопрос не в том, происходит ли это, а в том, что система делает во время окна. Сформулируйте требование: переименование, которое пользователь только что сделал, должно быть видно ему самому, а поисковый индекс, отстающий на секунду-две, вполне приемлем. Тогда чтения распадаются на два пути вместо одного расплывчатого, а класс запутанных сообщений превращается в задокументированное свойство с местом для номеров версий, повторных попыток или маршрута чтения собственных записей.