Pavle nehnevajte sa, ale dnesny diel ma trocha sklamal. V podstate ste len popisal kostry implementacie jednoducheho http servera v niektorych jazykoch, co su veci, ktorych su na webe mraky (pre lubovolny programovaci jazyk).
Skor som ocakaval nejake uzitocnejsie informacie, ako napr. ake technologie su pre jednotlive jazyky k dispozicii, ich vyhody/nevyhody/vhodnost pouzitia (napr. aplikacny server vs. standalone v Java svete, Spring Boot, deployment, kontainerizacia,...).
Chybaju mi tam odporucane konvencie pre REST/HTTP (ci uz HTTP metody pre jednotlive operacie, tvorba URL pre endpointy, navratove kody pri beznych chybach). Pevne verim, ze sa este o tychto veciach v niektorom dalsom pokracovani docitam (lebo Vas pohlad na vec by ma rozhodne zaujimal).
Na druhej strane velmi ocenujem, ze ste spomenuli swagger (mozno by som sa mu venoval este trocha viac).
V uvodnych dieloch ste si postavili latku dost vysoko a chapem, ze nie je jednoduche taku uroven udrzat (z toho mozno prameni aj moje dnesne sklamanie). Napriek tomu dakujem za serial a tesim sa na dalsi diel ;-)
Díky za zpětnou vazbu.
Já se právě rozhodoval, jak za sebe zařadit dva článku:
1) teorie okolo REST API, sémantika metod, co jsou to zdroje (resources) a jak je správně psát, vztah mezi resource a například daty v databázi atd.
2) vytvoření jednoduché služby, ideálně s využitím Swaggeru (resp. OpenAPI 2/3), vyzkoušení Swagger UI a curlu (jsou to možná základy, ale spousta lidí opravdu začíná od nuly)
No a protože v kurzech, které jsem vedl, byl vždycky problém s tím, že se do lidí nacpe teorie (bez ošahání v praxi) a až potom si to vyzkouší (mezitím tu teorii zapomenou), tak jsem zvolil opačný postup: nejdřív ukázat jednoduchou službu, kterou budeme dále rozšiřovat ve druhém článku, tentokrát už se znalostí teorie.
Asi to bylo špatně...
Čiže to podstatné a zaujímavé ešte len príde ;-) V tom prípade je to ok.
Možno ešte ešte posledná drobnosť, keď už do toho rýpem - možno by som sa v ďalších príkladoch obmedzil na jeden jazyk/framework - je imho zbytočné ukazovať to isté 2x (osobitosti implementácie v iných jazykoch si ľudia vedia dohliadať, pokiaľ tam nie je je vyslovene nejaká zaľudnosť). Ale zase Vám nechcem do toho moc kecať, lebo robíte inak veľmi dobre.
Popis specifikace API je nejvetsi slabina RESTu. Ve firme hledame nastroje a vlastne i format, ve kterem popsat stredne velke API. Kdyz pominu to, ze se stredne dlouhy yaml (dejme tomu 1500 radek) nekomu spatne cte (a nejen cloveku, ale i automatickym mergum pomoci gitu), pak je tu otazka, jakou specifikaci vlastne zvolit. OpenAPI 2 vs OpenAPI 3 vs RAML. Nastroje jsou taky bida, ale neco uz je. V holem editoru se to neda. A bacha na taby, myslim ze ani ty Pavle tam nemas validny yamly, proste pri copy pastovani se to obcas nekde rozsype.
Podle mě je obecně špatný přístup vytváření dokumentace nezávisle na kódu a programování podle specifikace. Naopak generování dokumentace z kódu není problém, všechny lepší frameworky to umožňují. Třeba django https://www.django-rest-framework.org/topics/documenting-your-api/
Programování podle specifikace budete vždy potřebovat – u těch REST služeb máte vždy minimálně dvě strany, vygenerovat dokumentaci z kódu můžete jen na jedné straně, na druhé pak musíte napsat kód podle té specifikace. Ideální je, když ta specifikace je ve strojově čitelném formátu, pak je možné z ní nechat vygenerovat struktury v příslušném programovacím jazyce. Já ty generátory kódu nerad používám pro produkční kód, ale třeba pro prototypování je to výborná věc.
Jinak je zajímavé, že ve světě XML je tohle vyřešené už spoustu let. Teď se to holt znova objevuje ve světě JSONu a vznikají OpenAPI (tam je alespoň proti WSDL něco trochu nového) nebo GraphQL (primitivní nápodoba XQuery).
Fajn. Takže vaše předchozí dva komentáře můžeme škrtnout, protože neplatí, a zbývá nám tu ten problém uvedený v prvním komentáři vlákna, totiž že velkou slabinou současného RESTu je to, jak vytvářet specifikaci API. Protože vyjít z kódu je sice hezká věc, ale z toho dostanete menší a tu nejméně zajímavou část specifikace. Z toho dostanete jen názvy, struktury a jednoduché podmínky jako povinnost, maximální délku textu, rozsah hodnot apod. Pak to ale potřebujete obohatit o popis významu (což už je normální dokumentace, i když je obvykle součástí zdrojového kódu) a pak ještě o popis závislostí, postupů a předpokladů (které jsou sice v kódu zapsané, ale vyrobit z toho automaticky specifikaci nikdo neumí).
@Filip Jirsák
@gill
@Ondřej Němeček
To vychází asi z nepochopení té obvyklé poznámky, že podle testů jde poznat, resp. z testů jde vyčíst jak se aplikace, resp. daný kód, chová nebo má chovat a že je to svým způsobem dokumentace kódu
To často je a lze to tak použít, ale není to hlavním účelem testů, není to ani nutná ani postačující podmínka a rozhodně to IMO nemá a nemůže nahradi specifikaci, protože právě ze specifikace se často právě vychází když se zachycují limity a stavy v testech.
12. 7. 2019, 12:31 editováno autorem komentáře
@Tomáš Procházka: Ne, to není příklad testu, který by byl zároveň specifikací. To je jenom ukázka toho, že se příklady v dokumentaci automaticky testují. To je samozřejmě užitečná vlastnost, nefunkční příklady v dokumentaci jsou problém – ale je to něco úplně jiného, než o čem teoreticky píšou gilll nebo Ondrej Nemecek.
@Tomáš Procházka
Ve finále jste ten kód stejně musel popsat, jenom jste ty samotné údaje nezachytil do textu ale kódu, takže jste jenom k normální specifikaci přidal složitost ve formě nutnosti znalosti zvoleného jazyka a všech jeho možných sideefektů - tedy např. naprosto neuchopitelné pro běžnou tel. podporu atd.
13. 7. 2019, 00:01 editováno autorem komentáře
Ak by sa za špecifikáciu považovali ukážkové volania (aj s hlavičkami requestov a responsov), tak imho by mohla vyhovovať vhodne napísaná dokumentácia s rest-docs knižnicou (spring/java). Viď ukážka niekde ku koncu tuná https://g00glen00b.be/spring-rest-docs/
Osobne sa mi páči, že dokumentácia používa kusy skutočne vykonaných requestov z integračných testov a aserty z tých testov sú vlastne vygenerovaná dokumentácia. Takto sa dokumentácia (vpodstate špecifikácia) nerozíde s kódom tak jednoducho.
Ukázková volání nejsou specifikace. Mohou být její součástí, jednoduché věci často člověk pochopí lépe z příkladu než ze specifikace, pro jednoduché a nedůležité věci často může ten příklad stačit. Ale rozhodně nestačí vždy. Jen pomocí příkladů se učí zvířata, lidské jazyky právě umožňují ta omezení příkladů překonat a komunikovat o složitějších věcech.
Obecně špatné to možná je ale v konkrétních případech v tom problém nevidím.
Proč myslíte, že si vznikl connexion? Někdo měl právě opačný názor: https://github.com/zalando/connexion#why-connexion
11. 7. 2019, 16:11 editováno autorem komentáře
Ten opačný názor byl princip "API First" viz také https://opensource.zalando.com/restful-api-guidelines/
No mám opačnou zkušenost, protože to vede k tomu, že se dokumentace nakonec neudělá, je zastaralá apod. A potom někdo (třeba i o dobré vůli) změní nějaký API call a je problém (vím vím, verzování API, ovšem v reálném světě je to chaos). Navíc když je popis v RAMLu/Swaggeru, tak se to už může implementovat v různých jazycích, opačně je to dost přes ruku.
Ahoj Honzo.
jj pro monolity s velkym mnozstvim koncovych bodu to muze byt zlo (vim o cem mluvim, nam par mikrosluzeb rozrostlo do monolitickych rozmeru :)
RAML uz bych asi nechal byt, IMHO je pro OpenAPI vice nastroju.
Ad validita: to je docela dobre mozne, zkusim to projet linterem a opravit (i kdyz v clanku to bude porad spatne, protoze redakcni system v kombinaci s prohlizecem taby a spol nedaji dobre nikdy:). Diky za upozorneni!
Pokud je to dlouho běžící "transakce", tak proč to nenamodelovat jako eventy (v event sourcingu tomu vzoru říkají Saga)? POST pak nezapisuje přímo data, ale dává požadavky do fronty. Ten event pak může být nastavení odložené akce, když se něco nepovede (nebo vyprší čas).
Něco jako:
POST /users registrace uživatele -> 201 Created; id
-> POST /queue smaž uživatele id v čase t+1 den -> 202 Accepted
po potvrzení emailu:
-> POST zruš příkaz na smazání uživatele (nebo rovnou DELETE)
Uvedl jste tu nejednodušší variantu, kdy na POST/CREATE máte kompenzační transakci DELETE.
A myslím si, že jste nepopsal SAGA pattern, ale 2PC https://en.wikipedia.org/wiki/Two-phase_commit_protocol
Tady jako commit nakonci smažete naplánované kompenzační transakce.
Saga udržuje nějaký stav automatu a emituje další akce. V mém případě je jedna taková schovaná, ten požadavek na potvrzení emailu se někde přece musí evidovat. Takže vznikne nějaký záznam stavu někde (saga) - v reakci na event EmailPotvrzen se ukončí. Její reakce na event Timeout zase spustí tu kompenzaci (resp pošle event UživatelSmazán).
Uznávám, že v tom komentáři to nebylo dost důkladně rozebrané. Ale tento přístup umí řídit i složité procesy.
Pokud to je nějaký proces rozdělený na kroky anebo déle běžící proces tak tam asi opravdu pomůže SAGA:
- https://microservices.io/patterns/data/saga.html
11. 7. 2019, 15:09 editováno autorem komentáře
Dobrý den,
jak píšou kolegové, buď se dá použít SAGA nebo přímo kappa architektura (https://www.root.cz/clanky/zpusoby-ulozeni-dat-v-aplikacich-zalozenych-na-mikrosluzbach/#k14), ale to už záleží na konkrétních požadavcích (protože někdy to vypadá, že potřebujete transakce a nakonec se ukáže, že to vlastně není nutné).
Ano, vím co je SAGA pattern, ale abych ho mohl implementovat, potřebuji kompenzační transakci. Tedy smazat vytvořené, obnovit smazané, vrátit změněné do původního stavu. Tyto funkce bych měl vytvářet spolu.
Proto mi zde REST přijde nevhodný a do budoucna jako i možný technický dluh. Neboť netuším, jak bych dělal reverzní akci na PUT/PATCH když nevím původní stav.
Ano, ale abych se choval tak, jak praví REST, tak budu volat POST pro vytvoření záznamu o modifikaci/mutaci. Možná by pro tento případ asi šel použít PATCH. Ale PUT není editace, to je kompletní nahrazení daného resource.
https://www.thoughtworks.com/insights/blog/rest-api-design-resource-modeling
není tak kotva, tak hledejte REST without PUT and CQRS
A když už dělám takovéhle ústupky, není lepší se na celý REST vyprdnout a dělat JSON-RPC?
REST je určitě super jako API nad datovým skladem, ale v mikroservisách ho nechápu.
Tak jsem tomu věnoval trochu víkendu, doplnil znalosti, odpočinul si a polevil v zatvrzelosti.
Špatně jsem pochopil význam těch kompenzací.
Jen si to pokusím zde shrnout.
REST pouze tedy slouží pouze jako spouštěč sledu událostí. Dále vše proudí jako event, a až pro ty je tedy potřeba definovat kompenzace.
14. 7. 2019, 21:41 editováno autorem komentáře
Mě osobně se článek nelíbil, docela mi vadí, že se zabývá konkrétními věcmi, a navíc ještě špatně
Například implementace SSL je hodně špatná. Prvotně SSL většinou spravují administrátoři, stálo by za to říci, že toto v aplikaci vůbec nemá být řešeno, a měl by se o to starat webový server v režimu reverzní proxy, aby to byly administrátoři schopni spravovat.
Další věc, co se týká SSL by bylo fajn říci, že by měl být nějaký Root certifikát, a neschvalovat jednotlivé certifikáty.
Návod zde uvedený mi přijde, jak kdyby ho psal programátor bez zkušeností s architekturou či reálným provozem. U mikroslužeb je mnoho otázek, které by si člověk měl řešit, to jestli se použije REST, SOAP nebo XML-RPC a jestli v Go nebo Pythonu je snad ta poslední otázka, kterou bych si kladl.
Je tu mnoho věcí, které je potřeba řešit, např.:
- co dělat, když se změní API k části aplikace, a vyjde verze mikroslužby nekompatabilní s jinou službou
- co dělat v případě přetížení aplikace
- chování při chybách
atd.
Problém ovšem je, jak se rozhodnout mezi REST API a SOAPem, který zmiňujete, když si to člověk sám neodzkouší na pár příkladech, ideálně i s nasazením někam do public cloudu. Třeba tady zmiňovaný REST s Flaskem je v praxi moc fajn a doufám, že příště budou popsány i HTTP metody, kódy odpovědí a další důležité věci, možná i RAML. A kdyby byly potom i ukázky SOAPu, tak by potom bylo jasné, co si vybrat. Teoreticky je to sice pěkné popsat, ale není nad praktické odzkoušení.
PS: IMHO se SOAP do světa mikroslužeb moc nehodí, ale to je opravdu jen moje IMHO, SOAP máme jen v monolitech, kam "pěkně" zapadá :-)
Mňa by zaujímalo v ďalších dieloch tiež porovnanie rest-ov vecí ako restql, či graphql. Tiež nejaká teória, ktorá by smerovala aj k HATEOAS a možným formátom (ako napríklad HAL). Osobne totiž vyvíjam v springboote backend, kde používam json+hal reprezentáciu a príde mi to minimálne zaujímavé a použiteľné. Ako hlavný prínos beriem, že server je zdrojom relácií (url linkov), ktoré je možné nad daným resorsom vykonať a teda klient si nemá generovať nejaké url podľa templejtov "zbrucha".