Сучасна диджитал-освіта для дітей — безоплатне заняття в GoITeens ×
Mazda CX 30
×

Тайпсейф HTTP API в Scala, вихід Tapir 1.0 та результати опитування Українського Scala Community

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті

Всім привіт! Попри війну, що триває, ми намагаємось оживляти діяльність різних IT-спільнот і продукувати нові цікаві новини та статті. Цього разу пропоную вам поглянути на новий значущий реліз в екосистемі Scala та результати опитування Scala-спільноти у телеграм-чаті.

Минулого тижня оголосили про вихід першої стабільної версії Tapir, бібліотеки для «типобезпечного», декларативного будування HTTP API. Тапір є фасадом над іншими бібліотеками HTTP і дозволяє описувати API незалежно від реального сервера, який використовується. Як реалізацію цей фасад може використовувати такі технології як Play, Akka HTTP, Netty, Http4s, Armeria, Vert.x і навіть AWS лямбди. Найприємнішою особливістю тапіру є генерація OpenAPI документації ендпоїнтів на основі описаних шляхів (routes) HTTP-сервіса.

У цьому дописі хочу представити вам переклад статті з блогу softwaremill про реліз Tapir 1.0, а в кінці привести результати голосування, проведеного в телеграм чаті scala_ukraine щодо того, яким HTTP-фреймворком найчастіше користуються Scala розробники сьогодні.

Далі переклад:

Ми раді оголосити про випуск tapir 1.0!

Після майже 4 років розробки та кількох мінорних випусків 0.x декларативна, типобезпечна бібліотека ендпоінтів досягла важливого майлстоуну — стабільного випуску.

libraryDependencies += 
  "com.softwaremill.sttp.tapir" %% "tapir-core" % "1.0.0"

import sttp.tapir._

💡 Метою tapir є надання зручного для програміста, достатньо безпечного с точки зору типів API для надання, використання та документування HTTP ендпоінтів. Як ми цього досягаємо? Читайте далі! :)

Що таке тапір?

Якщо ви ще не знайомі з tapir, зараз чудовий час почати це знайомство! За допомогою tapir ви можете описати ендпоінти HTTP API як незмінні значення Scala. Кожен ендпоінт може містити кілька вхідних і вихідних параметрів. На основі специфікації ендпоінта можна сгенерувати (інтерпретувати) сервер, клієнт або документацію.

Приклад ендпоінту може бути таким:

val addBook: PublicEndpoint[(Book, AuthToken), String, Unit, Any] = 
  endpoint
    .post
    .in("books" / "add")
    .in(jsonBody[Book]
        .description("The book to add")
        .example(Book("Pride and Prejudice", Author("Jane Austen"))))
    .in(header[AuthToken](HeaderNames.Authorization)
        .description("The token is 'secret'"))
    .errorOut(stringBody)

Під час інтерпретації сервера вам потрібно поєднати опис ендпоінта (який містить лише метадані) з функцією, що реалізує бізнес-логіку. Сигнатура цієї функції повинна відповідати формі ендпоінту, і це перевіряється під час компіляції! Існує ряд інтерпретаторів, які інтегруються з конкретною реалізацією сервера, такими як akka-http, http4s, netty, playframework, vertx та інші:

// повертає або помилку у форматі String або Unit,
// що означає вдале додавання книги
def bookAddLogic(
    book: Book, token: AuthToken): Future[Either[String, Unit]] = ???

val addBookServerEndpoint = 
  addBook.serverLogic((bookAddLogic _).tupled)

val akkaRoute = 
  AkkaHttpServerInterpreter().toRoute(addBookServerEndpoint)

Tapir підтримує всі основні стеки Scala: апі, що базуються на Future зі стандартної бібліотеки Scala, cats-effect і ZIO. Тож, незалежно від ваших уподобань, ми вас забезпечимо відповідною реалізацією!

З іншого боку, інтерпретуючи той самий ендпоінт як клієнт, ви також отримаєте функцію. В цю функцію потрібно передати параметри, за допомогою яких слід зробити виклик ендпоінту:

val result: Either[String, Unit] = SttpClientInterpreter()
  .toQuickClient(addBook, Some(uri"<http://library.com>"))
  .apply(Book("Iliad", Author("Homer")))

Нарешті, інтерпретатори документації дозволяють конвертувати високорівневий опис, записаний як case class, в OpenAPI yaml і відображати цей yaml за допомогою інтерфейсу користувача Swagger:

Доступні також і інші інтерпретатори, зокрема для документації AsyncAPI (для ендпоінтів веб-сокетів) і для безсерверного розгортання (наразі ендпоінт інтерпретується як конфігурація AWS Lambda). Перегляньте документацію, щоб дізнатися більше!

Ви також можете створити проект tapir з бажаним стеком. Просто перейдіть на сайт accept-tapir.softwaremill.com, введіть потрібне ім’я, імпортуйте його у свою улюблену IDE та почніть роботу!

Чому Tapir?

З огляду на велику кількість можливостей для створення HTTP API у вашому сервісі, чому ви повинні розглядати tapir взагалі?

Перш за все, є всі вагомі причини, чому Scala має бути у вашому списку кандидатів. Ця сучасна, гнучка, функціональна/об’єктно-орієнтована мова є міцною основою для моделювання складних бізнес-доменів і створення коду, який буде легко підтримувати. Використовуючи Scala, концепції домену можна виносити на передній план, а не втопати в тоннах інфраструктурного коду. Незмінність структур даних і той факт, що все в Scala є виразом і має значення (мається на увазі, що в Scala всі конструкції повертають якесь значення), впливають на якість розробки набагато більше, ніж може здатися на перший погляд!

Tapir використовує можливості Scala багатьма шляхами:

  • Безпека типів: гарантії під час компіляції, авто-доповнення коду під час розробки, додаткова інформація під час читання коду.
  • Декларативний підхід: відокремте форму ендпоінту («що») від логіки сервера («як»).
  • Інтеграція з OpenAPI / Swagger: генеруйте документацію з описів ендпоінтів.
  • Observability: використовуйте метадані, щоб звітувати про різноманітні показники та інформацію про відстеження (tracing).
  • Абстракція: повторно використовувуйте загальні визначення ендпоінтів, а також окремі входи/виходи.
  • Бібліотека, а не фреймворк: інтегрується з вашим стеком.

Дослідіть приклади, щоб побачити тапір в дії.

Що означає «стабільний»?

З випуском 1.0 ми переводимо основний модуль для Scala 2 до статусу «стабільний». Це означає, що бінарна сумісність гарантується в основній версії. Тобто до виходу tapir 2.0 у цьому модулі не буде бінарно-несумісних змін. Це гарантується за допомогою MiMa плагіну.

У Tapir є багато інших модулів (наразі понад 40), які мають різні рівні стабільності. Ми класифікували їх як стабільні, ті які стабілізуються та експериментальні.

Хоча поки ми робимо стабільним лише один модуль (втім, це найважливіший!), більшість інших модулів перебувають у фазі стабілізації. Наступні мінорні випуски tapir призведуть до їх переведення в стабільний стан. Перегляньте сторінку стабільності в документації, щоб отримати вичерпний список.

Той факт, що core модуль є стабільним, означає, що сторонні бібліотеки можуть безпечно залежати від цього модуля, який визначає основні абстракції тапіра: Endpoint, Schema, Codec та ServerEndpoint. Ми сподіваємося побачити деякі захоплюючі розробки у вигляді незалежно розроблених інтерпретаторів!

💡 Що стосується Scala 3, ми все ще розглядаємо деякі зміни в тому як працює макроси для виведення інстансів Schema (макроси в Scala 3 самі все ще переживають певний розвиток), тому в цій області можуть бути деякі бінарно-несумісні зміни.

Спільнота

Випуск tapir 1.0 став можливим лише завдяки нашій фантастичній спільноті. Протягом останніх 4 років ми постійно отримували зворотний зв’язок у вигляді запитань у gitter, issues із GitHub та пул-реквестів, які допомогли нам сформувати тапір та охопити якомога більше корнер-кейсів.

Ми дослідили ряд різних конструкцій, деякі з них задокументовані в ADR (architecture decision records). Наші ранні користувачі терпляче переносили свої бази коду з однієї версії 0.x до іншої, допомагаючи нам зміцнювати впевненість у тому, що ми рухаємося в правильному напрямку, або зупиняючи нас, коли нова функція виявилася занадто складною.

Спасибі за ваш відгук!

А що далі?

Після святкування випуску tapir 1.0 ми повернемося до важкої роботи! Окрім зусиль зі стабілізації додаткових модулів, про які я згадував раніше, є також деякі захоплюючі функції, над якими ми б хотіли попрацювати. Прикладами цього є створення підтримки gRPC ендпоінтів, інтеграція з CDK Amazon або з безсерверними стеками Google/GCP та Microsoft/Azure. Існує також багато дрібних функцій і доповнень, які не вимагають змін в основних структурах даних, але потребують часу. Якщо ви хочете допомогти, повний список є на GitHub!

Зрештою, вам — користувачам — вирішувати, куди тапір піде далі. Приєднуйтесь до нашої спільноти, дайте нам знати, які функції та інтерпретатори є найбільш корисними, яких не вистачає, що легко зробити з tapir, а що має бути простіше.

Повертаючись до нашої загальної мети — спрощення процесу розробки, підтримки та документування HTTP API, чи можемо ми зробити краще? Ми вже переклали багато роботи на компілятор, щоб скоротити цикл зворотного зв’язку та усунути цілий клас помилок, які в іншому випадку вимагали б написання тесту (або, гірше, ручного тестування!). Але це не означає, що це кінець шляху!

Ваш наступний крок: скористайтеся тапіром і створіть свій перший проект на основі тапіра вже сьогодні!

Кінець перекладу.

Думки автора статті

Я давно спостерігаю за tapir, з самого початку проекту у 2018му році, раніше в мене були побоювання — використоввувати цю лібу чи ні, через те що бінарна сумісність ламалася у мінорних релізах, але фічі які пропонував тапір завжди виглядали привабливо: тайпсейф опис роутів, генерація OpenAPI, серверів і клієнтів на основі цього опису, з можливістю обирати бекенди, відокремлення опису АПІ від бізнес логіки та мінімум бойлерплейту. Тепер коли вийшов стабільний реліз я можу з більшою впевненостю затягнути тапір на свої продакшн проєкти. Якщо вас зацікавила ідея бібліотеки також рекомендую вам поглянути на sttp — це так само фасад, але для клієнтських HTTP бібліотек, який має безліч інтеграцій, спрощує тестування і чудово співпрацює з tapir, цю бібліотеку ми давно використовуєм на своїх проектах і вона показала себе дуже корисною.

А тепер до опитування української scala спільноти.

У зв’язку з виходом стабільної версії Tapir, ми організували опитування в новоствореномму телеграм чаті Scala Ukraine (доречі доєднуйтеся, ми будем раді бачити нові обличчя і старі також 😉).

(В голосуванні можна було обрати декілька опцій відразу, бо на роботі можуть використовуватися одночасно декілька ліб, а також тапір обов’язково має бекенд лібу)

Виявилося, що найчастіше серед опитуваних використовють бібліотеку Akka HTTP. Ця технологія де-факто є стандартом індустрії у Scala, бібліотека для якої написано багато інтеграцій, вона чудово задокументована і перевірена роками в бою. Також дуже часто використовується http4s, що демонструє тренд на чисто функціональне програмування в спільноті. Finagle/Finch — це твітер стек, він доволі мачурний і існує давно, імплементує багато цікавих фіч, як, наприклад, адмінка з коробки, але зараз він не на перших шпальтах новин про скалу, трохи в тіні, тому бачимо невеликий процент використання порівяно з іншими. Тапір також має не так багато прихильників, але це молода технологія, яка тільки-но стабілізувалася, тому в майбутньому ми, можливо, побачимо збільшення частки проектів з тапір. Як це не дивно, але і Spring фреймворк також має свою долю в Scala розробці, але не домінуючу. Колись дуже популярний фреймворк Play 2, який нещодавно віддали на підтримку в opensource-спільноту, зараз втратив минулу славу, але все ще є гарним варінтом для тих, хто тільки входить у Scala, переходячі, наприклад, зі Java/Spring. Остання частка вказана як «Other» — це більш нішеві бібліотеки, такі як zio-http, зроблений спеціально для екосистеми бібліотек на основі ZIO, та cask, що є портом пітонівського Flask на Scala.

Дякую, що дочитали статтю до кінця! Якщо вам цікава ця та інші теми, пов’язані з розробкою на Scala, будь ласка, доєднуйтесь до нашого телеграм каналу.

Також, буду радий вашим думкам в коментарях.

👍ПодобаєтьсяСподобалось4
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Чи є зараз сенс починати вивчати Scala 3, чи все ж таки з версії 2?

Залежить від того чи ви хочете швидше вже на проект попасти, тоді краще Scala 2, на третій ще не так багато проєктів. Якщо ж вам все одно або ви хочете писати щось для себе і знуля, то рекомендую починати вже Scala 3. Загалом же багато чого співпадає в цих версіях, тому якщо ви знаєте Scala 2 вже на достатньо хорошому рівні, то для вас вивчити Scala 3 буде не складно. Також майте на увазі, що екосистема скали ще не цілком готова для Scala 3, тому можуть бути поодинокі випадки бібліотек які не до кінця підтримують Scala 3, і там треба самому портити.
На цю тему, доречі, можете почитати мою статтю hackernoon.com/...​obie-for-ci-notifications, там є декілька слів про це.

По напрямкам — цікавить використання Scala для: Big Data, Data Engineering....

Тоді 100% зараз краще робити ставку на Scala 2, введення всибічної і стабільної підтримки Scala 3 для цих напрямків займе якийсь час

Підписатись на коментарі