|
Erik M.
Jeg er en programmerer fra Oslo som har drevet med data siden midten av åttitallet. Jeg har pløyet meg gjennom fire-fem programmeringsspråk og en haug med scriptspråk og blir aldri ferdig med det tror jeg. ————- For tiden er jeg svært opptatt av Web arkitektur og begreper som REST, APP, TAG, Semantic Web og RDF. Internettet blir muliggjort av at hvem som helst kan lenke til hva som helst. Alt av interesse har sin unike URL som kan lastes ned. Alt for mange nettsteder bryter dette enkle prinsippet ved å lage URLer som ikke lar seg lenke til. ————- Profesjonelt jobber jeg som systemarkitekt hos Escenic AS hvor jeg har jobbet siden årtusenskiftet. Før det jobbet jeg seks år i IBM og før det var det diverse programmeringsstrøjobber. ————- Mer om meg finner du på mogsie.com og på min claimid side.
Erik M. har ikke anbefalt noen soner ennå. Vi viser derfor de nyeste sonene Erik M. har blitt medlem i.
Lagdelt arkitekturWow. Lenge siden sist. Jeg er blitt et barn rikere, og har lært masse om hvordan verdensveven er tenkt fra et arkitekturståsted. Tidligere innlegg her har jo med å forklare Representational State Transfer, og hvordan man kan anvende denne arkitekturstilen i systemer som ikke er verdensveven. Siden sist har vi på jobben (Escenic AS) kommet mye lengre med vår tykke klient, som snakker med en server over HTTP, hvor vi har forsøkt å bruke REST slik det var tiltenkt. Det jeg vil dele med dere i dag er tanken om vevens lagdeling. Lagdeling er en av Roy Fielding sine begrensninger. Konkret er det slik at man utnytter det enhetlige settet med verb (i HTTP, GET, PUT, POST, DELETE osv) og selvforklarende meldinger. Lagdeling illustreres best med en proxy server, som kanskje din internettleverandør har, for at de skal spare båndbredde. Kina har en hel mur med slike proxy servere, men ikke for å spare båndbredde, kan dere tro. Det innlegget du ser på nå har antakelig også gått gjennom noen lag før den når dine øyne:
Jeg vil også våge å tro at netleseren har en proxy, nemlig dens innebygde browser cache. Denne lagdelingen er innebygget i HTTP, og det gjøres ofte helt usynlig for (mesteparten av) selve nettleseren din. Men denne lagdelingen stopper gjerne i applikasjonene som bruker HTTP for å snakke med serverene. Klientkoden er gjerne en grøt med objekter som sender meldinger til hverandre, tråder som sparker igang arbeid, og av og til noe som gjør et kall til HTTP PUT for å sende den greia over til serveren. En ting vi har skjønt (helt nylig) er at man kan ta lagdelingen et hakk videre, nemlig å ta arkitekturen til webben (REST) og implementasjonen (HTTP), og tilby et nytt lag inni applikasjonen. Vi skjønte tidlig at vi måtte ha abstraksjoner over HTTP, og beholdt metoder i koden vår for f.eks. å ta en URI og returnere et flott objekt. Men det vi ikke skjønte da vi gjorde det var at vi egentlig implementerte et nytt “lag” i ånden til vevens arkitektur. Hadde vi skjønt det, hadde vi antakelig dette laget sett mer fullstendig ut, og ikke litt “hullete” som det er i dag. Et eksempel. Du har en URI som du er interessert i å se på. Koden din vil ikke vite om HTTP, men vil gjøre et funksjonskall og få tilbake et objekt som du så kan spørre ut. Ikke noe rå byte-strøm. Så man lager en metode som ser omtrent ut som slik:
Og man hacker det sammen slik at det virker, for de forskjellige media typene man har. Vips så har man abstrahert bort HTTP, og programmerer’ne får et simpelt read(“http://api.mysite.com/v3/23432”). Dog er det er flere problemer:
Rådet jeg gir i dette innlegget er å fullfør abstraksjonen. Tilby (semantisk) de samme tingene som HTTP tilbyr, men gjerne i abstrahert form. Ikke abstraher vekk optimistisk låsing, cache validering og andre juveler i HTTP. Det kan hende at Restlet API’et har noe for seg på klientsiden også. Vi syntes det ikke helt fungerte den gangen da vi så på det for et par år siden, og vi endte da opp med en hullete abstraksjon over HTTP, hvor vi hele tiden må lappe for å tilby det og det aspektet ved HTTP. Til nå har vi tatt med
Poenget her er at vi er godt på veit til å lage en java-abstraksjon som tilbyr alle (viktige) deler av HTTP. Hvis vi hadde tatt den helt ut ville vi kunne også gjort flere kule ting med mellommenn (proxy):
Jeg lukter et eller annet REST klientrammeverk i dette her, noe som hjelper programmerer’ne lage gode RESTful klientapplikasjoner uten å måtte dille så mye med RFC2616, men allikevel få en applikasjon som følger vevens arkitektur. God programmeringshøst! Å bruke web arkitektur i ikke-web-programvareSkalerbarhet i tradisjonell softwareutvikling innebærer ofte at man gjør seg mindre avhengig av databasen, og introduserer en objektcache i minnet til en eller flere servere. Problemer oppstår når dataene forandrer seg under skjørtene på serveren. Da kan man låne noen teknikker fra webben: HTTP har nemlig særdeles gode mekanismer for å kunne skalere. Først må man akseptere at ikke alle nodene i en server vil til enhver tid se de aller siste dataene. Hvis du lager en børsapplikasjon som skal tjene penger på day-trading er det kanskje greit å ha de siste tallene, og ikke en 60 sekunder gammel kurs. Kan man akseptere litt elde (noen sekunder) er mulighetene mange. Ok punkt en er å putte objektene inn i cache, men det er jo ikke så spennende. Noen ganger vet man at objektet forandrer seg et spesielt klokkeslett. Slikt kan man nytte seg av: Man tar HTTP’s Cache-Control: max-age og gjør noe tilsvarende med objektene når de puttes i en cache. Hvis man vet at objektet ikke er gyldig etter et visst klokkeslett er det bare å fortelle cache’n dette. Hvis objektene fakisk brukes til videre oppdatering mot databasen (f.eks. du forandrer en liten ting og O/R mappingen tar og lagrer hele greia) så låner man If-Unmodified-Since eller enda bedre: If-Match fra HTTP og "gjør det selv. Når man får et objekt som skal sendes ned til databasen, så sjekker man versjonsnummeret til objektet man fikk er det samme som versjonsnummeret i databasen. Versjonsnummeret må selvfølgelig ikke være noe som klientkoden kan forandre på. Modifiseringsdato funker også om man ikke liker versjonsnummer. Hva om dataene har forandret seg? Jo, det er jo HTTP 412 Precondition Failed som får en liknende vri i koden din. Slikt kan stort sett unngås ved å gjøre noe som tilsvarer en unconditional GET—nemlig å forbigå cachen når man henter data for oppdatering. Ingen kan garantere at andre holder seg unna dataene om ikke man har en form for pessimistisk lås da. Utrolig nok har ikke Wikipedia noen entry for Pessimistic locking, bare Optimistic locking. Hvis objektene forandrer seg av ymse årsaker, så kan man låne mnot sin lovende Cache Channels slik: Med jevne mellomrom (et par ganger i minuttet) henter cachen ut en liste med endringer fra databasen, og fjerner så utdaterte objektene fra cachen. Finnes det flere cacher vil de alle hente samme liste med jevne mellomrom, og er det virkelig mange cacher kan jo listen over endringer caches den også. Nettoresultat:
Ganske stilig. Motto? Les HTTP spec’en (igjen)! Metadata i HTMLHTTP handler jo om hypermedia: Du mottar et dokument som har lenker til andre dokumenter. Men visste du at det er mulig å lenke til andre dokumenter uten å putte lenkene inni dokumenter? HTTP deler jo responsen i data og metadata, nemlig i selve dokumentet og headers (“hoder”?). Header’ene beskriver selve dokumentet sett utenifra; f.eks. HTML blir jo ofte hyllet som det ultimate hypermediaformatet, på grunn av Men å si at dette andre dokumentet er en i en rekke av dokumenter (next/previous), eller at atom feeden til dokumentet er her: Det er jo metadata! Jeg ønsker ikke å måtte forkludre dokumentet mitt. Hva om jeg returnerer et dokument som ikke har rom for lenker? Putt dem i HTTP header’ene istedenfor i HTML header’en: Link: <http://my/other/reference.txt>; rel="alternate"; type="text/plain" Link: <http://mypage/me>; rev="made"; title="John Doe" Mark Nottingham har forsøkt å beskrive Personlig anser jeg at metadata hører hjemme i HTTP header’en, og ikke i dokumentet. Metadata i dokumentet er jo plutselig data. At HTTP og HTML begge støtter både data og metadata er litt kunstig, og speiler kanskje det faktum at webben stammer fra fil-servere som ikke hadde noen særlig rik meta-modell. Både Last-Modified, Content-Length og Allow støttes jo av ethvert filsystem, og HTML fikk jo tilogmed 1 Link Header esw.w3.org 2 Mark Nottinghams Draft 3 Diskusjon om temaet Eksempler på HypermediaDen lille CSS-saken som Alexander postet her om dagen fikk meg til å tenke:
Så her sitter jeg og skriver igjen! Hypermedia er jo egentlig bare media (tekst, bilder, video) med hyperlenker til annet media (mer tekst, bilder, video). Når man sier hypermedia er det jo HTML man tenker på: HyperText Markup Language. Naturlig, ikke sant? Men hva med f.eks. CSS? Er ikke det er hypermediaspråk? Sier man ikke i CSS at man ønsker det bakgrunnsbildet på dette elementet? Og da refererer man jo til bildet ved hjelp av en URI Og da tenker jeg: Er det andre opplagte hypermediaformat man bør vurdere når man skal gi fra seg representasjoner? JSON blir ofte disset fordi det sies at det ikke er et hypermediaformat, og det har man jo rett i. CSS har en egen “uri” funksjon for å uttrykke hypertekstlenker. JSON har ikke det. XML blir ofte hypet opp som et veldig bra hypermediaformat, men det er jo helt feil. XML har heller ingen “uri” funksjon for å si at dette attributtet eller denne strengen her er faktisk en URI som en UA bør bruke til noe. Slikt må (for både XML og JSON) uttrykkes i andre dokumenter som beskriver strukturen i dokumentet. Ironisk nok gjøres dette i XML ved hjelp av URI’er:
xmlns:foo=“urn:foo” Her sier man at dokumentet ligger i namespacet foo. Neste linje sier at namespacet foo identifiseres ved hjelp av URI’en urn:foo. Dernest sier man at namespacet urn:foo har et XML schema som ligger klart til henting på http://bar—en XML prossessor kan hente denne for å sikre seg dokumentet er gyldig. Til slutt må man si til prosessoren at prefixet xsi faktisk er XML Schema Instance namespacet, som igjen blir identifisert ved hjelp av nok en URI. XML parseren slipper å hente skjemadefinisjonen for xsi fordi parseren skal kjenne igjen denne bare på bakgrunn av URI’en.Men spør du meg, er det mye magi bare for å gjøre XML til et überhypermediaformat. XML Schema Instance er også et lite dyr, men med litt øvelse kan man sikkert definere at et attributt er av type anyURI. Dermed kan hvemsomhelst som leser dokumentet og skjemaet ditt, kjenne igjen URIer. Men hva skal man bruke det til? Huff :-) JSON tiltaler meg. Det er Lists og Maps i skjønn harmoni. Et rent datautvekslingsformat som ikke forsøker å spesifisere datatypen utover noen enkle primitiver. Det er ikke noe problem å uttrykke en URI i et JSON dokument; Det er jo bare en streng som alltid. Så blir det opp til spesifikasjonen av JSON-dokumentet (som kanskje ligger i prosatekst slik som hele Atom Publishing Protocol Misforstått: URIURIer er en av hjørnestenene i webbens arkitektur. Alle websider har en adresse, en oppskrift for å hente en spesifik webside. Opprinnelig het disse URLer fordi de lokaliserte websider på nettet. F.eks. denne sonen har URI’en http://web-arkitektur.origo.no/ Det er sonens kanoniske identifikator. Jeg kan gi URIen til andre og de vil kjenne den igjen som en URL og skjønne at den peker på noe: URIen er også sonens URL—man kan skrive det inn i en nettlos, og så forsøker den å hente innholdet. Voilá. Men arkitekturen bygger også på at man kan identifisere hva som helst En vanlig misforståelse er at URIer angir nettopp websider. Det gjør de ikke. De fleste URIer på webben i dag gjør det (stort sett websider, bilder, CSS og javascript), men noen URIer gjør det ikke. Min oppfattning av URIer er at de kan identifisere hva som helst: For eksempel bygger XML Namespaces på URIer. Et XML Namespace er ikke en webside eller en skjemadefinisjon, men et abstrakt konsept om et unikt navneområde for XML tagger. Det er ingen forventning om at man skal kunne putte inn en namespace URI i en braoser og få f.eks. et skjemadokument. Namespace URIen er primært for å identifisere namespacet fra andre namespaces. Det er en identifikator. JSP Taglib URIer har samme funksjon. De er der kun for å identifisere et tag library fra et annet tag library. Her forventes det heller ikke (strengt tatt) at man må eller kan hente noe hvis man går til et taglib URI. Taglib URIer er ikke nødvendigvis URLer. På denne måten kan URIer brukes til å identifisere ting uten at man må sette opp ett nettsted for å servere innhold. Ting som ikke kan servere innhold. For eksempel mennesker, bygninger, produkter, lyspærer, og stoler kan i teorien gis egne URIer og refereres til. Andre som kjenner til de samme tingene kjenner også disse tingenes URIer og kan dermed kjenne igjen URIen hvis vi ser den. XML prosessorer som kjenner igjen et xml namespace URIer. JSP prosessorer som kjenner igjen taglib URIer. RDF er et språk som har tatt dette til sitt hjerte. RDF er et språk som lar deg uttrykke kunnskap om relasjoner mellom ressurser. URIer brukes her for å identifisere personer, firmaer, blogger og blogginnlegg, og attributter på disse: navn, overskrifter, forfattere osv. Man kan uttrykke at en person er forfatter til en bloggentry, at personen har navnet sånn og sånn, og at han kjenner disse andre personene, og at de har disse navnene. Her og der kommer det også “rdfs:seeAlso” som sier at her er en URI som forteller deg mer om denne ressursen. Hva er poenget med URIer som ikke lar seg “hente”? For en webutvikler kan det være meningsløst. Det skjønner jeg. Men i softwareutvikling kan det brukes som en generisk måte å referere til ting. Primærnøkler? Hvorfor ikke? Sannsynligvis vil alle dataene leve med samme scheme (http har grei semantikk…) og et hostnavn hvor dataene “lever” (i kanonisk forstand) Det som gjenstår er “path” til dataene. På samme måte som på en web server er pathene dine en uendelig stor tomt som skal deles opp. Poenget er at det gir universell adresserbarhet. Hvemsomhelst i verden kan referere til tingene dine, presist og nøyaktig. Hvorfor velge en annen identifikator enn URIer? Annonse | |||||||||||||||||||||||||||||