Метод: оглавление против системы
Читать инженерную книгу подряд и надеяться, что «отложится», — способ потратить неделю без следа. Проход устроен иначе. Берём полное оглавление, идём по темам и на каждой отвечаем: что у нас на этом месте построено, чем оно уже ломалось, что книга предлагает взамен. Тема без ответа закрывается пометкой «не про нас», тема с инцидентом и датой становится строкой в списке дыр. Наложение шло на боевые системы — хранилище на файлах, API админки, конвейер разбора переписки, параллельные сессии, выкладку через автоматику, — и дыра без указания «чем стреляла» в список не попадала: иначе получается не разбор, а конспект. Побочный эффект вышел ценнее ожидаемого: неприменимого оказалось больше, чем находок, а соблазн «книга умная, значит надо внедрить» — крупный источник лишней работы.
Что дала каждая книга и что мы отказались брать
| Источник | Что нашёл у нас | Что не берём |
|---|---|---|
| Клеппман, «Designing Data-Intensive Applications» 12 глав | четыре дыры из семи: единственная копия данных, хранилище без схемы, запись без блокировок, слепота к чужим сбоям | партиционирование не нужно при наших объёмах; пригодилось одно: разбиение архива переписки на 27 кусков названо уже правильно |
| Эванс, «Domain-Driven Design» 17 глав и справочник паттернов на 52 страницы | язык домена не собран в один артефакт; правила тарификации размазаны по калькуляторам, серверному коду и заметкам | крупномасштабные структуры — для нашего размера хватает границ контекстов |
| Ричардсон, «Microservices Patterns» 13 глав, 44 паттерна | ноль автотестов у API, ворочающего деньгами; отсутствие проверки живости боевого контура | дробление на микросервисы — книга сама предостерегает: это про масштаб команды |
| Петцольд, «Code», 2-е издание 28 глав | новых дыр ни одной, зато объяснение всех наших аварий с текстом и повод превратить обходной приём в канон | двадцать глав общего образования: сумматоры, триггеры, регистры — не проецируются |
| Сюй, «System Design Interview», том 1 16 глав | коллизии идентификаторов при параллельной записи, три требования к цепочке уведомлений, навык оценки на салфетке | согласованное хеширование, сокращатель ссылок, ленты и хранилища крупных площадок — половина оглавления |
| Курс «Distributed Systems» того же автора 8 лекций, 91 страница | воскрешение удалённых записей при слиянии копий, тихая потеря правки в режиме «побеждает поздний», формула идемпотентности | консенсус, кворумы, устойчивость к злонамеренным узлам — для кластеров с автоматическим переключением |
Строка про Петцольда показывает нормальную пропорцию. Из двадцати восьми глав стреляет одна: про переход от таблицы символов к универсальной кодировке. Зато после неё правило стало окончательным и записано каноном: всё новое пишем в универсальной кодировке без служебного маркера в начале файла, чужое читаем с явным указанием кодировки и падением при ошибке — молчаливая подмена непонятого символа запрещена. Одна глава на книгу — честная цена.
Две идеи, которые изменили приоритет работ
Первая — оценка на обратной стороне салфетки, единственная глава Сюя, присвоенная как навык. Приём занимает минуту и закрывает споры, которые иначе тянутся неделями. Наш пример: в архиве переписки 137 664 сообщения примерно за два года, значит около 190 в сутки и около 8 в час. Вывод следует мгновенно: очереди, масштабирование и отдельное железо конвейеру не нужны — нужен слой знаний, то есть качество ответа, а не пропускная способность. «Не потянет» почти всегда означает, что порядок величины никто не посчитал.
Вторая пришла из главы Эванса про дистилляцию и звучит неудобно: усилия высшего качества имеет смысл вкладывать только в ядро домена, остальное — по остаточному принципу.
- Ядро — диспетчеризация, сверка расчётов, знание о тарифах и клиентах. Того, что здесь накоплено, у конкурентов по нише нет; проверяли по тринадцати.
- Поддержка — сайты и продвижение: кормят ядро заявками, но полировка тут не приносит того, что приносит час в ядре.
- Общее — бухгалтерия, хостинг, рутина: берётся готовым, улучшается только когда мешает.
Из справочника паттернов пришло сигнальное правило к разделению — прямой ответ на вопрос «когда дёргать владельца». Правишь ядро (тарифы, сверку, правила идентичности) — согласование обязательно; правишь поддержку — полная автономия. Раньше граница существовала интуитивно и работала через раз в обе стороны: то лишний вопрос, то самовольная правка там, где нельзя.
Предохранитель от перфекционизма — оттуда же. «Плохо сидящая структура хуже, чем никакой», и не надо стремиться к всеохватности: минимальный набор, решающий уже возникшие проблемы. Применили к самому разбору — внедряем только семь дыр из таблицы, прочие паттерны не тащим.
Что закрыто и что нет
| Дыра | Статус на конец разбора |
|---|---|
| Единственная копия репозиториев: 14 из 16 без внешней копии | в работе |
| Сбои прода и сервера находит человек постфактум | закрыта: почасовая проверка живости по пяти целям |
| Хранилище без схемы и без версии формата | открыта — единственная из семи |
| Запись файлов без атомарности и блокировок | закрыта: восемь оставшихся точек записи |
| Термины домена разбросаны по трём десяткам заметок | закрыта: единый словарь домена |
| Ноль автотестов у API админки, ворочающего деньгами | закрыта: 15 проверок на локальном сервере |
| Идентификаторы при параллельной записи | закрыта: аудит всех генераторов |
| Итог | 5 закрыто · 1 в работе · 1 открыта |
Одна строка менялась дважды, и об этом честнее рассказать, чем умолчать. Дыру про запись без атомарности разбор сначала записал как полностью открытую — и ошибся: измерение шло по локальной копии, отставшей от основного состояния на 955 коммитов. В актуальном коде пять точек записи уже были атомарными, пересчёт сократил работу до восьми оставшихся файлов. Урок общий: аудит собственной системы врёт так же, как любой прибор, меряющий устаревшую копию.