исправлены дефекты формулировок в конвенциях
- убраны неверные утверждения: покрытие forbidigo сужено до честного, таблица классов доменного отказа больше не претендует на полноту, механизация не подаётся как факт канона - введены недостающие определения (доменная и внешняя границы, объявление пути), критерий постоянного поля сведён к одному на R16.1 и R17 - kebab-case имени файла убран из правил в прозу: обоснование не формулировалось, номер R16 оставлен свободным
This commit is contained in:
@@ -209,7 +209,7 @@ dev-выводом перестаёшь ежедневно гонять собс
|
||||
|
||||
| № | Когда добавляем | Поля |
|
||||
|---|---|---|
|
||||
| R16.1 | входящий HTTP-запрос (middleware) | `http.method`, `http.route`, `http.status_code`, `duration_ms`, `transport` — если транспортов больше одного |
|
||||
| R16.1 | входящий HTTP-запрос (middleware) | `http.method`, `http.route`, `http.status_code`, `duration_ms`, `transport` — пока его значение различается между записями (R17) |
|
||||
| R16.2 | работа с сущностью (scoped-логгер) | `<entity>_id` и доменные атрибуты |
|
||||
| R16.3 | запись об ошибке | `error` |
|
||||
| R16.4 | вызов внешнего сервиса | `ext.service`, `ext.operation` (логическая операция, не URL), `ext.status_code`, `duration_ms`, `retry` |
|
||||
@@ -223,10 +223,12 @@ dev-выводом перестаёшь ежедневно гонять собс
|
||||
|
||||
### R17. `service.*` и `host.*` не заводим
|
||||
|
||||
**НЕ СЛЕДУЕТ.** Пока это один бинарь на одном хосте.
|
||||
**НЕ СЛЕДУЕТ.** Поле, значение которого одинаково во всех записях, не
|
||||
заводится — для одного бинаря на одном хосте это `service.*` и `host.*`.
|
||||
|
||||
**Почему.** Поле с одним и тем же значением во всех записях не несёт
|
||||
информации, но стоит места в каждой строке и внимания при чтении. Условие
|
||||
**Почему.** Такое поле не несёт информации, но стоит места в каждой строке
|
||||
и внимания при чтении. Критерий один на все поля словаря — им же решается,
|
||||
нужен ли `transport` (R16.1): пока транспорт один, поле постоянно. Условие
|
||||
названо явно, поэтому правило отпадёт вместе со своей причиной: с
|
||||
появлением нескольких инстансов различающее поле (`service.version`)
|
||||
добавляется одной строкой при старте.
|
||||
@@ -326,7 +328,8 @@ ctx = logctx.With(ctx, log) // достаём логгер из ctx в кажд
|
||||
### R25. Уровень доменного отказа — по классу отказа
|
||||
|
||||
**ДОЛЖЕН.** Уровень выбирает единственный логирующий (R23), и выбирает по
|
||||
классу, а не по месту в коде.
|
||||
классу, а не по месту в коде. Классификация покрывает **доменные** отказы —
|
||||
те, что операция вернула значением `error`.
|
||||
|
||||
| № | Класс отказа | Кому | Уровень |
|
||||
|---|---|---|---|
|
||||
@@ -341,6 +344,10 @@ ctx = logctx.With(ctx, log) // достаём логгер из ctx в кажд
|
||||
его вызвал, — и невалидный ввод из формы копился бы в `ERROR` наравне с
|
||||
упавшей базой.
|
||||
|
||||
Нарушение инварианта в собственном коде — паника, недостижимая ветка — в
|
||||
таблицу не входит: это не доменный отказ, и логирует его recover-граница
|
||||
вместе со стеком (`lang/go/errors.md`). Искать его класс здесь не нужно.
|
||||
|
||||
### R26. Тот же отказ в асинхронной стадии — уровнем выше
|
||||
|
||||
**ДОЛЖЕН.** Когда пользователь не ждёт результата, отказ адресован
|
||||
|
||||
Reference in New Issue
Block a user