Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Uwolnij swoje API od bólu z Smithy4s

Uwolnij swoje API od bólu z Smithy4s

W życiu większości backendowych projektów przychodzi moment, gdy trzeba zdefiniować jakieś API. Implementujemy dla nich route'y, dokumentujemy je, czasem piszemy klienta. Wykonujemy praktycznie tę samą pracę kilka razy - w naszych endpointach są wciąż te same ścieżki, a jednak nie mamy "jednego źródła prawdy". I wtedy wchodzi Smithy, cały na biało!
W prezentacji pokażę, jak Smithy (i smithy4s) umożliwia definiowanie API w jednym miejscu i budowanie dla niego serwera, klienta, a także CLI - w przyjazny dla Scali i jej toolingu sposób. Porównam też wady i zalety rozwiązania, jakie oferuje Smithy, z alternatywami (OpenAPI, tapir, http4s-rho etc.).

Linki ze slajdu z linkami:

- https://linktr.ee/kubukoz
- https://smithy.io
- https://disneystreaming.github.io/smithy4s
- https://youtu.be/3GpZzu4guTE
- https://youtu.be/kvBX9u6uRaE
- https://blog.indoorvivants.com/2022-06-10-smithy4s-fullstack-part-1

Jakub Kozłowski

January 23, 2023
Tweet

More Decks by Jakub Kozłowski

Other Decks in Programming

Transcript

  1. Uwolnij
    Uwolnij
    swoje API od
    swoje API od
    bólu z
    bólu z
    smithy4s
    smithy4s
    Jakub Kozłowski
    Jakub Kozłowski

    View Slide

  2. Plan na dziś
    Plan na dziś
    częste błędy i problemy: przyczyny
    i skutki

    smithy: czym jest, o co w tym
    chodzi

    jak Smithy pomaga rozwiązać te
    problemy

    View Slide

  3. 1/3
    1/3
    Porozmawiajmy
    Porozmawiajmy
    o błędach
    o błędach
    Zacznijmy od tego...

    View Slide

  4. Błędy zaczynają się od nas.
    Przede wszystkim:
    nie jesteśmy idealni

    nie jesteśmy maszynami

    zdarzają się pomyłki

    View Slide

  5. Komunikacja
    Komunikacja
    Mamy błędy w komunikacji.
    W komunikacji jest naprawdę bardzo dużo okazji do pomyłek.
    decydujemy co trzeba zrobić i dlaczego.
    często już tutaj zdarza się nie dogadać - komunikacja jest po prostu
    komunikacja jest po prostu
    TRUDNA
    TRUDNA.
    Jest to z wielu powodów:
    A nawet nie zaczęliśmy jeszcze pisać kodu!
    Co może wyniknąć z takich pomyłek?
    Rozmawiamy z innymi zespołami

    naszymi stakeholderami

    użytkownikami

    bariery językowe, kulturowe

    implicit bias

    opinie

    błędy! Może po prostu nie usłyszeliśmy dokładnie całego zdania, albo
    zapomnieliśmy czegoś zanim planowaliśmy to zapisać.

    View Slide

  6. Źle zrozumiane
    Źle zrozumiane
    wymagania
    wymagania
    Co do tego, co ma się znaleźć w
    naszym API, albo jak my mamy
    używać czyjegoś.

    View Slide

  7. Pomijanie istotnych
    Pomijanie istotnych
    detali
    detali
    Brakujące pola, wymagania dotyczące
    właściwości danego pola...

    View Slide

  8. Rozwiązywanie
    Rozwiązywanie
    złego problemu
    złego problemu
    I najgorsze
    Zdarza się, że po prostu zabieramy
    się za rozwiązywanie problemu, który
    nie istnieje, albo budujemy
    rozwiązanie które nie ma się nijak do
    tego problemu, który jest.
    Ogromna strata czasu (wielu osób i
    zespołów)

    View Slide

  9. I to nawet nie
    I to nawet nie
    wszystko!
    wszystko!
    Wiele innych problemów może
    wyniknąć z błędów i niejasności w
    komunikacji, ale te wymienione
    powinny dać Wam jakiś obraz
    możliwych komplikacji.
    Ale wyobraźmy sobie, że udało nam
    się przebrnąć przez fazę planowania, i
    zabieramy się do implementacji
    naszego API!

    View Slide

  10. Implementacja
    Implementacja
    Co może pójść nie
    Co może pójść nie
    tak?
    tak?

    View Slide

  11. Pomyłki przy
    Pomyłki przy
    pisaniu
    pisaniu
    literówki

    kod klienta się rozjeżdża

    kod serwera się rozjeżdża

    klient/serwer do siebie nie pasują

    ten sam endpoint definiowany w
    każdym kliencie/serwerze, więc
    problem mnoży się

    View Slide

  12. Problemy z
    Problemy z
    dokumentacją
    dokumentacją
    nie ma jej, albo

    Nie zgadza się z tym, co robi
    serwer

    Zdarza się częściej, niż by się
    chciało

    Nawet w dojrzałych technicznie
    organizacjach

    View Slide

  13. Utrudnienia w
    Utrudnienia w
    utrzymywaniu
    utrzymywaniu
    ciężko wykryć zmiany naruszające
    kompatybilność

    reszta zespołów nie wprowadza
    koniecznych zmian

    ciężko np. usunąć stare API które
    od dawna jest "deprecated"

    View Slide

  14. 2/3
    2/3
    Smithy na
    Smithy na
    ratunek
    ratunek

    View Slide

  15. Czym jest Smithy?
    Czym jest Smithy?

    View Slide

  16. Język
    Język
    opisu
    opisu
    interfejsu
    interfejsu
    (IDL -
    (IDL -
    Interface
    Interface
    definition
    definition
    language)
    language)
    operation GetWeather
    {
    input := {
    @required
    city: String
    }
    output := {
    @required
    weather: Weather
    }
    }
    structure Weather {
    @required
    degrees: Integer
    details: String
    }
    Niewielki język, ograniczona ilość
    feature'ów

    Rozszerzalny dla użytkowników

    Nie ma tu detali np. HTTP (ale da
    się je dodać)

    View Slide

  17. Stworzony przez AWS
    Stworzony przez AWS
    używany wewnątrz do budowania
    wszystkich API

    używany w SDK (Java, JS, Rust...)

    używany też w SXM, DSS

    View Slide

  18. Niezależny od
    Niezależny od
    protokołu
    protokołu
    nie tylko HTTP, nie tylko REST

    najpierw modelujemy domenę,
    implementacja to detal

    zależy od interpretacji

    możemy budować własne
    protokoły/transporty

    np. Jest otwarty PR do bsp
    definiujący ten protokół w Smithy i
    generujący kod do bsp4j

    View Slide

  19. Czytelny i zwięzły
    Czytelny i zwięzły
    dla maszyny i dla człowieka
    Czytelny dla maszyny, bo jest deklaratywny:
    Da się to opisać jako struktura danych, więc można analizować bez rozumienia
    konceptów takich jak "if".
    W przypadku np. Http4s, nawet wtedy nie byłoby to możliwe.
    Czytelny dla człowieka, bo ma prostą składnię bez zbędnych informacji
    dla maszyny:

    umożliwia precyzyjną interpretację

    da się generować kod

    łatwe budowanie/rozszerzanie narzędzi

    można ustalać standardy i sprawdzać czy API się ich trzymają, np.

    spójne wersjonowanie API w całej firmie

    spójny kształt odpowiedzi z błędami

    dla człowieka:

    da się to czytać w Pull Requestach

    da się to pisać bez specjalnego edytora

    jeśli reszta nie przekonuje, przynajmniej nie jest to YAML

    View Slide

  20. Przykład HTTP
    Przykład HTTP namespace hello
    use alloy#simpleRestJson
    @simpleRestJson
    service WeatherService {
    operations:
    [GetWeather]
    }
    @http(
    method: "GET",
    uri: "/weather/{city}"
    )
    @readonly
    operation GetWeather {
    ...
    }

    View Slide

  21. 3/3
    3/3
    Jak Smithy
    Jak Smithy
    rozwiązuje
    rozwiązuje
    problem?
    problem?

    View Slide

  22. Ułatwia
    Ułatwia
    komunikację
    komunikację
    Język precyzyjnie opisuje API, więc nie
    ma miejsca na nie zrozumienie drugiej
    osoby

    Przegapienie pola w dyskusji zostanie
    zauważone w pull requeście
    definiującym API

    W podejściu API-first możemy łatwo
    pracować z osobami nie znającymi
    naszego języka programowania i
    bibliotek

    View Slide

  23. Jedno źródło
    Jedno źródło
    prawdy
    prawdy
    Dokumentacja, klient i serwer nie
    "rozjadą" się (dzięki temu że
    maszyny mogą to czytać)

    Definicję możemy dystrybuować
    przez udostępnianie plików np.
    GitHub assety, JARy w artifactory
    albo wtyczka do build toola (sbt)

    nie tylko łatwe do napisania, ale
    też do utrzymania

    View Slide

  24. Niezależny od
    Niezależny od
    języka
    języka
    Ja wiem, że kochamy Scalę i
    chcielibyśmy żeby wszyscy jej używali

    ale nie tylko Scalą projekt żyje ;)

    np. Urządzenia mobilne, frontend

    abstrakcja nie cieknie, API nie jest
    zależne od konwencji w języku. Nie
    musimy znać bibliotek.

    można zapomnieć o eDSLach
    routingowych (implicity, makra, pattern
    matching)

    View Slide

  25. Smithy4s
    Smithy4s
    Biblioteka do generowania kodu i
    pracy z Smithy w Scali

    Generuje czytelny kod i metadane z
    definicji w Smithy

    Zaprojektowana dla rozszerzalności
    (Bez zależności w core)

    Integruje się z http4s, można
    budować własne integracje

    Klient/serwer/CLI za darmo

    View Slide

  26. Co dostajemy?
    Co dostajemy?
    def server(impl:
    WeatherService[IO]):
    HttpRoutes[IO]
    def client(c: Client[IO]):
    WeatherService[IO]

    View Slide

  27. Serwer (routes)
    Serwer (routes)
    val impl: WeatherService[IO] = ...
    def run: IO[Unit] =
    SimpleRestJsonBuilder
    .routes(impl)
    .resource
    .flatMap { routes =>
    // normal http4s stuff from now on
    EmberServerBuilder
    .default[IO]
    .withHttpApp(routes.orNotFound)
    .build
    }
    .useForever

    View Slide

  28. Klient
    Klient
    EmberClientBuilder.default[IO].build
    .flatMap {
    SimpleRestJsonBuilder(WeatherService)
    .client(_)
    .uri(url)
    .resource
    }

    View Slide

  29. OpenAPI
    OpenAPI
    smithy4s.http4s.swagger
    .docs[IO](WeatherService):
    HttpRoutes[IO]

    View Slide

  30. Linki
    Linki
    Slajdy: będą na
    – linktr.ee/kubukoz
    kontakt: też ;)

    – smithy.io
    – disneystreaming.github.io/smithy4s
    – Scaling APIs with Smithy
    – Revisiting visitors: a talk about
    generalising serialisation
    – smithy4s fullstack (blogpost series)

    View Slide

  31. See also
    See also
    Smithy Playground
    Smithy Playground
    github.com/kubukoz/smithy-playground
    pomijając czy jest to przydatne,
    potrzebne czy wartościowe w
    jakikolwiek sposób

    fajna zabawa i dało mi możliwość
    nauczenia się wielu rzeczy, np.
    Budowania serwerów LSP

    o tym też może kiedyś będzie
    prezentacja

    zapraszam do subskrypcji ;)

    View Slide

  32. Bonus
    Bonus
    Dlaczego nie
    Dlaczego nie
    wystarczy X?
    wystarczy X?

    View Slide

  33. OpenAPI
    OpenAPI
    ograniczone do HTTP

    ciężko budować na tym narzędzia (np. Brak
    walidacji w standardowych narzędziach dla
    JVM)

    generowanie kodu to tak naprawdę bootstrap
    dla projektu

    podejście do codegenu nie jest tym czego
    potrzebuję

    jest wspierane w standardowych narzędziach
    Smithy. Musimy tylko trochę to konfigurować
    jeśli definiujemy własny protokół.

    View Slide

  34. tapir, endpoints4s,
    tapir, endpoints4s,
    Udash, http4s-rho ...
    Udash, http4s-rho ...
    ograniczają się do Scali

    korzystają ze skomplikowanych feature's
    języka tj. Implicity, makra

    (tapir kombinuje z generowaniem z openapi
    - brak postępu od ok. roku)

    głównie HTTP, choć tapir powoli idzie w
    kierunku wsparcia gRPC

    ale: aktualnie np. Tapir wspiera znacznie
    więcej frameworków. Choć dodanie nowego
    frameworka nie wymaga wielkiej ilości pracy,
    smithy4s część tej pracy załatwia już za nas.

    View Slide

  35. gRPC, GraphQL,
    gRPC, GraphQL,
    RSocket...
    RSocket...
    te protokoły/specyfikacje mają specjalne zastosowania

    np. graphql skupia się na zapytaniach o konkretne
    elementy i na grafach. IMO głównie przydatny dla klientów
    frontendowych/na urządzeniach użytkownika

    mogą wymagać innego sposobu myślenia, innych
    narzędzi, a jednak REST/HTTP są teraz standardem i
    Smithy pozwala nam zacząć z tego punktu wyjścia i
    potencjalnie przenieść się na inny protokół później

    nic nie stoi na przeszkodzie żeby wspierać nawet kilka
    protokołów naraz

    możemy je "wywnioskować" z definicji w Smithy

    np. Jak dana rzecz ma być reprezentowana w
    protobuf

    warto wspomnieć o "apply" w smithy

    View Slide