Måleenheter er der datamodellen møter kjøkkenet
terazjemy.pl var et polsk nettsted om sunt kosthold og fysisk aktivitet: oppskrifter, veiledende artikler og forklarende stoff. Nettstedet har ikke vært tilgjengelig på en stund, så det som står her beskriver valg som ble tatt, ikke en nåværende tilstand. Leveransen skjedde i 2012 og arbeidet tok rundt seks uker.
Jeg begynner med måleenhetene, for det er der en ryddig datamodell kolliderer med hvordan folk faktisk lager mat. Så snart ingredienser blir egne listeoppføringer, må noen bestemme hva en enhet er, og oppskrifter snakker ikke i milliliter. En norsk oppskrift måler mel i desiliter, ikke i gram, og bruker ss og ts som om de var presise mål. En polsk oppskrift har sin egen variant av det samme: ved siden av gram og milliliter lever glass, skje, klype og dekagram, en enhet knapt noen utenfor polsk hjemmekjøkken bruker, men som står helt naturlig i en eldre oppskrift.
Det finnes to nærliggende løsninger, og begge koster noe. Tving alt over til metriske mål, og du får konsistente data og oppskrifter som leses som en laboratorieprosedyre. La enhetene stå slik de ble skrevet, og du får naturlig språk og ingen mulighet til å regne om noe automatisk.
Vi valgte en tredje vei. Enheten er et felt fra en lukket liste, og der en omregning til metrisk finnes, ligger den ved siden av. Oppskriften vises da slik den ble skrevet, mens porsjonsomregningen virker der den har noe å ta tak i, og åpent lar være der den ikke har det.
Selve omregningen ser triviell ut og gjøres sjelden ordentlig. Dobbelt antall porsjoner dobler verken steketiden eller en klype salt. En mekanisme som ganger alt med to, lager oppskrifter som ikke kan følges. Derfor regnes bare oppføringer med tallfestet mengde og målbar enhet om, mens tider og beskrivende anvisninger står urørt.
En oppskrift oppfører seg ikke som en artikkel
Avgjørelsen som formet resten av prosjektet, ser banal ut utenfra. En oppskrift ligner en artikkel: tittel, bilde, tekst. Den oppfører seg helt annerledes. En artikkel leses én gang, ovenfra og ned, av en person som sitter stille. En oppskrift leses to ganger, først i butikken for handlelisten og så på kjøkkenet for rekkefølgen, og den andre lesningen skjer med skitne hender og en skjerm som stadig slukker.
En artikkel har en forfatter og en dato. En oppskrift har tilberedningstid, antall porsjoner, vanskelighetsgrad, en ingrediensliste med mengder og et sett kostholdsmerker, og alt dette er ting folk søker på, ikke pynt rundt teksten.
En oppskrift kunne derfor ikke være et vanlig innlegg med brødtekst. Den trengte en egen struktur, der ingredienser er listeoppføringer med mengde og enhet, stegene er en ordnet sekvens, og tid, porsjoner og kostholdskategorier ligger i egne felter. Bare en slik struktur svarer på et spørsmål av typen glutenfri middag under tretti minutter, og bare en slik struktur lar seg beskrive på en måte en søkemotor faktisk leser.
Strukturerte data må komme fra samme kilde som teksten
Oppskrifter er en av få innholdstyper søkemotorer har et eget, detaljert vokabular for. Ingredienser, steg, tilberedning- og koketid, porsjoner og næringsinnhold har alle en plass i det, og en korrekt beskrevet oppskrift dukker opp annerledes i resultatene enn et vanlig innlegg.
Den viktige avgjørelsen her er organisatorisk og ikke teknisk. Strukturerte data er bare verdt noe hvis de lages fra samme kilde som det synlige innholdet. Skriver redaksjonen ingredienser inn i en brødtekst mens noen andre fyller ut felter for søkemotoren, glir de to settene fra hverandre i løpet av måneder, og de glir lydløst, for ingen leser strukturerte data med øynene. Oppskriftsfeltene er derfor eneste inngangspunkt, og både menneskevisningen og maskinbeskrivelsen genereres fra dem.
Det samme prinsippet stopper en annen vanlig feil. Et næringstall er en påstand om en bestemt rett og avhenger av hvilke varer som faktisk ble brukt. Feltet for det er derfor valgfritt og står tomt til noen bevisst fyller det ut. Et felt som hjelpsomt forhåndsutfyller en beregnet verdi, lager noe som ser ut som en måling og ikke er det.
Trafikken følger en kalender
Et oppskriftsnettsted har ikke jevn trafikk. Det har skarpe sesongtopper, og i Norge er julen den tydeligste, med etterspørsel etter retter ingen leter etter de øvrige elleve månedene. Tidlig i januar skifter ikke retten, men hensikten: folk leter etter de samme rettene i en lettere utgave. Fellesferien i juli gir en tredje form, der trafikken ikke forsvinner men flytter seg mot enklere mat og grill.
To ting følger av dette. Det første er et kapasitetsspørsmål, og det er smalere enn det høres ut som. Belastningen fordeler seg ikke over året, så et oppsett som holder i mars, holder kanskje ikke uken før jul, og presset lander på et dusin konkrete adresser og ikke på hele nettstedet. En smal strøm mot noen få sider er farlig og samtidig lett å forberede, fordi nøyaktig de sidene kan varmes i mellomlageret på forhånd.
Det andre er redaksjonelt. Sesongstoff som ligger stille i elleve måneder er sovende, ikke dødt, så å slette det etter sesongen er en feil. Sesongoppskrifter beholder både publiseringsdato og dato for siste endring, og i vinduet der de søkes opp, kommer de tilbake til synlige plasser gjennom tematiske koblinger og ikke gjennom å publisere samme tekst på nytt med frisk dato.
Bildene er nyttelasten
Bildet av en rett er innhold her, ikke illustrasjon. En oppskrift uten bilde fungerer så vidt, for leseren bestemmer seg med øynene før den første ingrediensen er lest. Matbilder er dessuten uvanlig dyre å overføre: mye tekstur, få jevne flater, dårlig komprimerbarhet, og ofte flere vinkler.
Ytelsesarbeidet gikk derfor dit massen lå. Filene behandles ved opplasting til akkurat de størrelsene som faktisk forekommer: flis i oversikten, hovedbilde på oppskriften, eventuelle stegbilder. Flisen er aldri hovedbildet skalert ned i nettleseren, for skalering i nettleseren sparer piksler og ikke byte, og det er byte leseren venter på.
Bilder under første skjermflate lastes først når de nærmer seg synsfeltet. Grensen for den teknikken hører med, fordi den ofte brukes uten ettertanke: hovedbildet i en oppskrift er som regel det viktigste elementet på første skjerm, og å utsette nettopp det gjør inntrykket dårligere i stedet for bedre.
Nyhetsbrevet, og delen som ikke er skjemaet
Nettstedet samlet adresser til et nyhetsbrev. Det er her prosjekter oftest tar en snarvei, for et felt og en knapp bygges på et kvarter, og alt som er vanskelig ligger under.
En adresse skrevet inn i et skjema er en påstand, ikke et samtykke. Før den er bekreftet med et klikk i en melding, vet ingen engang om den tilhører personen som skrev den. Påmeldingen går derfor i to trinn: innsending lager en ventende oppføring, og først bekreftelsen gjør den til et abonnement. Uten det trinnet kan hvem som helst melde på en annens adresse, og listen vokser med oppføringer som blir til klager ved første utsending.
Utgangen betyr like mye som inngangen. Avmeldingslenken må virke uten innlogging og uten skjema, med ett klikk, for hver hindring på den veien flytter avmeldingen over i søppelpostknappen i e-postprogrammet, og det koster langt mer enn én tapt adresse.
Selve utsendingen kan heller ikke skje inne i en brukerforespørsel. Utsending til en liste tar tid og feiler på måter som ikke har noe med personen foran skjemaet å gjøre. Slike oppgaver går i kø og kjøres utenfor forespørselen, med nytt forsøk, for et midlertidig avslag fra en e-posttjener skal ikke bety at meldingen er borte.
Hva som faktisk mellomlagres
Et innholdsnettsted er et takknemlig tilfelle for mellomlagring: nesten alt det viser er likt for alle og endrer seg sjelden. Gevinsten kommer først og fremst av at en forespørsel om en eksisterende oppskrift aldri når PHP i det hele tatt.
Elementene som faktisk endrer seg er få og lar seg telle opp: kommentartelleren, blokken med siste innlegg, innloggingsstatus. Hvert av dem gjør, lagt rett inn i dokumentet, mellomlageret for hele siden ugyldig. De er derfor skilt ut og hentes for seg, noe som høres ut som mer kompleksitet og virker motsatt: resten av siden kan ligge lenge i mellomlageret i stedet for å bygges på nytt hver gang noen kommenterer.
Redis bærer laget under, altså spørringsresultater som går igjen på mange sider: kategorilister, koblinger mellom oppskrifter, sammenstillinger av kostholdsmerker. Ingen av dem er dyre alene. Alle beregnes ved hvert oppslag, og den typen kostnad viser seg først under trafikk og aldri på en ren testinstallasjon.
Å gjøre mellomlageret ugyldig er vanskeligere enn å fylle det. Publisering av én oppskrift endrer ikke bare dens egen side, men også kategorilisten, forsiden, blokken med beslektet stoff og nettstedskartet. Tømmes bare det første, later resten av nettstedet i en time som om oppskriften ikke finnes. Tømmes alt, kaster hver publisering bort mellomlageret for hele nettstedet. Den fornuftige mellomveien tømmer det som faktisk avhenger av det endrede objektet, og den avhengigheten må skrives ut under utviklingen, for ingen mekanisme kjenner den av seg selv.
Sikkerhetskopier og prøven ingen tar
Sikkerhetskopier gikk automatisk og ble lagret utenfor nettstedets egen tjener, med versjonering, slik at det gikk an å komme tilbake ikke bare til tilstanden før et avbrudd, men også til tilstanden før en redaksjonell glipp for tre dager siden. Det er to ulike scenarier, og bare det andre inntreffer ofte.
Ett poeng tåler å gjentas, fordi det nesten aldri står i en prosjektbeskrivelse. En sikkerhetskopi ingen noen gang har lest tilbake, er en antakelse og ikke en sikring. Tilbakelesingen må gjøres minst én gang, i et eget miljø, for å vite hvor lang tid den tar og hva som mangler i den, for hull i en kopi viser seg utelukkende under tilbakelesing.
Drift og retninger som aldri ble bygget
Den løpende driften omfattet oppdatering av kjerne, tema og utvidelser, gjennomgang av logger, oppfølging av indeksering og opprydding i databasespørringer som vokste med antallet oppskrifter. Testingen gikk i et miljø med en kopi av ekte data, for et nettsted med flere hundre oppskrifter og tunge taksonomier oppfører seg ikke i nærheten av en ren installasjon med demotema.
En måltidsplanlegger, en kobling mot kostholdsapper og en fellesskapsdel ble diskutert som retninger. Ingen av dem ble bygget, og derfor står de her som retninger og ikke som funksjoner. Hver av dem ville dessuten endret prosjektets karakter: en planlegger innfører data som tilhører en navngitt person, en app-kobling innfører avhengighet av et fremmed grensesnitt, og en fellesskapsdel innfører moderering, altså løpende menneskelig arbeid som et innholdsnettsted til da ikke hadde trengt.
Hva som følger med videre
Arbeidsmåten følger med: behandle en oppskrift som data og ikke som prosa, generere menneskevisningen og maskinbeskrivelsen fra én kilde, skille stabilt innhold fra flyktige fragmenter når mellomlageret planlegges, legge alt som går ut av nettstedet i kø, og teste mot en kopi av produksjonen.
Innholdsmodellen følger ikke med. Den ble formet rundt én redaksjon og ett oppdrag i kategorien Strony www. Feltsettet for en oppskrift speiler den redaksjonens valg, og listen over kostholdsmerker er en faglig og ikke en teknisk avgjørelse. Neste leveranse begynner med en gjennomgang av omfanget, og tilbudet kommer etter den.
Ofte stilte spørsmål
Praktiske svar for å bruke temaet i faktisk arbeid.
Hvilket omfang hadde prosjektet terazjemy.pl?
#Hvordan gikk leveransen for terazjemy.pl?
#Hva var hardest teknisk i terazjemy.pl?
#Hvilken del av terazjemy.pl kan gjenbrukes på et nytt bygg?
#Trenger du FAQ tilpasset bransje og marked? Vi lager en versjon som støtter dine forretningsmål.
Ta kontakt