верхняя ступень ревью задана тестом, а не списком
«Идентичность, слияние, разбор» пришли из одного проекта, и в общем виде формулировка не читалась: вопрос «как применить это к моему проекту» не имел ответа в тексте. Теперь класс задан тремя условиями, не зависящими ни от домена, ни от языка: вариантов несколько и оба защитимы; спека между ними не выбирает; неверный выбор не падает, а даёт правдоподобный результат и молча меняет смысл данных. Отрицательный тест сильнее трёх положительных: то, что красит гейт, роняет запрос или ломает тест, в класс не входит — это ловят проходы дешевле. Отсюда же и причина, по которой класс достался самому дорогому проходу: независимая реализация выберет другой вариант, и дифф между вариантами и есть находка; там, где вариант один, она совпадёт с существующей. Три слова остались как три места, где такие правила водятся — граница, где данные входят или встречаются: состав ключа и нормализация перед сравнением; победитель конфликта и тай-брейк при равенстве; границы токенов и неоднозначный вход. Проект перечисляет свои места в docs/review.md, и перечень производен от теста, а не заменяет его. Две оговорки, без которых правило вырождается: - триггер — новое или изменённое по существу правило, а не код рядом с ним; иначе проект, чей домен и состоит из таких правил, всегда в deep; - проект, где такого класса нет вовсе, deep не запускает никогда, и это законное состояние, а не недонастройка. review-reimpl получил тот же тест и право сказать первой строкой, что позвали не на его класс, — строкой в границы покрытия, а не отказом работать. DECISIONS 18, XXX и следствия 76–77. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -177,8 +177,8 @@ charter'а, а модель потом двигает калибровка, и
|
||||
|
||||
Правило выбора профиля — **по факту изменения, не по ощущению важности**:
|
||||
|
||||
- трогается правило, определяющее **идентичность, слияние или разбор** данных →
|
||||
`deep`;
|
||||
- вводится или меняется по существу правило, определяющее **идентичность, слияние
|
||||
или разбор** данных (тест — ниже) → `deep`;
|
||||
- иначе изменение вводит **новое понятие или структурную единицу**: новый пакет
|
||||
или слой, новая точка входа, второй способ делать то, что уже делается, перенос
|
||||
ответственности между узлами → `wide`;
|
||||
@@ -215,6 +215,63 @@ charter'а, а модель потом двигает калибровка, и
|
||||
правда архитектурное (публичный SDK, чужие потребители), там же поднимает его до
|
||||
`wide` — и это уточнение, а не возврат прежнего умолчания.
|
||||
|
||||
### Идентичность, слияние, разбор — тест, а не список
|
||||
|
||||
Три слова названы затем, чтобы верхнюю ступень нельзя было выбрать по ощущению.
|
||||
Читаются они **тестом**, применимым к любому проекту на любом языке; домен, стек
|
||||
и имена узлов в тест не входят.
|
||||
|
||||
Правило принадлежит этому классу, если сходятся **три условия**:
|
||||
|
||||
1. **вариантов несколько** — два добросовестных исполнителя выберут разное, и оба
|
||||
решения защитимы;
|
||||
2. **спека между ними не выбирает** — она требует, чтобы вещи сравнивались,
|
||||
сливались или разбирались, но не называет исход в пограничном случае;
|
||||
3. **неверный выбор не падает** — он даёт правдоподобный результат и меняет смысл
|
||||
данных молча.
|
||||
|
||||
**Отрицательный тест, и он важнее трёх положительных:** если неверная реализация
|
||||
красит гейт, роняет запрос или ломает тест — это **не** сюда. Такое ловят проходы
|
||||
дешевле, и платить за него верхней ступенью не за что.
|
||||
|
||||
Отсюда же и причина, по которой класс достался самому дорогому проходу:
|
||||
независимая реализация **выберет другой вариант**, и дифф между двумя вариантами
|
||||
и есть находка. Там, где вариант один, она совпадёт с существующей — и верхняя
|
||||
ступень оплатит подтверждение того, что и так известно.
|
||||
|
||||
Три слова — это **три места**, где такие правила водятся, и все три стоят на
|
||||
границе, где данные входят или встречаются:
|
||||
|
||||
| Слово | Вопрос, на который правило отвечает | Что в нём выбирается |
|
||||
|---|---|---|
|
||||
| **идентичность** | когда две вещи считаются одной и той же | состав ключа и что в него намеренно не входит; нормализация перед сравнением — регистр, пробелы, кодировка, время, единицы, округление; дедупликация |
|
||||
| **слияние** | что получается, когда два представления одного встретились | кто побеждает при конфликте; накопительное против замещающего; что делать с отсутствующим полем; тай-брейк при равенстве |
|
||||
| **разбор** | как внешнее представление становится внутренним | границы токенов; извлечение полей; сопоставление с известным набором; поведение на неоднозначном входе |
|
||||
|
||||
**Триггер — новое или изменённое правило, а не код рядом с ним.** Правка
|
||||
сообщения об ошибке в узле, который разбирает вход, ступень не поднимает.
|
||||
Поднимают: заводится ключ или меняется его состав; в слияние добавляется источник
|
||||
или меняется победитель при конфликте; у разбора появляется новый вид входа или
|
||||
новая ветка неоднозначности. Без этой оговорки проект, чей домен и **состоит** из
|
||||
таких правил, оказывался бы в `deep` всегда — та же болезнь, от которой лечилась
|
||||
ступень `wide`.
|
||||
|
||||
**Ступень определяет класс правила, а не вид работы.** Миграция схемы сама по
|
||||
себе `standard` — но миграция, которая **переносит данные** по правилу («сложить
|
||||
дубли», «привести к одному виду перед сравнением»), несёт правило идентичности и
|
||||
потому `deep`. Одно и то же слово в описании задачи попадает в разные ступени, и
|
||||
это не противоречие: смотрят не на слово, а на то, есть ли выбор, которого спека
|
||||
не сделала.
|
||||
|
||||
**Проект, у которого таких правил нет вовсе, `deep` не запускает никогда.** Это
|
||||
законное состояние, а не признак недонастройки: бывают проекты, где данные
|
||||
приходят уже нормализованными, ничего ни с чем не сливается, а внешних форматов
|
||||
нет. Верхняя ступень там просто не срабатывает, и придумывать ей повод не надо.
|
||||
|
||||
Свои места проект перечисляет в `docs/review.md`, подраздел «Триггеры профиля» —
|
||||
поимённо, узлами или capability. Перечень **производен от теста**: он не расширяет
|
||||
класс, а называет, где этот класс живёт именно здесь.
|
||||
|
||||
### Профиль — максимум по поверхности, и отсюда размер задачи
|
||||
|
||||
Условия читаются сверху вниз, и **первое подошедшее отвечает за весь дифф**.
|
||||
@@ -458,14 +515,20 @@ Recall обоих равен длине их источника — это и е
|
||||
|
||||
- `review-reimpl` — пишет свою реализацию, не открывая существующую, затем
|
||||
диффит по решениям. **Профиль и есть его условие:** `deep` выбирается ровно
|
||||
тогда, когда изменение вводит новое правило идентичности, слияния или разбора
|
||||
(проектная формулировка — в `docs/review.md`, если записана). Это самый дорогой
|
||||
проход конвейера (его счёт определяется объёмом вывода — он пишет реализацию
|
||||
целиком), а вне этого случая независимый взгляд в значительной мере уже дал
|
||||
профиль `design`: код писался под его находки. Условие выбрано по факту:
|
||||
тогда, когда вводится или меняется по существу правило идентичности, слияния
|
||||
или разбора — по тесту из раздела «Идентичность, слияние, разбор»; проектный
|
||||
перечень мест, где такие правила живут, — в `docs/review.md`, если записан. Это
|
||||
самый дорогой проход конвейера (его счёт определяется объёмом вывода — он пишет
|
||||
реализацию целиком), а вне этого случая независимый взгляд в значительной мере
|
||||
уже дал профиль `design`: код писался под его находки. Условие выбрано по факту:
|
||||
единственный раз, когда триаж назвал отсутствие `reimpl` дырой покрытия, — это
|
||||
была задача с новым правилом слияния сущностей.
|
||||
|
||||
Такие правила обычно занимают десятки строк, но определяют смысл **всех** данных
|
||||
проекта. Отсюда особенность верхней ступени, из-за которой её легко выбрать
|
||||
неверно: самый дорогой проход тратится на самый **маленький** дифф. `deep` не про
|
||||
размер изменения и не про его опасность — он про класс правила.
|
||||
|
||||
Раньше это условие стояло **внутри** профиля, и `deep` означал то семь проходов,
|
||||
то восемь. Реестр состава, который «проверяется взглядом», проверять было нечем:
|
||||
у профиля не было одного правильного ответа. Теперь ступеней две — `wide` и
|
||||
|
||||
Reference in New Issue
Block a user