Эй, подожди, что за несчастный путь? Хорошо, давайте начнем с самого начала, успешный путь — это сценарий по умолчанию, в котором нет исключительных или ошибочных условий, поэтому неудачный путь — это все остальные сценарии, в которых случаются исключительные ситуации или ошибки.

В этой статье мы попытаемся объединить несколько концепций, таких как «Любой» и «Проверено», в приложение REST.

  • Моделирование несчастливого пути (исключения/ошибки)
  • Обработка ошибок и сопоставление с кодами состояния HTTP

Предпосылки

  • Базовое понимание DataTypes, Kotlin и SpringBoot

Моделирование несчастливого пути

«Как пользователь, я хочу получать бронирования данного продукта по идентификатору»

У нас есть счастливый путь, на котором мы можем ответить на запрос пользователя бронированием (зеленые стрелки), и есть 5 путей, на которых мы должны вернуть сообщение об ошибке, в котором говорится, что мы не можем вернуть то, что они просили.

Эти ошибки — это то, что в Java мы привыкли «моделировать» как исключения. Программист должен иметь детализированные исключения, описывающие каждый тип ошибки, как мы все делали в начале, вы начинаете генерировать new RuntimeException(), который ни хрена не говорит об ошибке ( несчастливый путь), и когда это происходит в производстве, вам просто нужно отладить свой код, чтобы узнать, что произошло. После нескольких ударов по лицу вы начинаете (надеюсь :) ) создавать пользовательские исключения и включать описания, позволяющие с первого взгляда узнать о контексте сбоя. На данный момент вы в порядке (с точки зрения Java).

Но у исключений есть несколько недостатков, исключение может быть просто потеряно, и если документация недостаточно хороша, вы обнаружите некоторые из них во время выполнения ›.‹

Здесь мы можем пойти дальше и использовать типы данных и соглашения для улучшения этого сценария.

Типы данных на помощь: любой и проверенный

Тип данных — это абстракция, которая инкапсулирует повторно используемый шаблон кодирования. Эти решения имеют каноническую реализацию, обобщенную для всех возможных применений.

Предложение состоит в том, что если мы моделируем наш сценарий успеха, то же самое делаем и для неудач. Как тогда мы сообщаем об ошибке? Делая это явным в типе данных, который мы возвращаем.

Либо используется для сокращения вычислений при первой ошибке, что соответствует логическому ИЛИ или + как алгебраическому типу данных. Мне нравится думать, что это коробка с двумя сегментами: по соглашению левый сегмент используется для сохранения неудачи, а правый сегмент — для успеха. Здесь вы можете найти действительно хорошую документацию по этому типу данных.

Существует много документации с множеством небольших примеров, мы переходим непосредственно к реальному варианту использования. В нашем примере мы должны использовать внешний сервис и десериализовать его содержимое в нашу модель Booking. Сервис возвращает список бронирований даже при поиске по ID.

Проверьте, что мы сделали, сигнатура нашего метода fun get(pnr: String): Либо‹BookingRetrievalError, Booking›говорит, что он вернет Booking (справа), когда все идет вправо и BookingRetrievalError (слева) в случае сбоя. Класс BookingRetrievalError моделирует все возможные сбои, поэтому вы можете обрабатывать каждый из них, избегая неожиданностей во время выполнения.

  • BookingNotFound -› бронирование с указанным pnr (id) не найдено
  • SupplierFailure -› внешнему поставщику не удалось обработать наш запрос
  • UnexpectedFailure -› мы не знали, что случилось

Как видите, неожиданностей во время выполнения не будет, все возможные сбои есть во время компиляции.

Теперь у нас есть вызов внешней службы, предположим, что нам нужно управлять только бронированиями со статусом Подтверждено и с некоторой ценностью для агентства. Мы также хотим смоделировать наши валидации, чтобы было ясно как вода, почему наш сервис может дать сбой.

Сколько раз вы заполняли форму, а затем отправляли. Выскакивает ошибка о том, что имя пользователя уже занято, вы меняете его, а затем отправляете повторно. Появляется еще одна ошибка, говорящая о том, что ваш адрес не имеет ожидаемого формата. Напрасно поминаете Господа и удивляетесь, почему сразу все ошибки валидации сходятся... Вот и тип данных Validated.

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

Здесь — это остальная часть примера, охватывающая сквозную службу REST, довольно близкую к продуктивному приложению. Вы можете запустить его и играть с ним. В этой статье есть примеры для каждой неудачи.

Моделирование неудовлетворительного пути — это шаг вперед к созданию надежных, отказоустойчивых и простых в мониторинге приложений. Тесты легко писать, и их гораздо легче охватить кодом. Никаких сюрпризов в 3 часа ночи :)

Удачного кодирования!

Что дальше?





Глава 19. Обработка ошибок
Когда мы говорим о «чистой
обработке ошибок, мы имеем в виду алгоритмы, которые не требуют ничего из монады IO…book .realworldhaskell.org»