An open API service indexing awesome lists of open source software.

https://github.com/alexwayfer/payapp_job_test

Тестовое задание для вакансии Ruby Developer в PayApp
https://github.com/alexwayfer/payapp_job_test

Last synced: over 1 year ago
JSON representation

Тестовое задание для вакансии Ruby Developer в PayApp

Awesome Lists containing this project

README

          

# Тестовое задание для вакансии Ruby Developer в PayApp

## Постановка

Два микросервиса.

Первый решает квадратное уравнение `aX^2 + bX + c = 0`.

`POST /api/equation` принимает JSON объект `{ a: , b: , c: }` и возвращает `id`
созданного уравнения

`PATCH /api/equation/:id/solve` решает уравнение, записывает в базу корни,
проверяет их вторым сервисом и возвращает клиенту. Если проверка не прошла,
транзакция откатывается. Предусмотреть корректную обработку ошибок второго
сервиса.

Второй проверяет, что оба корня положительны.

`POST /api/check` принимает JSON объект `{ x1: , x2: }` и возвращает объект
`{ valid: true|false }`.

В метод добавить генерацию ошибки случайным образом (чтобы часть запросов не
проходила).

Бонус: использовать `dry-validation` для проверки входных параметров.

## Решение

Первый сервис в `solver/`, второй — в `checker/`.

Решил впервые попробовать [`grape`](https://github.com/ruby-grape/grape).
Не понравилось: неясная привязка `params` к методам, дублирование в `params` и `route_param`.
Понравилось: `values` и `except_values`, но можно было обойтись меньшими хелперами.

Добавил валидацию `a ≠ 0` (условие решений квадратных уравнений).
Не уверен, когда лучше валидировать: при создании уравнения или при попытке его решить.
Пошёл по более простому и оптимальному пути (первому).

Некоторые инструменты (`toys`) и решения (мемоизация в `config`)
перенёс из экосистемы [Flame](https://github.com/AlexWayfer/flame).

Непонятно, что возвращать от `/solve` в случае какой-либо ошибки. Оставил на откуп `grape`.

Так как это уравнение в вакууме, непонятно, лучше проверять количество корней до отправки запроса
второму сервису или перенести полностью логику туда.
В итоге перенёс, ведь цель задания не (оптимальное) решение уравнения, а взаимодействие сервисов.

Также хотелось бы кэшировать решение в базе до отправки на проверку и переиспользовать его
при повторах после недоступности сервиса проверки, но не стал этого делать по тем же причинам.

Не понятно, в какой "метод" добавить "генерацию ошибки случайным образом".
Добавил в `POST /api/check` у второго сервиса (избегая тестов).
Но из-за наличия кэширования в первом сервисе (про которое не указано ни нужно ли оно,
ни не нужно ли), добиться этого ручным тестированием может быть сложно.

Не использовал `dry-validation` потому, что решил попробовать `grape`, который, как оказалось,
использует `dry`, но не `-validation`. Не нашёл смысла и места использовать `dry-validation`,
но могу прикрутить в дополнительное место или к другому абстрактному коню в вакууме.

Во время решения узнал, что мемоизация с `module_function` не работает,
в отличие от `class << self`.

Вообще, я имел дело с откатом транзакций
[[1]](https://github.com/AlexWayfer/formalism-sequel_transactions),
с обработкой ошибок от сторонних сервисов
[[1]](https://github.com/dustinlakin/twitch-rb/pull/34)
[[2]](https://github.com/EnotPoloskun/twitch-chat/pull/6),
так что не очень понимаю, в чём именно ожидали протестировать меня как кандидата.

Я бы больше понял тестовое с RabbitMQ, Kafka, чем-нибудь подобным, с чем не имел дела,
но что может быть важным в микро-сервисной архитектуре.