Дизайн API играет большую роль в создании приложений. Если вы не разработаете его хорошо, вам в будущем придется столкнуться с минусами. Поскольку архитектура микросервисов позволяет большому приложению разделиться на множество небольших, автономных, слабо связанных сервисов. Микрослужба работает как подключаемый компонент, который мы можем изменять в любое время, не затрагивая другие службы в архитектуре микросервисов. Работая над архитектурой микросервисов, мы пишем множество сервисов. Если мы не дадим ему правильного определения, это создаст множество проблем для других пользователей потребительских сервисов / API. Если вы не разработаете надлежащий ответ, потребительские службы не узнают, что происходит за обращением в службу поддержки. Мы всегда пишем как минимум 3 слоя для любого заданного api ex. Контроллер, сервис, дао. Мы всегда должны стараться четко разделить здесь ответственность.

  1. Конечные точки: вокруг много дискуссий. Но мы бы увидели рекомендуемые практики для этого. Начнем с нескольких примеров
  • getEmployees
  • addEmployee
  • deleteEmployee
  • findEmployeeById
  • UpdateEmployee и т. Д.

С этой практикой связаны серьезные проблемы. Допустим, вы пишете еще один api для клиента, чтобы в конечном итоге написать много похожих конечных точек, используя заданную практику. Итак, в конце ваше приложение будет иметь конечные точки. Их было бы трудно поддерживать. В конечном итоге вы создадите несколько конечных точек для одного и того же ресурса, например. сотрудник, клиент и т. д., что совсем не требуется. Конечные точки API не должны содержать никаких глаголов, действий. В конечной точке должно быть только существительное (ресурс во множественном числе). Нам не нужно выполнять действия в конечной точке, доступны различные методы https (GET, POST, DELETE, PUT), которые работают для вас здесь. Теперь, если мы будем следовать этой практике, у нас должны быть следующие конечные точки:

  • Путь GET / сотрудники
  • УДАЛИТЬ путь / сотрудники / идентификатор
  • Путь POST / сотрудники

2. Обработка исключений: здесь нам нужно быть очень осторожными, поскольку он дает потребителю много информации о вашем API, когда он не работает должным образом. Мы всегда должны стараться придумывать минимально необходимые коды состояния, сообщения во время работы над новым api. Допустим, мы пишем api, который обрабатывает оплату для данного заказа клиента.

  • VALIDATION_ERROR, если введенные данные неверны, например, некоторые поля могут быть пустыми и т. Д.
  • ORDER_NOT_FOUND, когда нет заказа с данной информацией.
  • ORDER_CANCELLED при отмене заказа.
  • REFUND_FAILED, когда возврат уже обработан.
  • INVALID_AMOUND недействительная сумма
  • ТЕХНИЧЕСКАЯ_ОШИБКА

Если вы видите здесь, это упростит жизнь потребителя, если мы правильно разработаем коды состояния, сообщения вокруг нашего API, вместо того, чтобы просто использовать TECHNICAL_ERROR, что очень абстрактно. Всегда старайтесь придумывать минимальные варианты использования вашего api. Если мы будем использовать TECNICAL_ERROR для каждого случая, потребителю будет сложно понять вывод нашего API, когда что-то пойдет не так. Потребителю придется проверять журналы, чтобы понять это правильно, что не рекомендуется. Потребителю не нужно проверять журналы на предмет этих базовых сценариев использования, если мы хорошо спроектировали наш API.

  • Выбрасывать настраиваемое исключение (создавать настраиваемое исключение, которое принимает сообщение и код состояния в качестве входных данных) из службы на основе этих вариантов использования, например. неверная сумма, проверка ввода, сбой возврата и т. д., и обработайте это в контроллере.
  • Создайте окончательный ответ api, передав информацию об исключении в служебный метод ответа, который принимает статус, сообщение в качестве входных данных и дает окончательный ответ.
  • Избегайте создания окончательного ответа на сервисе, поскольку окончательный ответ api содержит успех, код ошибки, сообщение, которое не должно выполняться на уровне сервиса. Бывают случаи, когда мы вызываем разные службы из одной службы и не ожидаем ответа в таком формате. Это нарушает принцип «четкого разделения слоев». Получение окончательного ответа API не входит в обязанности службы. это то, что должно выполняться на уровне контроллера.

3. Контроллер: Контроллер - это место, куда вы сначала получаете запрос. У нас всегда должны быть классы dto, предназначенные для контроллера. Никогда не смешивайте классы домена (объект / документ) с контроллером, поскольку мы всегда ожидаем, что эти два поведения будут вести себя по-разному. Возьмем пример

  • Класс домена (объект / документ) может иметь много полей, но мы можем не захотеть отправлять все потребителю. Есть классы dto с обязательными полями.
  • Есть случаи, когда нам нужно сравнить классы наших моделей. Скажем, при обновлении любого объекта домена вы хотите записать его в историю с измененными полями. Когда вы думаете о сравнении двух объектов pojo, вы заботитесь обо всех полях, но объект домена можно сравнить, просто используя идентификаторы. Таким образом, эти классы предназначены не только для передачи информации об объектах предметной области с одного уровня на другой, существуют различия в поведении.
  • Контроллер не должен иметь никакой бизнес-логики.
  • Рекомендуется создать окончательный ответ на контроллере, так как это место, где мы должны создавать окончательный ответ с заданным кодом состояния, сообщением. Уровень обслуживания передает код состояния, сообщение в виде настраиваемого исключения, которое необходимо обрабатывать на уровне контроллера.
  • Не следует вызывать несколько служб из контроллера, вместо этого нужно иметь новую службу, которая при необходимости вызывает несколько служб. Опять же, нам нужно быть осторожными с точки зрения дизайна ex. что, если первая служба выдает исключение, дает пустой ответ и т. д. Попробуйте разработать правильный код состояния, сообщив об этом.
  • Не следует вызывать dao / репозиторий из контроллера, поскольку это не ответственность контроллера.

4. Служба. Служба - это место, где должна быть написана бизнес-логика API.

  • Всегда старайтесь разделить методы обслуживания на небольшие. Опять же, если мы разделим его на частные методы, возникнут проблемы с разработкой тестовых примеров. Вы можете переместить эти частные методы в класс адаптера, иметь статические методы для достижения того же, поскольку трудно охватить все возможные варианты использования частных методов из вызова тестового примера. Иногда требуется несколько больших конфигураций для тестирования всех сценариев. Мы также можем иметь эти методы как частные пакеты и хранить их в том же классе обслуживания.
  • Всегда выполняйте проверку полей ввода и генерируйте настраиваемое исключение с кодом ошибки проверки и сообщением об ошибке для конкретных полей. Если необходимо проверить несколько полей, переместите его за пределы обслуживания. Имейте класс валидатора для записи валидации для всех полей. Это сделает ваши методы обслуживания небольшими и чистыми.
  • Допустим, есть два объекта домена A, B, и у нас есть два разных репозитория, определенных для этих двух. Есть случай, когда нам нужно получить информацию о других объектах домена. В этом случае мы не должны вызывать методы репозитория B напрямую из метода службы A. Всегда старайтесь получить класс обслуживания для методов репозитория, даже если он вам нужен в контроллере. Поскольку есть несколько вещей, которые мы обрабатываем на уровне обслуживания, а не на уровне репозитория, например. транзакция, кеширование и т. д.
  • Не смешивайте два объекта / репозитория домена с одним и тем же методом обслуживания.
  • При вызове внешних служб или других служб, если мы не получаем необходимых данных, генерируем настраиваемое исключение с требуемым кодом состояния, сообщением об ошибке.
  • Не делайте ничего, что характерно для уровня репозитория при обслуживании. бывший. построение критериев / запроса на уровне обслуживания в случае mongodb.
  • Поместите кеширование для требуемых методов обслуживания.

5. Репозиторий / Дао: этот уровень взаимодействует с базой данных в вашем приложении. База данных сканирует каждую запись, чтобы получить требуемый результат, если мы не создадим индекс для enitity / document, что крайне неэффективно. Индексы помогают сократить пространство поиска. Прочтите this, чтобы узнать больше о работе индексов.

  • Мы должны сначала попытаться понять методы поиска, а затем придумать правильную индексацию.
  • Создавайте индекс только тогда, когда это необходимо, поскольку это может сделать операцию записи или удаления дорогостоящей. И потребуется обновить как таблицу / документ, так и индексированные данные.
  • Если вам нужно получить данные на основе нескольких полей, избегайте написания нескольких методов, вместо этого попробуйте создать динамический запрос на основе заданных полей с помощью одного метода репозитория.

6. Модульное тестирование. Модульное тестирование помогает независимо тестировать код. если ваши методы кода выглядят очень сложными или содержат много строк кода, его всегда сложно протестировать. Попробуйте разбить на несколько небольших методов (обсуждаемых в служебной части). Модульное тестирование очень поможет вам при написании больших модулей с большим количеством конфигураций и множеством связанных с этим условий. Это экономит много времени, поскольку вам не нужно повторно развертывать код каждый раз, когда вы вносите небольшие изменения в код. Вы можете просто проверить это с помощью тестового примера. Это также помогает вам в дублировании проблем приложения, вам просто нужно получить конфигурацию для данной проблемы в вашем тестовом примере, и вы можете легко ее исправить.

API - это интерфейс, который позволяет многим разработчикам взаимодействовать с данными. Мы всегда должны сосредотачиваться на разработке отличного API, поскольку он очень помогает с точки зрения его использования и понимания.