Статьи

Clojure (призматические) схемы чванства

чванство-Clojure Недавно я решил включить документацию Swagger в нашу заявку. Хотя Swagger предоставляет инструменты, помогающие клиентам интегрироваться с вашим REST API, наиболее мощная функция, на мой взгляд, заключается в том, что он действует как «живая документация» для API. Добавление Swagger в мое приложение имело несколько приятных побочных эффектов:

Идиоматическое Clojure поощряет использование структур данных, таких как карты. Это работает очень хорошо, потому что перевод JSON в / из Clojure Map, и постоянство становится прямым, независимо от того, используете ли вы org.clojure / java.jdbc или сохраняете базу данных документов, такую ​​как MongoDB. Однако проблема с этим подходом заключается в том, что понимание ваших сущностей становится трудным. Для этого вам часто приходится прибегать к DDL, а в случае некоторых баз данных у вас может даже не быть этого. В случаях, когда вы используете миграции — ваш DDL может быть разбросан по многим миграциям с течением времени. Поддержка Swagger, предоставляемая metosin / compojure-api, использует призму / схему для определения вашего API. Вот пример того, как «Активность» и список «Активностей» выглядят в приложении «Мои ведомости»:

1
2
3
4
5
6
7
(def Activity {
  :id s/Num
  :name s/Str
  :description s/Str
  :activitytype (s/enum "Daily" "Hourly") })
 
(def Activities [Activity])

Призматическая схема предоставляет другие функции, такие как необязательность атрибутов, необязательность значений, настраиваемые типы схем и т. Д. См. README для получения дополнительной информации.

Теперь, когда у меня есть единственное место, куда я могу пойти, чтобы полностью понять, как выглядят мои сущности / объекты-значения. Те же объекты / значения-объекты используются в моих определениях маршрута для определения REST API.

1
2
3
4
5
6
7
8
9
(GET* "/activity" []
  :return Activities
  :summary "All activities in the system"
  (ok (auth #(controller/get-activities))))
 
(PUT* "/activity" []
  :body [activity Activity]
  :summary "Update an activity"
  (ok (auth #(controller/update-activity activity))))

Здесь я создаю два маршрута для запросов GET и PUT HTTP. В случае GET я верну активность, а в случае PUT ожидаю активность в теле и ничего не верну. В обоих случаях я возвращаю HTTP-код ОК. Вызов «auth» позволяет мне аутентифицировать пользователя до того, как будет выполнен вызов на контроллер. API Compojure может генерировать полный интерфейс Swagger, позволяя разработчикам-клиентам исследовать и вызывать API (если, конечно, у них есть правильный доступ!).

Сгенерированный интерфейс Swagger выглядит следующим образом.

чванство-документ

API Compojure проверяет каждый запрос / ответ на соответствие модели, так что любое нарушение API приведет к сбою. Это подводит меня ко второму побочному эффекту; Вы можете проверить модель по вашим тестам! В моем случае я проверяю модель по моим контроллерам:

1
2
3
4
5
(defn ^:always-validate get-activities :- Activities []
  (model/get-activities))
 
(defn ^:always-validate update-activity [activity :- Activity]
  (model/update-activity activity))

Использование метаданных ^:always-validate проверит мои тесты по модели. В этом случае мои функциональные тесты тестируют систему от контроллеров до базы данных, что позволяет мне применять схему во время сборки.

Clojure — это динамический язык. Одна из его основных критических замечаний — отсутствие типов. Хотя проект Typed Clojure проделал хорошую работу, я думаю, что библиотека Prismatic Schema обеспечивает очень хороший компромисс, и тот факт, что она прекрасно сочетается с Swagger, является обледенением.

Ссылка: Схемы Clojure (Prismatic) — это Swagger от нашего партнера JCG Mashooq Badar из блога Crafted Software .