generated from VLADIMIR/template
update
This commit is contained in:
+30
-8
@@ -204,18 +204,40 @@ SQL держи рядом с методом, которому он нужен.
|
|||||||
## 8. Ошибки и context
|
## 8. Ошибки и context
|
||||||
|
|
||||||
- Возвращай ошибки, не паникуй в обработке пользовательского ввода, БД,
|
- Возвращай ошибки, не паникуй в обработке пользовательского ввода, БД,
|
||||||
файлов, сети и внешних сервисов.
|
файлов, сети и внешних сервисов. `panic` допустим только для невозможного
|
||||||
- Для ожидаемых веток объявляй sentinel-ошибку в пакете, который владеет
|
нарушения внутреннего инварианта при старте или в коде, который не имеет
|
||||||
смыслом ошибки; проверяй её через `errors.Is`.
|
осмысленного способа продолжить работу.
|
||||||
|
- Ошибкой владеет пакет, которому принадлежит её смысл. Ожидаемые состояния
|
||||||
|
объявляй как sentinel-ошибки (`var Err... = errors.New(...)`) в сервисе,
|
||||||
|
repository или module; не дублируй одну смысловую ошибку в разных слоях.
|
||||||
|
- Repository переводит ошибки драйвера и ограничения БД в свои предметные
|
||||||
|
ошибки. Service переводит их в ошибки use case. `app` не меняет бизнес-смысл
|
||||||
|
ошибки, а только преобразует её в транспортный ответ.
|
||||||
|
- Для ожидаемых веток проверяй цепочку через `errors.Is`; для ошибок с данными
|
||||||
|
используй `errors.As`. Текст ошибки не сравнивай.
|
||||||
- Оборачивай ошибку с контекстом через `%w`, например
|
- Оборачивай ошибку с контекстом через `%w`, например
|
||||||
`fmt.Errorf("загрузить сценарий %d: %w", id, err)`.
|
`fmt.Errorf("загрузить сценарий %d: %w", id, err)`. Не теряй исходную ошибку
|
||||||
- Не сравнивай текст ошибки и не теряй исходную ошибку без причины.
|
без причины и не оборачивай её повторно пустым или одинаковым сообщением.
|
||||||
|
- `status.Error` и `status.Errorf` используй только на транспортной границе
|
||||||
|
(`internal/app` или gRPC middleware). Services, repositories и modules не
|
||||||
|
возвращают gRPC-ошибки.
|
||||||
|
- Преобразование ошибок use case в gRPC-коды держи в `*_errors.go` рядом с
|
||||||
|
handler-ом. Для неизвестной ошибки возвращай `codes.Internal` с безопасным
|
||||||
|
общим сообщением; детали причины сохраняй в цепочке и логируй на внешней
|
||||||
|
границе.
|
||||||
|
- Клиенту нельзя отдавать SQL, пути файлов, адреса внешних сервисов, stack
|
||||||
|
trace, токены, пароли или персональные данные. Ошибки валидации могут
|
||||||
|
содержать только безопасные сведения, необходимые клиенту.
|
||||||
|
- Логируй ошибку один раз на границе, которая принимает решение о внешнем
|
||||||
|
ответе; нижние слои добавляют контекст через `%w`, но не дублируют лог.
|
||||||
- Каждый внешний вызов получает переданный `context.Context`; timeout нужен на
|
- Каждый внешний вызов получает переданный `context.Context`; timeout нужен на
|
||||||
границе долгой операции или фонового worker-а.
|
границе долгой операции или фонового worker-а. Отмену контекста не скрывай:
|
||||||
|
возвращай `ctx.Err()` или оборачивай её через `%w`.
|
||||||
- Не помещай обязательные параметры операции в context. В context допустимы
|
- Не помещай обязательные параметры операции в context. В context допустимы
|
||||||
только request-scoped данные, уже принятые проектным middleware.
|
только request-scoped данные, уже принятые проектным middleware.
|
||||||
- Не логируй пароли, токены, персональные данные и содержимое пользовательских
|
- Для каждой новой ветки бизнес-ошибки тестируй `errors.Is` и итоговый
|
||||||
файлов.
|
транспортный код; для неизвестной ошибки проверяй, что наружу уходит
|
||||||
|
`codes.Internal` без внутренних деталей.
|
||||||
|
|
||||||
## 9. SQL и транзакции
|
## 9. SQL и транзакции
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user