Jak je o mě jistě známo, jsem svého druhu dinosaurus. Stále ještě programuji v Javě a dokonce používám takové předpotopní technologie, jakými jsou SOAP webové služby. Ale abych věděl, o čem všichni mluví, občas si přečtu i nějakou tu knihu o novinkách. Onehdá jsem studoval Scalu (vřele doporučuji) a teď jsem zrovna dočetl knihu RESTful Web Services od pánů Richardsona a Rubyho.
Pokud se chcete dozvědět co to vlastně ten REST je, tak je to ta pravá kniha pro vás. Dozvíte se tam hodně o filozofii RESTu, o jeho výhodách, o tom jak takové služby navrhovat a jaké technologie k tomu používat. Většina příkladů je sice napsána v jakémsi obskurním jazyce jménem Ruby, ale pochopí je i Javista.
Kniha je napsána i docela čtivě, musíte jenom překousnout demagogii typu „REST je nejlepší, RPC je k ničemu“. Co se mi hodně líbilo je to, že jsem snad konečně pochopil principy RESTu. Je to totiž jedna z těch technologií, o kterých všichni mluví, ale málokdo ji plně rozumí. Pokusím se tu shrnout to nejdůležitější.
Dělej to jako Web
To je asi hlavní krédo RESTovaných aplikací. Web funguje, je snadno použitelný, dobře škáluje, tak proč bychom nemohli dělat webové služby úplně stejně. Je tu veliký rozdíl v tom, že normální web je určen pro lidi a webové služby pro stroje. Ale proč nepoužít stejných osvědčených principů?
Zdrojově orientované
Zdrojově orientované je můj geniální překlad pro Resource-Oriented. Znamená to, že se místo na služby, orientujeme na zdroje. Místo na slovesa typu udělej, založ, smaž se soustředíme na podstatná jména typu účet, zákazník a podobně. Je to podobné jako objektové programování, v něm bychom se měli soustředit hlavně na objekty samotné, jejich operace by z nich měli vyplývat. Stejné princip by měl platit u RESTu. Tady musím dát příznivcům RESTu za pravdu, normální WS jsou silně funkcionální, o objektech tam není ani památky. Na druhou stranu je spousta služeb, které se jako RESTové jenom tváří, ale v podstatě jsou také jen RPC.
Adresovatelnost
Další důležitý princip je adresovatelnost. Každá věc která je v daném systému důležitá, by měla mít vlastní adresu. To znamená, že každá instance objektu, by měla mít vlastní URI. Hodně to souvisí s orientací na zdroje. Každý zdroj, má svoji adresu, například takovouto http://www.exaple.com/v1/bank/client/12345. Pokud použijeme přirovnání k objektům, tak URI je podobná referenci.
Propojenost (Connectedness)
Propojenost hodně souvisí s předchozími body. Znamená to, že jako výsledek operací dostávám odkazy na další zdroje. Pokud se například zeptám na seznam klientů banky, měl bych dostat seznam jejich URI a ne jen jejich ID. Pokud bereme URI jako referenci na instanci, tak to dává smysl.
Idempotentnost
Krásné české slovo označující, to, že by mělo být možné zavolat jednu službu vícekrát, aniž by hrozilo něco ošklivého. To znamená, že operace by pokud možno neměly mít žádné vedlejší účinky. Pokud mění stav systému, měly by to dělat tak, aby se nic nestalo, pokud ho změní vícekrát. Je překvapivé, že takových operací je valná většina. Nic se nestane, pokud například vícekrát nastavím stejnou hodnotu nebo něco smažu. Jsou tu samozřejmě výjimky, ale i u těch se dá idempotentnost zařídit.
Bezstavovost
Bezstavovost je často nepochopené téma. A není se čemu divit, je to hodně matoucí. Pokusím se to ale vysvětlit. Bezstavovostí se v tomto případě myslí, že webová služba neukládá stav klienta. Rozhodně tam není žádná session. Klient může navíc volat operace v libovolném pořadí, takže by se nemělo objevovat žádné flow jak ho známe z normálního webu. Ale aplikace samotná samozřejmě stav má. Takže si samosebou pamatuje, kolik kdo má na účtu, kam chce letět na dovolenou nebo kam rád chodí do restaurace. Ale nejedná se o stav klientské aplikace, jedná se o stav zdrojů. V tom je veliký rozdíl.
Bezstavovost je docela rozumný princip, díky ní se například dobře škáluje. Bohužel často k jejímu dodržení musíme švindlovat. Občas prostě potřebujeme držet stav klientské aplikace. V RESTu proto dělají krok stranou a prohlásí stav klienta za stav systému. Takže když potřebují uložit obsah nákupního košíku, řeknou, že to není stav klienta, ale stav aplikace. Nákupní košík je vlastně takový zdroj, jehož stav aplikace naprosto přirozeně drží. Takový košík má pak svoji URI, své operace a je to prostě normální zdroj. Problém vyřešen. Tedy kromě té škálovatelnosti, s ní jsem na tom úplně stejně jako kdybych používal session. (Kvízová otázka. Jak zajistit, aby přidání položky do nákupního košíku bylo idempotentní?)
No zbytek z těch asi 400 stránek tu opisovat nebudu. Radši napíšu proč se budu držet dál normálních (tlustých) webových služeb.
V první řadě se mi nelíbí úzká vazba na HTTP. To je jedna z věcí, která mi ještě nedošla, takže budu rád když mi ji někdo vysvětlí. Na jedné straně čtu, že REST je na HTTP úplně nezávislý. Na druhé straně, je ale REST s HTTP neuvěřitelně úzce spjat. Chcete-li změnit stav zdroje, máte použít HTTP PUT, chcete-li ho smazat, použije HTTP DELETE, chcete zjistit jeho stav, použijte GET. Nastane chyba? Dostanete ten a ten HTTP chybový kód. Tak je to závislé nebo ne? Mě spíš připadá že jo.
Dalším důvodem, proč zatím zůstanu u klasického ošklivého SOAPu je to, že mi vyhovuje. Já prostě nepíši aplikace, které jsou podobné webovým stránkám. Píši věci, které jsou svoji podstatou spíše procedurální než objektové. Navíc mi vyhovuje to, že existuje něco jako WSDL, které je sice ošklivé jak noc, ale které i přes své mouchy funguje. Ano pro REST máme WADL, ale že by byl široce rozšířen se říci nedá.
Také mi vyhovuje, že v SOAPu jsou metadata součástí zprávy a ne protokolu, kterým se zpráva posílá. Prostě mi to připadá bezpečnější. Když volám webovou službu tak volání bohužel často přejde přes několik JMS front a pár HTTP připojení. Takže se na to radši dívám tak, že posílám XML dokument, který přes nějaké složitosti snad doputuje k svému adresátu.
Tím rozhodně nechci říci, že je REST špatný. Pokud bych vystavoval webové služby pro něco, co má svůj ekvivalent ve webové aplikaci, asi bych nad RESTem vážně uvažoval. Protože se ale pohybuji v jiném světě, tak je moje volba jiná. To mi ale nebrání se poučit a pár fint od RESTu okoukat.