# Заметки по ревью кода Сидорова В. *(тестовое задание в контент WB)* Ревьюер: [Гульков И.С.](https://t.me/isgulkov) Версия репы: [`799eacd8676fe4566a82085b5b00ba21f28c8c49`](https://github.com/sidorovvadim33/WeatherServiceApi/tree/799eacd8676fe4566a82085b5b00ba21f28c8c49) Допы: - [x] 1\. Асинхронное обновление данных - [x] 2\. Распараллеливание процесса - [x] 3\. Docker - [x] 4\. «Для самых смелых» - [x] 5\. Swagger, тесты, логи ## Несоответствия требованиям 1. Данные обновляются не раз в минуту, а раз в "минуту + время самого обновления" ## Замечания *Эти пункты в той или иной мере повлияли на оценку* ### Обработка ошибок 1. В куче мест, где ошибка — обычное дело (в частности, при походе по HTTP, запросе в БД), она обрабатывается "фатал еррором" (крэшем сервера). Это совершенно недопустимо ### Работа с внешним API 1. [Вот тут](https://github.com/sidorovvadim33/WeatherServiceApi/blob/799eacd8676fe4566a82085b5b00ba21f28c8c49/internal/api/weatherClient/weatherClient.go#L33-L55) мы запускаем множество HTTP-запросов во внешний сервис условно одновременно. Так нельзя, нужен рейт-лимит. При 20 городах всё работает, но если городов в базе хотя бы 1117... результат тебе уже известен 🌝 ## Придирки по-мелочи *Эти пункты __не__ повлияли на оценку* ### API самого сервиса 1. Формат тел ответов везде JSON, что прекрасно, но в некоторых случаях (напр. `POST /api/userfavs/...`) ответ приходит просто в виде текста "`1`". Так не годится: если везде JSON, то везде JSON, пусть даже просто `{ok: true}` 2. Система авторизации, в которой с каждым запросом нужно слать пароль — это а) небезопасно и б) колхозно. Раз уж заморочался, мог бы и bearer-токены прикрутить ### Архитектура 1. Что за термины `service` и `storage`? В частности, нахрена нужен `service`, если весь код всё равно в `storage`? Где ты это взял? *(просто у нас в коде ровно то же самое, и я всё это время был уверен, что это эндемическое заболевание)* ### Поддерживаемость и кодстайл 1. Вот это вот: ```go for _, city := range cities { city := city go func() { // Использование city }() } ``` покрасивше ж вот так: ```go for _, city := range cities { go func(city cityClient.CityData) { // Использование city }(city) } ``` 2. `w.WriteHeader(http.StatusOK)` — это no-op 3. А зачем использовать `net.Listen` вообще? HTTP-сервер из `net/http` сам это умеет... 4. Куча мест ([например](https://github.com/sidorovvadim33/WeatherServiceApi/blob/799eacd8676fe4566a82085b5b00ba21f28c8c49/internal/api/weatherClient/weatherClient.go#L36)), где переменная объявляется в самом начале функции, хотя используется только через 20–30 строк. Это чё, C89?