RESTful hypermedia aware media type választása erőforrás reprezentáláshoz
Ha valaki járatos a RESTful webservice-ek terén, az átugorhatja a következő bevezető részt. Miről is van szó? A webservice-ek osztott rendszerek esetében egy lehetséges megoldást jelentenek a gépek közötti (M2M) kommunikációra. Rengeteg megoldás van ezzel kapcsolatban, akit érdekel a téma, az olvasson utána. Ahhoz, hogy két gép kommunikálni tudjon egymással, szükség van valamilyen protokollra, amin keresztül folydogálhat az adat, illetve, hogy megkönnyítsük a programozók életét, szükség van valamilyen koncepcióra, amit jó, ha szabvány(ok)ba foglalnak. A webservice-ek esetén a HTTP a jellemző protokoll. A koncepció meg vagy SOA (service oriented architecture) vagy ROA (resource oriented architecture). Hasonlítsuk össze ezt a webbel: szintén HTTP-t használnak, szintén M2M kommunikáció: böngésző-szerver között. Egyedül a koncepció más azért mert HTML dokumentumok megjelenítésére lett kitalálva, nem pedig alkalmazások megjelenítésére. Manapság egyre jellemzőbb, hogy weboldalak helyett webalkalmazásokat írnak. Ezeknél pedig már lehet hasznosítani a webservice-ek nyújtotta előnyöket. Néhány éve még az volt a jellemző, hogy ha egy webalkalmazásnál valamit újratöltés nélkül akartunk megjeleníteni, akkor indítottunk egy AJAX kérést a szerver felé, aztán a válaszban megkaptuk az adatokat JSON-ban, a kliens pedig megjelenítette őket, és mindenki boldog volt. Ez hasonló koncepció, mint amit a SOA követ. A SOA-nál távoli eljárásokat hívunk meg, visszakapjuk a visszatérő értéket valamilyen formában, pl SOAP message, és utána eldöntjük, hogy hogyan dolgozzuk fel. Ennek a koncepciónak az a hátránya, hogyha változik a webservice, akkor változtatni kell a kliensen is. Azért van ez így, mert a kliens vastag: tud arról, hogy mi van a business logic-ban, előre tudja, hogy milyen jellegű az adat, amit kap, és azt hogyan kell feldolgoznia, vagy webalkalmazás esetében megjelenítenie. Ez a koncepció rossz a webre, több okból is. Az egyik, hogy általában egy webalkalmazásnál több eltérő kliens van (pl: mobil, asztali, javascript mentes, stb...) és csak egy szerver. Ha vastag a kliens, akkor minden egyes kliens változatban ugyanaz a business logic-al kapcsolatos kód fog ismétlődni, a kód duplikáció pedig általában rossz karbantarthatóságot és hibákat eredményez. A webalkalmazásoknál nem jó tulajdonság az, hogyha a kliensben egy kicsi hiba van, akkor bedőljön az egész oldal, mert nem tud kommunikálni a szerverrel. És még lehetne sorolni, maradjunk ennyinél... Lényeg a lényeg, a SOA nem húzható rá a webes környezetre szemben a ROA-val, ami direkt ilyen célra lett kitalálva. A ROA esetében szintén távoli eljárásokat hívunk, azonban itt egy kicsit más a koncepció, mint a SOA esetében. A ROA esetében nem csak adatot adunk vissza egy-egy távoli eljárás meghívásakor, hanem visszaadjuk a további lehetőségeket is linkek formájában, ezért van szükség egy hypermedia aware media type-ra, ami képes linkeket tartalmazni. Az ilyen webservice-eknél a kliens vékony maradhat, mert a business logic-ot kizárólag a webservice tartalmazza, a kliensnek elég csak a linkeket követnie ahhoz, hogy kommunikáljon a webservice-el. A kliens tehát csak annyit tud, hogy maga a webservice nagyjából mit csinál (talán még azt se), de arról fogalma sincs, hogy azt hogyan csinálja. Ezért egyzserűen lehet több klienst írni egy webservice-hez, és később módosítani a webservice-t a kliensek megváltoztatása nélkül. Lehetőség van továbbá azonos klienssel eltérő webservice-ek használatára, a kliensek tehát cserélhetőek. Ez egy nagyon rugalmas architektúra, ami webre nagyon jól működik. Ugyanígy működik olyan környezetben is, ahol az adatátvitel a fő szempont, de ott a SOAP használata a jellemzőbb (ami ugye SOA koncepcióra épül).
Az én esetemben van egy SPA-m, ami a böngészőben fut, és ezzel szeretnék a szervertől érkező adatokat megjeleníteni. Elég nyilvánvaló a bevezetőben leírtak alapján, hogy erre a legjobb választás a RESTful webservice-ek. Jelenleg PHP-ban SLIM-et használok szerver oldalra, a kliensnél meg Backbone-t, de ezek több-kevesebb erőfeszítéssel cserélhető dolgok... Amin agyalok, hogy milyen hypermedia aware media type, amit érdemes lenne választani ahhoz, hogy ne csak adatot, hanem linkeket is küldjek a kliensnek. Rengeteg ilyen van: http://amundsen.com/hypermedia/, és azóta még több: https://blog.apigee.com/detail/api_design_harnessing_hypermedia_types. A legtöbbjéről az átlag fejlesztő még nem is hallott... Ami ismerős mindenkinek az a HTML és esetleg az ATOM (RSS formátum). A HTML-nek az a hátránya, hogy lassú a parsolása, és az az előnye, hogy elég gazdag a nyelvezete ahhoz, hogy leírjuk vele, amit akarunk. Nyilván mindegyik media type-nak vannak előnyei és hátrányai. Továbbá vannak best practice-ek megjelenítéssel kapcsolatban is, amiket mikroformátumoknak hívunk. A legegyszerűbb ilyen, ha egy link-nél megadom rel-ben, hogy nofollow. Ilyenkor a google bot tudja, hogy a rangsorolásnál nem kell figyelembe venni a linket. A lapozáshoz szintén van ajánlott mikroformátum, általában a google által kitalált link relation-öket használják rá:
ATOMHTMLHAL+JSONAhogy látható ezek a mikroformátumok nem feltétlen függnek a media type-tól sem, ugyanúgy tudtam a lapozást használni ATOM, HTML, HAL+JSON esetében is. Ami a kérdés nálam, hogy milyen media type-ot használjak és milyen mikroformátumokat mellé? Én jelenleg HTML felé hajlok media type terén, mert azt mobilban is meg lehet jeleníteni, illetve ha nincs js a felhasználónál, akkor asztalinak is jó lesz. De persze meggyözhető vagyok másról, lehet ötletelni, érdekel, hogy mit gondoltok a témáról...
Ami még érdekes, hogyha asztali és mobil megjelenítést akarok, akkor hogyan csináljam. A progressice enhancement 2.0 szerint úgy kellene, hogy a kapott HTML-re kellene építenem még több réteg js kódot és css-t, és csak egy kliensem lenne, ami attól függően, hogy mi elérhető adna hozzá plusz effektet, menüt, stb... Nem tudom, hogy ez hogyan lehetséges egyetlen klienssel. A mobil nézetnél pl kevésbé fontos a részletes menü, inkább az, hogy tartalom legyen, és vissza gombra lehessen kattintani. Ott pl elég lenne az egy-egy kéréssel kapott HTML. Az asztali nézetnél fontos a sok szintes menü, ott kelleni fog egy váz az oldalnak, amibe betölti a menüt és a tartalmat. Először a tartalmat, aztán a visszagombokkal (link rel=up) lépkedve automatikusan feltölti tartalommal a több szintes menüt... Ezzel kapcsolatban van bármi ötlet?
■ Az én esetemben van egy SPA-m, ami a böngészőben fut, és ezzel szeretnék a szervertől érkező adatokat megjeleníteni. Elég nyilvánvaló a bevezetőben leírtak alapján, hogy erre a legjobb választás a RESTful webservice-ek. Jelenleg PHP-ban SLIM-et használok szerver oldalra, a kliensnél meg Backbone-t, de ezek több-kevesebb erőfeszítéssel cserélhető dolgok... Amin agyalok, hogy milyen hypermedia aware media type, amit érdemes lenne választani ahhoz, hogy ne csak adatot, hanem linkeket is küldjek a kliensnek. Rengeteg ilyen van: http://amundsen.com/hypermedia/, és azóta még több: https://blog.apigee.com/detail/api_design_harnessing_hypermedia_types. A legtöbbjéről az átlag fejlesztő még nem is hallott... Ami ismerős mindenkinek az a HTML és esetleg az ATOM (RSS formátum). A HTML-nek az a hátránya, hogy lassú a parsolása, és az az előnye, hogy elég gazdag a nyelvezete ahhoz, hogy leírjuk vele, amit akarunk. Nyilván mindegyik media type-nak vannak előnyei és hátrányai. Továbbá vannak best practice-ek megjelenítéssel kapcsolatban is, amiket mikroformátumoknak hívunk. A legegyszerűbb ilyen, ha egy link-nél megadom rel-ben, hogy nofollow. Ilyenkor a google bot tudja, hogy a rangsorolásnál nem kell figyelembe venni a linket. A lapozáshoz szintén van ajánlott mikroformátum, általában a google által kitalált link relation-öket használják rá:
ATOM
<link rel="first" type="application/atom+xml; type=feed" title="First Page" href="/salesOrders?startIndex=1&count=10" />
<link rel="last" type="application/atom+xml; type=feed" title="Last Page" href="/salesOrders?startIndex=31461&count=10" />
<link rel="previous" type="application/atom+xml; type=feed" title="Previous Page" href="/salesOrders?startIndex=11&count=10" />
<link rel="next" type="application/atom+xml; type=feed" title="Next Page" href="/salesOrders?startIndex=31&count=10" />
<a rel="first" href="/salesOrders?startIndex=1&count=10">First Page</a>
<a rel="last" href="/salesOrders?startIndex=31461&count=10">Last Page</a>
<a rel="previous" href="/salesOrders?startIndex=11&count=10">Previous Page</a>
<a rel="next" href="/salesOrders?startIndex=31&count=10">Next Page</a>
{
_links: {
first: {href: "/salesOrders?startIndex=1&count=10", title: "First Page"},
last: {href: "/salesOrders?startIndex=31461&count=10", title: "Last Page"},
previous: {href: "/salesOrders?startIndex=11&count=10", title: "Previous Page"},
next: {href: "/salesOrders?startIndex=31&count=10", title: "Next Page"},
}
}
Ami még érdekes, hogyha asztali és mobil megjelenítést akarok, akkor hogyan csináljam. A progressice enhancement 2.0 szerint úgy kellene, hogy a kapott HTML-re kellene építenem még több réteg js kódot és css-t, és csak egy kliensem lenne, ami attól függően, hogy mi elérhető adna hozzá plusz effektet, menüt, stb... Nem tudom, hogy ez hogyan lehetséges egyetlen klienssel. A mobil nézetnél pl kevésbé fontos a részletes menü, inkább az, hogy tartalom legyen, és vissza gombra lehessen kattintani. Ott pl elég lenne az egy-egy kéréssel kapott HTML. Az asztali nézetnél fontos a sok szintes menü, ott kelleni fog egy váz az oldalnak, amibe betölti a menüt és a tartalmat. Először a tartalmat, aztán a visszagombokkal (link rel=up) lépkedve automatikusan feltölti tartalommal a több szintes menüt... Ezzel kapcsolatban van bármi ötlet?
Hűha...
Az a furcsa, hogy így álmosan, végigolvasva a problémát és a kívánalmakat, nekem elsőre vagy a HTML, vagy az RSS (2.0) lenne az ötletem.
Előbbi azért, amit te is írsz: nincs js, megjelenik úgy-ahogy.
Utóbbi pedig azért, mert említetted az Atomot, és RSS-t könnyebb létrehozni és kezelni, valamint az eszközök túlnyomó többségén (talán mindegyiken) ez is megjelenik minden gond nélkül. Az Atom-ban nem vagyok biztos mobilokon (főleg nem okostelefon - szinte kizárt), de RSS tuti. És itt végülis XML formátumról beszélünk, tehát neked mindegy.
Az viszont meglepett, hogy a Suggested Hypermedia Types közt ott az RDF/XML is, de az RSS nincs, pedig előbbi továbbfejlesztése. Vajon miért?
A HTML-lel az a baj, hogy ha a kliens "másik" HTML-t készít belőle, akkor majdnem duplán parsolod, vagy tényleg duplán.
Mondjuk az XML-eknél is, ha azt akarod, hogy js nélkül is legyen valami. Vagy ha van js, akkor nem írod képernyőre, ezt esetleg sütizheted, vagy változóba töltöd - ezt most nem tudom.
De utólag fel- vagy átdolgozni szerintem a HTML-t a legnehezebb, az XML-eket könnyebb. (Bár js-ben nem tudom, mennyire jó eszközök vannak rá.) Ha XML, akkor lehet akár neked egyedi is, aszerint írod a klienset.
Mobil.
Hát azzal szerintem igen óvatosan, hogy nem a szervert dolgoztatod túlórában a mobil miatt (vagy épp kevesebbet).
Mire js-el végigzongorázod, hogy ott helyben mik a lehetőségek, akkora gigászi kliensed lesz, hogy a Júzer oldalanként 3x cserél akksit, vagy inkább 2x vágja földhöz a telót / tablet-et. :)
Ha nagyon egyszerű dologról van szó, akkor lehet ilyennel játszani - szerintem -, de ha már pl. egy webshop listájáról beszélünk, akkor mondjuk asztalira egyszerre 25 item megy (eszerint lapozol is), mobilra csak 10. Ilyenkor hülyeség kiküldeni a 25-öt, és csak 10-et megjeleníteni + variálhatod a lapozót, stb. És ez csak egy ötlet a millió közül, hogy miért foglalkozzunk a szerveren (is) a mobillal.
Azt lehet esetleg ötvözni, hogy ha asztalin mobilt néz valaki, az mindjárt gyengénlátónak is jó legyen. De ehhez is kell a szerver is.
De utólag fel- vagy
Nyilván a böngészőbe épített parsert használja mindenki, nem tudom, hogy mekkora időkülönbség van a kettő között, de amit tudok, hogy nekem nem kell törődni vele, csak küldeni a dom queryket ezerrel... A JSON-nal a legkönnyebb dolgozni, ha js-el kommunikálsz.
Mindenképp jobb ajánlások vagy szabványok szerint dolgozni, nem kell egyetlen nevet sem kitalálni, benne van a leírásában a dolognak... Mondjuk cserébe agyalhatsz azon, hogy melyik nevet húzd rá az adott jelenségre... A szabványos dolgokat a google feldolgozza, és tudja értelmezni, a microformats-ba ha belenézel, szinte mindegyiket támogatja... Ha ez szempont, akkor mindenképp microformats és html a legjobb megoldás. Nekem ennél a projektnél nem szempont.
A hypermedia API-nak (RESTful webservice böngészőnek küldve) a lényege, hogy vékony kliensek legyenek és vastag webservice-ek. Szóval alapból kevésbé dolgoztatja ez a megoldás a mobilt, mint ami úgy átlagban lenni szokott egy-egy ajaxos oldalon... Arról volt szó, hogy az asztali kliens kattintgatja végig a lehetőségeket, hogy feltöltse a menüjét menüpontokkal. Ez a gyakorlatban úgy néz ki, hogy a google dob egy linket, amire rákattintasz.
Sokat variálsz - nem véletlen
Kíváncsian várom, hogy merre indulsz el, egy kicsit "túlbonyolított" érzésem van, de ne legyen igazam. Szerintem azért böngészőt nem fogsz feltalálni, de lehet, hogy már közelítesz... :) Ne vedd rossz néven, értsd úgy, hogy várom a döntést / eredményt, többet nemigen tudok javasolni, ilyen mélyen talán nem mennék REST és ROA felé, de még ki tudja?
A vékony kliens azért
Én valószínűleg elfelejtem ezt a progressive enhancement-es dolgot, és csinálok két klienst, az egyik szerver oldali lesz, és session-ben fogja tárolni az aktuális állapotot, a másik a böngészőben fog futni, és ott fogja tárolni az aktuális állapotot. A szerver oldalinál megpróbálom először curl-el elküldeni a kéréseket a REST API felé, aztán ha túl lassú, akkor átváltok arra, hogy nem http-n keresztül küldöm őket, hanem csinálok egy külön belső interface-t. Egyébként ezt valszeg amúgy is megcsinálnám, hogy ne függjek a SLIM-től, vagy attól, hogy éppen milyen keretrendszerre dolgozok. Eddig ez volt a terv, a progressive enhancement-es meg az adaptive webdesign-os videok, amik ebben elbizonytalanítottak. Részben igazuk is van, hogyha véletlenül kiesik a javascript valamiért (nem jön meg egy fájl, stb...), akkor jó, ha működik csak HTML-el a webalkalmazás, de szerintem ez a RESTful webservice-ekkel nem összeegyeztethető, max a klienst lehet megírni ilyenre, hogy böngészőben és szerveren is fusson, és a kettő szupportálja egymást. Azért még olvasok a témában 20 cikket, meg megnézek kész kódokat is, mert elméletileg csináltak olyat, ahol a REST API-ból származó HTML-t követlenül jelenítik meg mobil nézetnél, a desktop meg feldolgozza a benne található adatot, és egy tök más nézetet ad. Kíváncsi vagyok, hogy a kettőt hogy sikerült összeegyeztetni. A microformats használatával elméletileg jó adatküldésre és mobil megjelenítésre is egyszerre ugyanaz a HTML, a gyakorlat viszont kicsit más. Pl az űrlapok nem tudnak method=DELETE vagy method=PUT-ot, szóval szerintem mindenképp muszáj gányolni vele...
Hmm közben megvilágosodtam,
Olyan megoldás szerintem nem lehetséges, ami a böngészőt használja REST kliensnek, még a HTTP method workaround-jával sem. Azért nem, mert az állapotot a kliens kell, hogy tárolja, és nem a REST service. A HTML-ben js nélkül viszont nem tudunk olyan parancsokat kiadni, amik állapot tárolásra szólítják fel a böngészőt. A böngésző csak néhány dologgal kapcsolatban tud állapotot tárolni:
A jogosultság kezelést általában ki szokták szervezni OAuth-al, ha bárki csinálhat klienst a webservice-hez. Egyébként nincs szükség rá. Lehet olyat csinálni, hogy a kliens elküldi HTTP header-ben a tokent, ami azonosítja. Lehet még munkamenetet csinálni, ami jogosultságokat tárol, hogy ne kelljen minden egyes alkalommal bejelentkezni, és összegyűjteni őket, de ez már többé-kevésbé hax-nak számít, és a böngészők nem támogatják. Az igazán jó az lenne, ha a HTTP auth kinézetét, és minden vele kapcsolatos dolgot személyre lehetne szabni, de erre én jelenleg nem találtam módot.
Az url queryString-et fel lehetne használni kliens állapot tárolásra, de egyrészt ronda, másrészt nem éri meg az erőfeszítést. Helyette jobb inkább egy szerver oldali klienst írni a REST service-hez. Ebből az lehet kivezető út, ha a HTML element-eket hozzá tudjuk kötni a böngészőben valamilyen localStorage-hez, és ehhez pusztán elég lesz egy data binding jellegú attribútumot megadni, nem lesz hozzá szükség js-re. Amíg ez nem valósul meg, addig csak nagyon buta, szinte állapotmentes REST kliensnek jó a böngésző.
Ezzel végülis választ kaptam
Az szinte biztos, hogy progressive enhancement-el állok neki a kliens fejlesztésének ahelyett, hogy külön venném js és nojs kliensekre.
A HTML előnye, hogy a
A HTML hátránya, hogy nincs hozzá serialize/unserialize: JS.object<->HTML<->PHP.object, ezt nekem kellene megírni... A serialize-hoz kelleni fog egy escaper, az unserialize-hoz meg kell DOM parser és unescaper. Ezek közül a DOM parser az, amiről tudom, hogy megvan, az escaper és unescaper szintén megszületett már XML RPC témában. Egyedül a logikáját kellene kidolgozni.
A JSON előnye, hogy van hozzá kész serialize/unserialize (ami mellesleg sokkal gyorsabb, mint egy HTML DOM parser), így ezzel nem kell foglalkozni.
A JSON hátránya, hogy a mikroformátumokat nem JSON-ra találták ki, így át kell gondolni minden egyes mikroformátumnál, hogy hogyan nézne ki JSON-ban. Lehetőleg ilyen célra valamilyen általános módszert kéne kidolgozni, amit aztán elő lehetne terjeszteni ajánlásnak. Na ez sem egyszerű. Ehhez érdemes lenne tanulmányozni a HAL+HTML<->HAL+JSON konverziót, és abból valami általános törvényszerűséget levezetni.
Mindkettőnél ugyanoda jutok, hogy HTML<->JSON konverzió kellene. A REST esetében annyiban szerencsém van, hogy ilyesmi már létezik, mert HAL+JSON<->HAL+HTML konverzió viszonylag könnyen kivitelezhető. Általános sémát nem szükséges kitalálni. Azt kell még kideríteni, hogy a HAL+HTML kizárja e a mikroformátumok lehetőségét. Ha igen, akkor nem használok mikroformátumokat az adatátvitelben, ha nem, akkor valószínűleg egyszerűen használhatóak JSON-ra is, és nem kell HTML-t használni adatátvitelre. A végeredmény mindenképp az, hogy JSON-t kell, hogy használjak, kivéve ha valami nagyon szimpla állapotmentes oldalról van szó, amit a böngésző is elvisz. Jelenleg nem ez a helyzet, úgyhogy a HAL+JSON az már biztos. A mikroformátumoknál kiderült, hogy már megcsinálták helyettem a munkát, a kettes verzióban mindegyiknek van kanonizált formája JSON-ban.
Szóval amit RESTful webservice-eknél használni érdemes:
HAL+JSON media type
microformats2+JSON szabványos/ajánlott adatszerkezetek
Azon még dolgozok, hogy ez a kettő hogyan egyeztethető össze. Lehet, hogy sehogy. HAL+JSON-nál a lényeg az, hogy minden egyes objektum egy resource a REST service-ben. A mikroformátumok meg inkább arról szólnak, hogy a kapott adatnak van egy szabványos típusa, ami szerint meg lehet jeleníteni, és fel lehet dolgozni azt. Vannak átfedések a kettő között, a HAL+JSON is használ linkekkel kapcsolatos mikroformátumokat. Tanulmányozni fogom mindkét lehetőséget, hogy mennyire egyeztethetőek össze, aztán jelezni fogom.
+1
A végén (közben) érdekelne is, hogy mire jutottál. Mikor meg van a megoldásod, amit most használni fogsz, érdemes lenne átnézni, hogyan jutottál oda, hátha összerakva a kockákat érdekes cikk lenne...
Nagyjából alakul a dolog, a
A microformats ezek közül az egyetlen, ami az én célomnak megfelel. A microformats-nál megmondják, hogy bizonyos típusú információkat milyen adatstruktúrákban érdemes tárolni, milyen változónevek, stb... legyenek, hol legyen beágyazott objektum, stb... Ezekben elég sok fejlesztői tapasztalat van benne, nyilván nem légbőlkapott, hogy mondjuk hogyan kell kontakt adatokat megadni, hanem átgondolták az egészet, és az összes szóba jöhető eshetőségre gondoltak, amire én nem feltétlen, vagy majd 10 év gyakorlat után.
Tök fura, hogy ez az egész tudat alól jött nálam már hetek óta, és csak mostanra állt össze a teljes kép, hogy mit akarok ezzel kapcsolatban...
Amit linkeltél
Kicsit hosszabb tőle a HTML, de ha nem az 500 fős cég legénységét jeleníted meg minden adattal egy oldalon (:)), akkor nem nagy plusz adat, viszont tényleg sokkal könnyebb (valamennyire) kötött attribútumokkal dolgozni, mint a nyers HTML-el.
Másoltam is a linket, van ott még sok hasznos dolog. :)
Szerk.: az újabb verzióban viszont úgy nézem több adható meg, viszont változtak az osztály- és attribútumnevek.
Gyors skicc
hal+json
Rögzített property nevekkel:
A mapping-en még agyalok, hogy kliens vagy szerver oldalon legyen e. Ha szerver oldalon van, akkor sokkal rövidebb egy-egy ilyen üzenet, és tisztább a kép kliens oldalon, debug meg minden szempontjából, a szerver oldalon meg nem jelent túl nagy megerőltetést, van már kész konverterem erre a témára...
A lényeg, hogy felsorolom minden resource-nél, hogy milyen mikroformátumokat használ, a REST kliens meg automatikusan hozzácsap egy regisztrált View-t, ami szépen besablonozza az adatot a mikroformátum alapján, és kiteszi a HTML-be. Lehet hibrid View-okat is csinálni, amik egyszerre több mikroformátumot támogatnak, lehet CompositeView-ot is csinálni, amibe akár automatikusan is összeszedheti a rendszer a mikroformátum típusok alapján, hogy milyen View-ok menjenek bele, és így tovább...
Egy elég komoly rendszert lehet erre a megközelítésre építeni i18n supporttal, saját skinekkel, meg minden egyébbel... Fogok is csinálni ilyet, ha kész, akkor kiteszem github-ra, meg talán írok cikket is a témában, ha úgy ítélem, hogy megéri... Ha nincs cikk, akkor csúfos kudarc lett a projekt :D
Ez az
Szerintem jól gondolod a mit-szerverre-és-mit-kliensre kérdést is.
Az szerintem már csak jövőre
Azt nézem, hogy vannak erre
Volt próbálkozás arra, hogy profile-al adják meg a különböző típusú xml-eket:
Itt írnak ezzel kapcsolatban: model-your-application-domain-not-your-json-structures.pdf.
Érdekes lenne kipróbálni, hogy vajon működik e az ilyen media type küldése, fogadása, automatikus parsolása, stb...
Ahogy nézem van még egy media type: json-ld, amit még nem ismerek, ez is ugyanúgy, mint a hal+json a json hypermedia problémát oldja meg. Általában erre a kérdésre helyezik a hangsúlyt, arra nem, hogy az adatokat is lehetne valamilyen ajánlás szerint reprezentálni, hogy teljesen újrahasznosíthatóak legyenek a kliensek.
Szerk: a linkelt pdf-nél nagyjából ugyanazt dumálják ki, mint amit én akarok csinálni, csak ők json-ld és rdf schema alapon csinálják, amit én hal+json és microformats2 alapon szeretnék. Azt hiszem el is küldöm blogmarknak.
Nekem kicsit sok az url az ő megoldásukban, de gyakorlatilag ugyanarról van szó. Talán annyiból jobb az rdf, mint a microformats, hogy van egy standard-jük metadata leírására, így elég megadni egy url-t valamihez, a metadata-t akár magától is leránthatja hozzá a kliens vagy a service, és mondjuk ellenőrizhet az alapján.
Azt hiszem ez már megér egy cikket... Decemberben összedobok egy cikket a hydra & rdf schema & json-ld témakörökben, ha lesz időm áttanulmányozni, addig viszont elkezdem a saját keretrendszerem & microformats2 & hal+json megvalósítását. Megpróbálom annyira általánosra csinálni, hogy akár még az rdf & json-ld is beleférjen a támogatott formátumok közé, ne csak a microformats2, esetleg áttanulmányozom a hydra-t, hogy ők hogyan oldották meg mindezt, hátha attól okosabb leszek...
Oké, ebből 4 cikk lesz:
Ezeket szerintem már angol nyelven is meg fogom írni, mert egyelőre úgy nézem, hogy angolul is hiány van a közérthető szakirodalomból ezen a téren. (Meg mert beletehetem az önéletrajzomba XD)
Biztos, hogy nem lesznek meg mind decemberre, nincs annyi időm cikk írásra...
Lehet mégsem csinálok saját
Közben kiderült, hogy az
off: Tök érdekes, hogy mindezt az agy megoldja 100W-ból egy focilabdányi helyen, nekünk meg rohadt sok szerverre van szükség baromi magas energia felhasználással mindehhez... Lehet, hogy a gráfok tárolására az agy hálózatos formája sokkal működőképesebb megoldás, mint a jelenlegi adattárolók, és az algoritmusokat, amiket használ ugyanúgy gráfban tárolja. Ami viszont már nehezebben felfogható, hogy hogyan zajlik benne az algoritmusok futtatása az adaton, mert processzort senki sem talált eddig benne... :-)
Hümm végülis ha fizikailag fölé nő az algoritmusokat tartalmazó réteg az adatokat tartalmazó réteg fölé, akkor tud rajta dolgozni... Az agyban van talán 7 db réteg egymás fölött eltérő típusú idegsejtekkel, úgyhogy ebben lehet valami. Ami megint érdekes, hogy ha ez igaz (mármint az eltérő funkciójú rétegek), akkor vajon referenciát hogy adnak egymásról az egymástól távol lévő idegsejtek (gondolom a köztes rétegek erre szolgálnak), és hogyan csinálja a rövid távú memóriát az agy? Az idegsejt kapcsolatok nem annyira képlékenyek, hogy gyors memóriát lehessen csinálni velük... Na hát van min AGYalni. :D
Na, ez nem semmi
Annyira szerintem ne mélyedj ebbe a témába, szép dolog a MI-kutatás (vagy AI), de ha valaha komoly eredményeket elérünk e téren, a gépek első dolga lesz kiirtani az emberiséget, mint legfőbb kockázati tényezőt a saját létére vonatkozóan...
De nem semmik a levezetéseid, látszik ott a bigyológus rendesen! :)
Nem hiszem, hogy kiirtanák az
Két megjegyzés
A második, ami a HTML mellett szól a JSON ellenében, hogy HTML fragmentek feldolgozásakor segítségül hívhatsz CSS szelektort vagy XPATH kifejezéseket. JSON-re nem tudok sahonló toolról (bár biztos léteznek próbálkozások) - viszont sok helyen eleve kizárt olyan eszköz használata, ami megnehezíti a projekt átadását.
HAL+JSON sokkal egyszerűbben
Ja hát dolgozni kell vele, vagy csinálni egy adaptert valamilyen külsős validator-hoz, ami elég rugalmas ilyen szempontból... Azért szerintem nem annyira nehéz validatort írni, ha nekifeszülsz, akkor 1-2 nap.
Közben agyaltam a másodikkal
A progressice enhancement 2.0 kb arról szól, hogy kapunk egy HTML-t, aztán arra teszünk több rétegben js-t és css-t. Ha valamelyik réteget nem tudja megjeleníteni a böngésző, akkor az kimarad, de az alatta lévő rétegek vígan elvannak. Pl facebook-nál nincs chat IE6-ban, de más funkciók vígan mennek, és a design is nagyjából ugyanúgy néz ki, nem pedig azt írja az oldal, hogy bocs, de a böngésző nem támogatott, és nem is noscript nézetet jelenít meg...
A hypermedia API ezzel szemben arra gyúr, hogy sok vékony kliens, mindegyik különbözőképp jeleníti meg ugyanazt az adatot, a szerver meg választ a böngészőnek neki megfelelő klienst attól függően, hogy melyik passzol hozzá a legjobban.
Az asztali nézetes több szintes menü ajax-al egyesével történő betöltése szintén ellentmondásban van az rss feed vagy html only mobil nézettel. Nehéz megírni úgy egy klienst, hogy egyszerre tudjon html only megjelenítőket és ajaxos megjelenítőket is kiszolgálni. Nem lehetetlen, csak nehéz. Mindkettőnél minden kérést index.php-re kell irányítani. Ezután lekérni az url-re vonatkozó tartalmat a szervertől, és megjeleníteni egy html oldalon. A mobil nézetnél marad ez a html oldal, az asztali nézetnél egy js pluszban elindít kéréseket, amik kirajzolják az oldal vázát, a menüt, és minden mást a tartalom köré. Ami problémás az a hibaüzenetek, leginkább a belépés. A RESTful webservice-ek esetében 401 unauthorized vagy 403 no permission, amit visszaszór a szerver ha nincs valaki belépve, a mobil kliensnél kapásból a login oldalt kell, hogy visszaküldje. A 400 bad request szintén ilyen, a webservice-nél nem fontos visszaküldeni, hogy melyik input hibás, mert a js-nek tudnia kell, a mobil kliens-nél viszont muszáj visszaküldeni HTML-ben, ha nincsen js. Szóval úgy néz ki, hogy muszáj szétválasztani legalább mobil, asztali noscript és asztali js kliensekre a megjelenítést, nem lehet mindent egyben megoldani. A progressive enhancement 2.0 tehát borul.
Van még pár dolog, amit ezzel kapcsolatban el akarok olvasni, hátha mégis megvilágosodom... Elvileg van kész kód is ezzel kapcsolatban, azt is megcsekkolom...
Lapozás
Más: sokat segítene az írásaid olvashatóságán, ha új gondolatkörnél nyomnál két entert.
Az egésznek a lényege, hogy
Az egésznek a lényege, hogy ne a kliens állítsa elő a linkeket, hanem a szerver. Az aktuális method, url azt jelöli, hogy milyen állapotban van most a kliens, a linkek azt jelölik, hogy innen milyen további állapotok lehetségesek. Pl ha van jogod törölni egy erőforrást, akkor kint lesz egy DELETE /res link, ha nincs, akkor nem lesz kint. Ha a kliens állítaná elő a linkeket, akkor le kellene másolni bele a jogosultság kezelésen át a link elő állítást, és így tovább, gyakorlatilag az egész business logic-ot. Ezért kapja a szervertől beégetve a linkeket. Ha mobil kliens, akkor úgy küldi a lekérést, hogy abban benne lesz, hogy abban benne lesz, hogy hány sor legyen egy oldalon, szóval hogy milyen típusú reprezentációt kér az adott erőforrásról. Ha még mindig nem világos, hogy miért, akkor tegyél fel további kérdéseket ezzel kapcsolatban.
Legközelebb. Most erre futotta... Nem akartam széttördelni, hogy egyértelműen látszódjon melyik az a rész, amit át lehet ugrani.
Ha mobil kliens, akkor úgy
Egy szóval nem mondtam, hogy
A bevezető szövegben azt
A bevezető szövegben azt
Ezt most már végképp nem
Nem térek át semmiről
Ezt kifejtenéd?
A ROA-ban kiküldöd a
SOA-ban vastag klienst használsz, itt ő dönti el, hogy az objektumokat milyen formában (lapozás, végtelen görgetés) valósítja meg.
Szóval a rugalmasság az nézőpont kérdése, mert első esetben egyszerű a kliens, nincs kódismétlés, de a lehetőségek is korlátozottak (funkciók megvalósítása, kinézet), míg vastag kliens esetén pont fordítva van.
Jó, akkor válasszuk el a
Innentől azon vitatkozunk, hogy megoldható e, hogy ROA-nál a kliens azt mondja, hogy neki 50 elem kell egy oldalra 25 helyett?
(Nem néztem utána, hogy erre a helyzetre milyen mikroformátum vonatkozik, csak az elvét tudom.)
Az egyik lehetőség erre, hogy küldök ki linkeket a szervertől, amiken el lehet jutni az általam a szerveren kiválasztott elemszámhoz.
A másik lehetőség, hogy teszek be egy űrlapot:
Elég a klienseket egyszer megcsinálni, és onnantól nem törnek el, csak akkor, ha mikroformátumot váltasz. A mikroformátum váltás egyáltalán nem reális forgatókönyv, de ha mégis valami miatt rákényszerülsz, akkor küldhetsz saját media type-ban olyan mikroformátumot a régi klienseidnek, amilyet azok várnak. Ehhez csak accept header-t kell átállítani a klienseken, ha még nincs eleve saját media type-ra beállítva. A reprezentáció készítő kód nagyjából maradhat ugyanaz, az új mikroformátumnak meg írsz új kódot, amit amúgy is megcsinálnál. Mindenki boldog, nem jár nagy munkával.
Mi a cél?
Egy kicsit erősnek érzem, hogy temeted a vastag klienset. A feltüntetett ellenérvek nekem kicsit sánták. Egy üzleti alkalmazás nem fog profilt váltani futásidőben, de ha mégis, akkor is lehetőségem van küldeni a szervertől egy reload parancsot. :)
Alapvetően én a célt nem látom, mindig nagy lelkesedésem figyelem a REST témában írt dolgaidról, de egyre jobban az az érzésem, hogy egy idő után fel fogod találni a böngészőt. Egy problémát látok, hogy már vagy húsz évvel ezelőtt feltalálták. :)
Persze ez túlzás, de most mégis ott tartasz, hogy HTML kellene feldolgozni, hogy aztán azt kis módosítással megjelenítsed. Sőt, kimondott cél lett, hogy JS nélkül is jól jelenjen meg, azaz módosítás nélkül is megjeleníthető legyen.
Az alkalmazásfejlesztésnél szerintem nem feltétlen kell erőltetni a responsive témát, ahogy azt sem, hogy mobilra és asztali böngészőre ugyanazt a kimenetet adjuk.
http://blog.teqneers.com/2013/08/extjs-vs-senchatouch-vs-responsive-web/ (az itt leírtak igazak lennének JQuery és JQuery Mobile-ra is, most ne ragadjunk le a Sencha-nál:)
A lényeg: egy alkalmazás legyen konfigurálható, ne pedig responsive.
Egyetértek az általad
csomó objektumom, amiből az
Meg kell adni queryString-ben, hogy milyen field-eket akarsz lekérni, onnantól gyorstárazható.
Példa
X felhasználó látja a terméket, Y pedig nem láthatja.
Ha X felhasználó lekéri a terméket, a böngésző gyorstárazza. Utána Y ül a géphez, lekéri a terméket, de 403-at kap. Ha viszont megnézi a böngésző gyorstárát (fizikailag), megtalálja benne a terméket, és máris van hozzáférése.
Egyelőre úgy érzem, hogy a REST csak publikus objektumok megjelenítésére alkalmas emiatt.
Igen, ezen már én is
Ha túl sok az érzékeny adat, akkor valószínűleg van a HTTP auth-hoz külön gyorstár, amit űrít a böngésző kijelentkezéskor. Ha nem HTTP auth-ot használsz, akkor nem tudom, hogy van e erre bevett megoldás. Ha van normál webalkalmazásoknál, akkor az ugyanúgy használható RESTful webservice-ek esetében is.
A szerver oldali kliensek pontosan ugyanúgy kesselhetőek, mint bármelyik webalkalmazás, a böngészőben futó javascript kliensek jobban kesselhetőek, mert a js kliens statikus fájlokból áll, amik nagyon ritkán változnak (vékony kliens esetében). A webservice-nél a publikus adatok kesselhetőek, HTTP auth esetében meg talán a nem publikusak is. Nem tudom, hogy erre pontosan mi a bevett módszer a böngésző gyártóknál. Ennek majd utánanézek, ha itt lesz az ideje.
Közben utánaolvastam, http
A privát dolgoknál ki lehet küldeni cache control private-et a public helyett, és akkor az oprendszer felhasználó mappájába megy a cache. Azt hiszem több lehetőség nem nagyon van ezzel kapcsolatban. Mármint ha a böngésző kessét nézzük.
php session_cache_limiter,
Üzleti alkalmazást fejlesztek most már pár éve, és nálunk tilos bármilyen adatot a kliensnél chache-elni, egyrészt biztonsági okokból, másrészt pedig amiatt, mert bármelyik adat bármikor megváltozhat, és az ügyfélnek tuti a legfrissebbet kell látnia. Emiatt látok ellentmondást a REST és az üzleti folyamatok modellezése között.
Tegnap találtam egy linket, ennek a 3-as pontjában van egy nagyon jó észrevétel: a jelenlegi HTTP "igék" alacsony száma a kliensoldali akciókat is korlátozza. Tipikus példa erre a törlés: mi például fizikailag nagyon ritkán törlünk, de néha van rá szükség. Ha csak egy DELETE parancs van, akkor azt kénytelenek vagyunk paraméterezni, ekkor viszont ott vagyunk, ahol a part szakad: miért ne hozhatnánk létre saját igéket (LOGICAL_DELETE, PHYSICAL_DELETE) vagy akár mehet az egész egyszerű GET vagy POST paraméterben (POST akcio=logikai_torles&termek=5).
Ha valamilyen szűrő szerint
A szerver oldali cache részéhez kevéssé értek a dolognak. Majd utánaolvasok...
Az a probléma, hogy egy
Semmi támadó szándékom nem volt...
Ezt a mondatot én tényleg túlzásnak érzem, ám ettől függetlenül továbbra is figyelem majd a posztjaidat, és kíváncsi leszek a végeredményre!
The World Wide Web (WWW)
[3] R.T. Fielding and R.N. Taylor,
"Principled design of the modern Web architecture,"
ACM Trans. Internet Technology
(TOIT), vol. 2, 2002, pp. 115-150.
Persze lehet, hogy nincs igaza (se neki, se nekem), el fogom olvasni, amint lesz időm rá, de valahogy jobban szeretem a tutorial jellegűbb dolgokat programozásnál, és abból is nyitva van most pár száz oldal a böngészőben.
Amint minden részletet tisztáztam ezzel kapcsolatban, és eljutok legalább egy mérföldkőig, írni fogok a tapasztalataimról, meg kiteszek valami basic példakódot.
Szerintem...
Számomra a REST azt jelenti, hogy az erőforrásokhoz a GET, POST, PUT, DELETE négyessel nyúlok hozzá. És baromi engedékeny vagyok, mert például a
valami?method=DELETE&id=12
url-t is elfogadom, ahogy az általam készített alkalmazásoknál nincs szükség cache-re, így a feljebb említett problémákkal nem kell foglalkoznom. Továbbá használok session-t is, mert szerintem az állapotmentességbe belefér. Biztos sokan erre azt mondják, hogy ez nem is REST api. Lehet.Ebben a témában is sok olyan kifejezést használtál, aminek utána kellett olvasnom. Így definíciók versenyében biztos alul maradnék, inkább csak annyit mondok, hogy a hatékonyság miatt szerintem engedékenynek kell lenni.
Amit furcsállok, hogy mintha szembemennél azzal a vívmánnyal, amit én az elmúlt 5-10 év eredményének látok, hogy egyre komplexebb JavaScript komponenseket építhetünk. Tegyünk ki egy grid-et, az oszlop definíciókat erről az url-ről olvassuk ki, az adatokat arról az url-ről olvassuk ki, és szépen megjelenik, és ugyanaz az utasítás mind asztali gépen, mind mobilon a kívánt eredményt adja. Az, hogy hogyan lapozzon, az hogy a lapozáshoz milyen címkéket használjunk, azt mind-mind a komponens tudja magáról. Nem látom, hogy milyen előny származik abból, ha ezt az infót a szerver adja. Illetve mintha a komponens létrehozása is szerver oldalra menne át. Szerintem minél komolyabb komponensekre van szükség a kliens oldalon, hogy a lehető legrugalmasabb végeredményt kapjuk. Szerintem.
Azt a logikát követem, hogy hasznos, ha több közös komponenst tudok használni mobilon és asztali alkalmazáson, ám az sosem cél, hogy egyik vagy másik kliensen emiatt kompromisszumokat kelljen kötni.
Számomra a REST azt jelenti,
Amit te írsz az a REST level 2, vannak szintjei a level 0 az RPC, a level 1 az erőforrások használata, a level 2 a metódusok használata, a level 3 a hypermedia használata adatátvitelre. A level 3-at szokták RESTful-nak hívni, mert a REST-re vonatkozó összes kritériumnak megfelel. Szóval amit te csinálni szoktál az is REST API, de nem RESTful. Itt le vannak írva, hogy mik a REST kritériumok. Ezek függetlenek a protokolltól az az átviteli formátumtól. (Ha sok időd van olvasd el, még én sem tettem meg, mert nagyon hosszú és elméleti.)
A kettő nem zárja ki egymást. Ez a megközelítés, hogy hypermedia-t használsz fel adatküldésre lehetővé teszi azt, hogy vékony klienst lehessen használni a jelenleg elterjedt vastag kliensek helyett. Ha olyan a kedved, akkor nyugodtan csinálhatsz hozzá vastag klienst is, működni fog, csak a kliensedben is le kell kódolnod majd a business logic egy részét, és ha az változik a szerveren, akkor a kliensed azonnal el fog törni. Ez a vastag kliens hátránya. A vékony kliensé meg az, hogy a szervertől több információt igényel azzal kapcsolatban, hogy mit jelenítsen meg, mert ő nem tud arról, hogy a szerver mit csinál. Erre a tudatlanságra szükség van ahhoz, hogy könnyen cserélhető klienseket írjunk. Ha ez nem cél, mert lenne összesen egy kliens a webservice-hez, és amúgy is ritkán változna a business logic, akkor teljesen jó a most elterjedt vastag klienses felállás is. Pl ha csinálsz egy webshopot, ahol az emberek vásárolgatnak a weben keresztül, akkor oda teljesen jó a vastag kliens, de ha csinálsz egy nagykert, aminél szeretnéd, hogy a viszonteladók automatikusan értesüljenek az új termékekről, árakról, tudjanak rendelni lista alapján, stb..., akkor ott már előnyben van a vékony kliens, mert nekik könnyebb dolguk lesz a saját kliensük fejlesztésénél.
A RESTful webservice nem mondja meg a klienseknek, hogy milyen komponenseket használhatnak, csak azt mondja meg, hogy mik a lehetőségeik az adott állapotban. Pl ha van egy webshopod, és valaki felkeresi, akkor először van olyan lehetősége, hogy böngészhet a termékek között, és kosárba tehet termékeket. Ha már kosárba tett terméket, akkor mivel nem üres a kosár, lesz olyan lehetősége, hogy a pénztárhoz fáradjon. Ha a pénztárhoz fárad, akkor lesz olyan lehetősége, hogy szállítási adatokat adjon meg, és így tovább. A szerver oldalon a vastag és vékony kliens esetében is le kell írni ezt az üzleti folyamatot. A vastag kliens esetében viszont szintén le kell írnod, mert ott ő maga állítja elő a kéréseket a szerver felé nulláról, nem pedig a szervertől kapott recept alapján dolgozik, mint a vékony kliens. A vékony kliens ugyanúgy használhat bármilyen js komponenst, amit eddig is használtál, mert ezek a js komponensek nem a business logic kliens oldali implementálásáról szólnak, hanem a megjelenítésről. Az meg vékony kliens esetében sincs megkötve.
Szivesen olvastam
A megvalósítás, ha kézzel
Amivel most szopok az a REST service generáltatás. Nehéz belőni, hogy a leíró pontosan mit tartalmazzon és mit adjunk hozzá kézzel. Ha túl részletesre csinálod a leíró fájlt, akkor rugalmatlan lesz, ha meg nem elég részletes, akkor meg felesleges lesz. Egyelőre még nem találtam meg az egyensúlyt ebben, lehet, hogy nem is fogom... Azért próbálkozok tovább, mert generálva mégis sokkal egyszerűbb bármit megcsinálni. Valószínűleg ha sikerül összehoznom ezt a részét, akkor az már nem lesz open-source, hanem kiteszem ebay-re, vagy legalább beteszek egy donation gombot hozzá. Még nem döntöttem el.