верхняя ступень ревью задана тестом, а не списком
«Идентичность, слияние, разбор» пришли из одного проекта, и в общем виде формулировка не читалась: вопрос «как применить это к моему проекту» не имел ответа в тексте. Теперь класс задан тремя условиями, не зависящими ни от домена, ни от языка: вариантов несколько и оба защитимы; спека между ними не выбирает; неверный выбор не падает, а даёт правдоподобный результат и молча меняет смысл данных. Отрицательный тест сильнее трёх положительных: то, что красит гейт, роняет запрос или ломает тест, в класс не входит — это ловят проходы дешевле. Отсюда же и причина, по которой класс достался самому дорогому проходу: независимая реализация выберет другой вариант, и дифф между вариантами и есть находка; там, где вариант один, она совпадёт с существующей. Три слова остались как три места, где такие правила водятся — граница, где данные входят или встречаются: состав ключа и нормализация перед сравнением; победитель конфликта и тай-брейк при равенстве; границы токенов и неоднозначный вход. Проект перечисляет свои места в 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:
@@ -1310,6 +1310,22 @@ SSS: рубрика на узел без нового понятия порож
|
|||||||
ступени, делает ревью **дороже**: тот же объём тем же составом, но костяк оплачен
|
ступени, делает ревью **дороже**: тот же объём тем же составом, но костяк оплачен
|
||||||
дважды. Резать — когда разрез снимает дорогой проход с большей части диффа.
|
дважды. Резать — когда разрез снимает дорогой проход с большей части диффа.
|
||||||
|
|
||||||
|
**XXX. Верхняя ступень задана тестом, а не списком.** «Идентичность, слияние,
|
||||||
|
разбор» — формулировка, пришедшая из одного проекта, и в общем виде она не
|
||||||
|
читалась: вопрос «как это применить к моему проекту» не имел ответа в тексте.
|
||||||
|
Теперь класс задан тремя условиями, независимыми от домена и языка: вариантов
|
||||||
|
несколько и оба защитимы; спека между ними не выбирает; неверный выбор не падает,
|
||||||
|
а молча меняет смысл данных. Отрицательный тест сильнее положительных — то, что
|
||||||
|
красит гейт или роняет запрос, в класс не входит. Три слова остались как **три
|
||||||
|
места**, где такие правила водятся (граница входа данных и место их встречи), а
|
||||||
|
проект перечисляет свои места в `docs/review.md` — перечень производен от теста и
|
||||||
|
не расширяет класс.
|
||||||
|
|
||||||
|
Оговорка, без которой правило вырождается: триггер — **новое или изменённое по
|
||||||
|
существу правило**, а не код рядом с ним. Проект, чей домен и состоит из таких
|
||||||
|
правил, иначе оказывался бы в `deep` всегда — та же болезнь, от которой лечилась
|
||||||
|
ступень `wide`.
|
||||||
|
|
||||||
### Что из этого следует
|
### Что из этого следует
|
||||||
|
|
||||||
72. **Порога в числе границ не заводится.** Тот же принцип, что в теме 16 (CCC):
|
72. **Порога в числе границ не заводится.** Тот же принцип, что в теме 16 (CCC):
|
||||||
@@ -1323,3 +1339,12 @@ SSS: рубрика на узел без нового понятия порож
|
|||||||
75. **Замер остаётся за обкаткой.** Правило выведено из состава проходов, а не из
|
75. **Замер остаётся за обкаткой.** Правило выведено из состава проходов, а не из
|
||||||
статистики прогонов: считать, какая доля задач попадает в каждую ступень,
|
статистики прогонов: считать, какая доля задач попадает в каждую ступень,
|
||||||
можно только на спринтах нового процесса (TODO шаг 4).
|
можно только на спринтах нового процесса (TODO шаг 4).
|
||||||
|
76. **Отсутствие верхней ступени — законное состояние проекта.** Бывают проекты,
|
||||||
|
где данные приходят нормализованными, ничего ни с чем не сливается, а внешних
|
||||||
|
форматов нет: `deep` там не срабатывает никогда, и придумывать ему повод не
|
||||||
|
надо. Раньше это читалось как недонастройка.
|
||||||
|
77. **Ступень определяет класс правила, а не вид работы.** Миграция схемы —
|
||||||
|
`standard`, но миграция, переносящая данные по правилу («сложить дубли»,
|
||||||
|
«привести к одному виду перед сравнением»), несёт правило идентичности и
|
||||||
|
потому `deep`. Одно слово в описании задачи попадает в разные ступени — это не
|
||||||
|
противоречие, смотрят не на слово.
|
||||||
|
|||||||
@@ -38,11 +38,32 @@ color: yellow
|
|||||||
твоя версия проще, потому что не знает, чего проект боится.
|
твоя версия проще, потому что не знает, чего проект боится.
|
||||||
|
|
||||||
**Тебя запускают только в верхнем профиле, `deep`, а не всегда.** Он выбирается
|
**Тебя запускают только в верхнем профиле, `deep`, а не всегда.** Он выбирается
|
||||||
ровно тогда, когда изменение вводит **новое правило идентичности, слияния или
|
ровно тогда, когда вводится или меняется по существу **правило идентичности,
|
||||||
разбора** (проектная формулировка — в разделе
|
слияния или разбора**; ты — единственное, чем `deep` отличается от соседней
|
||||||
`docs/review.md`, если он там записан); ты — единственное, чем `deep` отличается
|
ступени `wide`.
|
||||||
от соседней ступени `wide`. Вне этого случая твой счёт — самый большой в
|
|
||||||
конвейере (он
|
Класс задан тестом, а не списком, и тест не зависит ни от домена, ни от языка.
|
||||||
|
Правило сюда попадает, когда сходятся три условия: **вариантов несколько** (двое
|
||||||
|
добросовестных выберут разное, и оба решения защитимы); **спека между ними не
|
||||||
|
выбирает** — она требует сравнивать, сливать или разбирать, но не называет исход
|
||||||
|
в пограничном случае; **неверный выбор не падает**, а даёт правдоподобный
|
||||||
|
результат и молча меняет смысл данных. Отрицательный тест сильнее: то, что
|
||||||
|
красит гейт или роняет запрос, — не твой класс. Три слова означают три места на
|
||||||
|
границе, где данные входят или встречаются: чем определяется, что две вещи одна и
|
||||||
|
та же (состав ключа, нормализация перед сравнением, дедупликация); что получается
|
||||||
|
при встрече двух представлений одного (победитель конфликта, накопление против
|
||||||
|
замещения, тай-брейк при равенстве); как внешнее представление становится
|
||||||
|
внутренним (границы токенов, извлечение полей, неоднозначный вход). Проектный
|
||||||
|
перечень мест — в `docs/review.md`, если он там записан; он производен от теста,
|
||||||
|
а не расширяет его.
|
||||||
|
|
||||||
|
**Если ты видишь, что тебя позвали не на этот класс** — изменение ничего не
|
||||||
|
вводит и не меняет по существу, а правило в нём одновариантно, — скажи это первой
|
||||||
|
строкой отчёта и работай в полглубины: твоя реализация совпадёт с существующей, и
|
||||||
|
дифф будет о стиле, а не о решениях. Это строка в границы покрытия, а не отказ
|
||||||
|
работать.
|
||||||
|
|
||||||
|
Вне этого случая твой счёт — самый большой в конвейере (он
|
||||||
определяется объёмом вывода: ты пишешь реализацию целиком), а независимый взгляд
|
определяется объёмом вывода: ты пишешь реализацию целиком), а независимый взгляд
|
||||||
в значительной мере уже дал профиль `design` — код писался под его находки. Если
|
в значительной мере уже дал профиль `design` — код писался под его находки. Если
|
||||||
тебя позвали, значит случай тот самый: работай в полную глубину и не экономь на
|
тебя позвали, значит случай тот самый: работай в полную глубину и не экономь на
|
||||||
|
|||||||
@@ -177,8 +177,8 @@ charter'а, а модель потом двигает калибровка, и
|
|||||||
|
|
||||||
Правило выбора профиля — **по факту изменения, не по ощущению важности**:
|
Правило выбора профиля — **по факту изменения, не по ощущению важности**:
|
||||||
|
|
||||||
- трогается правило, определяющее **идентичность, слияние или разбор** данных →
|
- вводится или меняется по существу правило, определяющее **идентичность, слияние
|
||||||
`deep`;
|
или разбор** данных (тест — ниже) → `deep`;
|
||||||
- иначе изменение вводит **новое понятие или структурную единицу**: новый пакет
|
- иначе изменение вводит **новое понятие или структурную единицу**: новый пакет
|
||||||
или слой, новая точка входа, второй способ делать то, что уже делается, перенос
|
или слой, новая точка входа, второй способ делать то, что уже делается, перенос
|
||||||
ответственности между узлами → `wide`;
|
ответственности между узлами → `wide`;
|
||||||
@@ -215,6 +215,63 @@ charter'а, а модель потом двигает калибровка, и
|
|||||||
правда архитектурное (публичный SDK, чужие потребители), там же поднимает его до
|
правда архитектурное (публичный SDK, чужие потребители), там же поднимает его до
|
||||||
`wide` — и это уточнение, а не возврат прежнего умолчания.
|
`wide` — и это уточнение, а не возврат прежнего умолчания.
|
||||||
|
|
||||||
|
### Идентичность, слияние, разбор — тест, а не список
|
||||||
|
|
||||||
|
Три слова названы затем, чтобы верхнюю ступень нельзя было выбрать по ощущению.
|
||||||
|
Читаются они **тестом**, применимым к любому проекту на любом языке; домен, стек
|
||||||
|
и имена узлов в тест не входят.
|
||||||
|
|
||||||
|
Правило принадлежит этому классу, если сходятся **три условия**:
|
||||||
|
|
||||||
|
1. **вариантов несколько** — два добросовестных исполнителя выберут разное, и оба
|
||||||
|
решения защитимы;
|
||||||
|
2. **спека между ними не выбирает** — она требует, чтобы вещи сравнивались,
|
||||||
|
сливались или разбирались, но не называет исход в пограничном случае;
|
||||||
|
3. **неверный выбор не падает** — он даёт правдоподобный результат и меняет смысл
|
||||||
|
данных молча.
|
||||||
|
|
||||||
|
**Отрицательный тест, и он важнее трёх положительных:** если неверная реализация
|
||||||
|
красит гейт, роняет запрос или ломает тест — это **не** сюда. Такое ловят проходы
|
||||||
|
дешевле, и платить за него верхней ступенью не за что.
|
||||||
|
|
||||||
|
Отсюда же и причина, по которой класс достался самому дорогому проходу:
|
||||||
|
независимая реализация **выберет другой вариант**, и дифф между двумя вариантами
|
||||||
|
и есть находка. Там, где вариант один, она совпадёт с существующей — и верхняя
|
||||||
|
ступень оплатит подтверждение того, что и так известно.
|
||||||
|
|
||||||
|
Три слова — это **три места**, где такие правила водятся, и все три стоят на
|
||||||
|
границе, где данные входят или встречаются:
|
||||||
|
|
||||||
|
| Слово | Вопрос, на который правило отвечает | Что в нём выбирается |
|
||||||
|
|---|---|---|
|
||||||
|
| **идентичность** | когда две вещи считаются одной и той же | состав ключа и что в него намеренно не входит; нормализация перед сравнением — регистр, пробелы, кодировка, время, единицы, округление; дедупликация |
|
||||||
|
| **слияние** | что получается, когда два представления одного встретились | кто побеждает при конфликте; накопительное против замещающего; что делать с отсутствующим полем; тай-брейк при равенстве |
|
||||||
|
| **разбор** | как внешнее представление становится внутренним | границы токенов; извлечение полей; сопоставление с известным набором; поведение на неоднозначном входе |
|
||||||
|
|
||||||
|
**Триггер — новое или изменённое правило, а не код рядом с ним.** Правка
|
||||||
|
сообщения об ошибке в узле, который разбирает вход, ступень не поднимает.
|
||||||
|
Поднимают: заводится ключ или меняется его состав; в слияние добавляется источник
|
||||||
|
или меняется победитель при конфликте; у разбора появляется новый вид входа или
|
||||||
|
новая ветка неоднозначности. Без этой оговорки проект, чей домен и **состоит** из
|
||||||
|
таких правил, оказывался бы в `deep` всегда — та же болезнь, от которой лечилась
|
||||||
|
ступень `wide`.
|
||||||
|
|
||||||
|
**Ступень определяет класс правила, а не вид работы.** Миграция схемы сама по
|
||||||
|
себе `standard` — но миграция, которая **переносит данные** по правилу («сложить
|
||||||
|
дубли», «привести к одному виду перед сравнением»), несёт правило идентичности и
|
||||||
|
потому `deep`. Одно и то же слово в описании задачи попадает в разные ступени, и
|
||||||
|
это не противоречие: смотрят не на слово, а на то, есть ли выбор, которого спека
|
||||||
|
не сделала.
|
||||||
|
|
||||||
|
**Проект, у которого таких правил нет вовсе, `deep` не запускает никогда.** Это
|
||||||
|
законное состояние, а не признак недонастройки: бывают проекты, где данные
|
||||||
|
приходят уже нормализованными, ничего ни с чем не сливается, а внешних форматов
|
||||||
|
нет. Верхняя ступень там просто не срабатывает, и придумывать ей повод не надо.
|
||||||
|
|
||||||
|
Свои места проект перечисляет в `docs/review.md`, подраздел «Триггеры профиля» —
|
||||||
|
поимённо, узлами или capability. Перечень **производен от теста**: он не расширяет
|
||||||
|
класс, а называет, где этот класс живёт именно здесь.
|
||||||
|
|
||||||
### Профиль — максимум по поверхности, и отсюда размер задачи
|
### Профиль — максимум по поверхности, и отсюда размер задачи
|
||||||
|
|
||||||
Условия читаются сверху вниз, и **первое подошедшее отвечает за весь дифф**.
|
Условия читаются сверху вниз, и **первое подошедшее отвечает за весь дифф**.
|
||||||
@@ -458,14 +515,20 @@ Recall обоих равен длине их источника — это и е
|
|||||||
|
|
||||||
- `review-reimpl` — пишет свою реализацию, не открывая существующую, затем
|
- `review-reimpl` — пишет свою реализацию, не открывая существующую, затем
|
||||||
диффит по решениям. **Профиль и есть его условие:** `deep` выбирается ровно
|
диффит по решениям. **Профиль и есть его условие:** `deep` выбирается ровно
|
||||||
тогда, когда изменение вводит новое правило идентичности, слияния или разбора
|
тогда, когда вводится или меняется по существу правило идентичности, слияния
|
||||||
(проектная формулировка — в `docs/review.md`, если записана). Это самый дорогой
|
или разбора — по тесту из раздела «Идентичность, слияние, разбор»; проектный
|
||||||
проход конвейера (его счёт определяется объёмом вывода — он пишет реализацию
|
перечень мест, где такие правила живут, — в `docs/review.md`, если записан. Это
|
||||||
целиком), а вне этого случая независимый взгляд в значительной мере уже дал
|
самый дорогой проход конвейера (его счёт определяется объёмом вывода — он пишет
|
||||||
профиль `design`: код писался под его находки. Условие выбрано по факту:
|
реализацию целиком), а вне этого случая независимый взгляд в значительной мере
|
||||||
|
уже дал профиль `design`: код писался под его находки. Условие выбрано по факту:
|
||||||
единственный раз, когда триаж назвал отсутствие `reimpl` дырой покрытия, — это
|
единственный раз, когда триаж назвал отсутствие `reimpl` дырой покрытия, — это
|
||||||
была задача с новым правилом слияния сущностей.
|
была задача с новым правилом слияния сущностей.
|
||||||
|
|
||||||
|
Такие правила обычно занимают десятки строк, но определяют смысл **всех** данных
|
||||||
|
проекта. Отсюда особенность верхней ступени, из-за которой её легко выбрать
|
||||||
|
неверно: самый дорогой проход тратится на самый **маленький** дифф. `deep` не про
|
||||||
|
размер изменения и не про его опасность — он про класс правила.
|
||||||
|
|
||||||
Раньше это условие стояло **внутри** профиля, и `deep` означал то семь проходов,
|
Раньше это условие стояло **внутри** профиля, и `deep` означал то семь проходов,
|
||||||
то восемь. Реестр состава, который «проверяется взглядом», проверять было нечем:
|
то восемь. Реестр состава, который «проверяется взглядом», проверять было нечем:
|
||||||
у профиля не было одного правильного ответа. Теперь ступеней две — `wide` и
|
у профиля не было одного правильного ответа. Теперь ступеней две — `wide` и
|
||||||
|
|||||||
@@ -184,10 +184,11 @@ kebab-case.
|
|||||||
(<провенанс>)`;
|
(<провенанс>)`;
|
||||||
- **Триггеры профиля** — проектная конкретизация правила выбора профиля ревью:
|
- **Триггеры профиля** — проектная конкретизация правила выбора профиля ревью:
|
||||||
что в этом проекте считается **новым понятием или структурной единицей** (это
|
что в этом проекте считается **новым понятием или структурной единицей** (это
|
||||||
поднимает прогон до `wide`) и что — правилом идентичности, слияния или разбора
|
поднимает прогон до `wide`) и **где живут правила идентичности, слияния и
|
||||||
(до `deep`). Уточняет умолчания конвейера, а не отменяет их. Рабочее умолчание
|
разбора** (до `deep`) — перечнем мест, производным от теста конвейера, а не
|
||||||
— `standard`: миграция схемы и публичный контракт ступень **не** поднимают,
|
вторым определением класса. Уточняет умолчания, а не отменяет их. Рабочее
|
||||||
их проверяют проходы, которые в `standard` и так есть;
|
умолчание — `standard`: миграция схемы и публичный контракт ступень **не**
|
||||||
|
поднимают, их проверяют проходы, которые в `standard` и так есть;
|
||||||
- **Недоступно проверке** — два подраздела: «не проверит ни один проход»
|
- **Недоступно проверке** — два подраздела: «не проверит ни один проход»
|
||||||
(принципиальная граница, по факту промаха не пересматривается) и «перестали
|
(принципиальная граница, по факту промаха не пересматривается) и «перестали
|
||||||
проверять сознательно» (пересматривается первым).
|
проверять сознательно» (пересматривается первым).
|
||||||
|
|||||||
@@ -284,9 +284,17 @@
|
|||||||
|
|
||||||
Проектная конкретизация правила выбора профиля: что здесь считается **новым
|
Проектная конкретизация правила выбора профиля: что здесь считается **новым
|
||||||
понятием или структурной единицей** (поднимает прогон до `wide` и запускает
|
понятием или структурной единицей** (поднимает прогон до `wide` и запускает
|
||||||
архитектурный проход) и что — правилом идентичности, слияния или разбора
|
архитектурный проход) и **где живут правила идентичности, слияния и разбора**
|
||||||
(до `deep`, запускает независимую реализацию). Уточняет умолчания конвейера, не
|
(до `deep`, запускает независимую реализацию) — перечнем узлов или capability,
|
||||||
отменяет их; рабочее умолчание — `standard`.
|
поимённо. Уточняет умолчания конвейера, не отменяет их; рабочее умолчание —
|
||||||
|
`standard`.
|
||||||
|
|
||||||
|
Перечень для `deep` **производен от теста конвейера**, а не заменяет его:
|
||||||
|
правило попадает в класс, когда вариантов несколько, спека между ними не
|
||||||
|
выбирает, а неверный выбор не падает, а молча меняет смысл данных. Перечисляй
|
||||||
|
места, где этот класс здесь живёт, а не переписывай определение. Таких мест нет
|
||||||
|
вовсе — так и напиши: `deep` тогда не запускается никогда, и это законное
|
||||||
|
состояние.
|
||||||
|
|
||||||
### Недоступно проверке
|
### Недоступно проверке
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user