~ $

cat utviklar.txt

utviklar.txt
// Utviklar. Ser etter fast jobb.
 
Glimt er i open beta på iOS og bygd for Android. Paneless er ute for macOS. Kamerapipelinen i Glimt har eg skrive sjølv, i Swift og Kotlin, med shaderar på begge plattformer, og målt meg fram til at dei to gir det same biletet.
 
Eg går andre året på frontend-utvikling. Det meste under her står ikkje i pensum. Eg lærte det fordi noko såg feil ut og eg ikkje klarte å la det vere.
 
Før eg begynte å kode var eg lydteknikar. Studio, post-produksjon, og opptakslyd på location. Det er derfrå eg har vanen med å måle i staden for å tru.
 
// Denne sida svarar på det du eigentleg lurer på: tenkjer han, eller gjettar han?

Fire saker

Alle fire har same form: kva som var problemet, kva eg målte, kva eg tok feil om, og kva som står i produksjon no.

Den tredje delen er den eg er mest stolt av. Det er lett å liste opp det som gjekk bra. Det som faktisk seier noko om korleis eg jobbar, er kva eg gjorde då eg oppdaga at eg tok feil. Alle tala under står i commit-historikken, og du kan be om å få sjå kva som helst av det.

01

Eg bygde ei avgjerd på eit tal som ikkje kunne bere henne

Fargevitskap · Metal · GLSL · SkSL

Problemet
Glimt har eigne filmsimuleringar. Fjord er tilpassa Fuji-oppskrifta R-Superia. I varmt lys bomma vi, og eg hadde slått på eit nøytraliseringssteg for å rette det.
Det eg målte
Gråkort under krysset, to lysoppsett, tre målingar side om side: iPhone sin råframe, målet, og det Glimt faktisk leverte. I varmt lys låg råframen alt 1,2 % frå målet før vi rørte han. Steget mitt dytta han 15 % for blå og 11 % for lite raud. I dagslys, der steget nesten ikkje var på, landa vi 1,1 % frå målet.
Det eg tok feil om
Eg hadde slått på steget tre timar tidlegare, på grunnlag av ein forteiknsanalyse eg fekk ved å invertere vår eiga kjede. Den inverteringa var degenerert: R og B kom ut identiske til fire siffer, og ein tredjedel av kuben var rangdefekt. Talet kunne aldri ha svart på spørsmålet eg stilte det. Ei flate med kjend fasit og éin avlesing gjorde det ein heil dag med utleiing ikkje klarte.
I produksjon
Steget er av, og graderinga blir generert inn i alle tre shaderane, Metal, GLSL og SkSL, frå eitt skript, med ein --check i testsuiten som feiler om ein av dei driv frå dei andre. Og eg skreiv ein falsifiserbar prediksjon inn i commiten: med steget av skulle Fjord lande rundt 0,74 mot målet 0,732, og gjorde han ikkje det, så tok eg feil igjen.
02

Eg målte kostnaden og ikkje gevinsten

iOS · Android · ISP-åtferd · produktval

Problemet
Panorer frå ein vegg til eit ansikt, og heile biletet blei varmare. Det såg ut som eit av våre eigne hudsteg som oppførte seg dårleg, og vi hadde tre kandidatar som alle rører hud og alle reagerer på ansikt.
Det eg målte
Den opplyste veggen las R/G 0,840 åleine og 1,161 med eit ansikt i bildet. 38 % relativ endring, på ein look utan eiga kvitbalanseforskyving. Eg slo av alle tre av våre eigne hudsteg og såg at skiftet overlevde. Då var det bevist: det skjer i telefonen sin ISP, før vi får ein einaste piksel.
Det eg tok feil om
Diagnosen var riktig. Avgjerda var feil. Eg låste kvitbalansen, og så sa nokon at ho syntest ho var stygg og oransje med looken vår. Målinga mi var på veggen, ikkje på motivet. Når eit ansikt er i bildet, så er ansiktet motivet, og at kameraet balanserer for det betyr at huda blir rett. Veggen som blir varm er prisen. Eg målte kostnaden og ikkje gevinsten, og konkluderte på halve rekneskapen. Så rulla eg det tilbake.
I produksjon
Kameraet sin eigen ansiktsprioriterte kvitbalanse får stå. Diagnosen står òg, i ein test som finst like mykje for å ta vare på konklusjonen som for å vakte koden. Forsvinn dei linjene, må heile utgreiinga gjerast på nytt.
03

Koden som melde suksess og gjorde ingenting

Swift · Accessibility API · CVDisplayLink

Problemet
Flisleggjande vindaugsbehandlarar på macOS animerer ikkje, fordi du må flytte andre appar sine vindauge gjennom Accessibility-API-et. Filhovudet mitt påstod at eg hadde løyst det med GPU-komposisjon.
Det eg målte
Fyrst kostnaden per ramme: 0,2 til 2 ms å flytte, 5 ms for Ghostty, 25 til 53 ms å endre storleik i Safari. Rammebudsjettet på 120 Hz er 8,33 ms for alle vindauge til saman. Så ein kontrollert test med to prosessar, som viste at både SLSSetWindowTransform og CGSSetWindowAlpha returnerer CGError 0 og gjer absolutt ingenting med eit vindauge ein annan prosess eig.
Det eg tok feil om
Filhovudet påstod det motsette av målinga, og eg hadde bygd tre kodevegar oppå påstanden. Kven som helst som las den fila, meg sjølv same dag inkludert, ville rimeleg konkludert med at effektane virka og bygd vidare på dei. Det er verre enn ubrukeleg. Eg sletta alt saman i staden for å halde det varmt.
I produksjon
Verifisert etterpå: eit vindauge som opnar inn i eit fullt rutenett startar å røre seg etter 191 ms mot 236 ms før, og køyrer 27 rammer rein forflytting. Flytting kan i staden overlatast til appen sjølv via AXEnhancedUserInterface, som gir rundt 110 fps frå éi einaste melding. Storleiksendring blir verande hos Paneless, fordi appar snappar storleik i staden for å ease han.
04

To feilmeldingar, éi årsak

Postgres · row-level security · Cloudflare R2 · ende-til-ende

Problemet
Ei sendingstype feila. Brukaren såg to ulike feil, ein time frå kvarandre, frå to ulike system: 403 {"error":"not yours"} frå fillageret, og new row violates row-level security policy frå databasen.
Det eg målte
«not yours» er lagerfunksjonen sin eigen streng for eit avslag. Den funksjonen gir skriveløyve på nøyaktig to måtar: ei rad du eig, eller ein intensjon du eig som namngir stien. På den haldbare vegen er rada serveren sin å skrive, så intensjonen er den einaste som kan finnast. Og koden bad om den signerte URL-en i steg 2, men skreiv intensjonen i steg 3. Kvar einaste sending bad om løyve før løyvet fanst.
Det eg tok feil om
Eg leste dei to feilmeldingane som to problem, fordi dei kom frå to system og éin time frå kvarandre. Og feilen var usynleg for den andre sendingstypen, fordi løyvefunksjonen har ein ekstra arm som dekkjer akkurat den. Ein bug som berre viser seg for éin av to funksjonar les som ein funksjonsfeil, ikkje som ein rekkjefølgjefeil. Det var éi årsak heile vegen.
I produksjon
Intensjonen blir skriven før noko som helst blir spurt om løyve. Ein intensjon som blir liggande igjen etter ein feila førespurnad er harmlaus av same grunn som han alltid har vore. Media ligg i EU, tilgangskontroll på radnivå i Postgres, og nøklane forlèt aldri eininga.

Det eg brukar

Dagleg

TypeScript, React, React Native og Expo, Swift, Kotlin

Også

Metal og GLSL, Postgres med row-level security, Supabase, Cloudflare R2, ende-til-ende-kryptering, talegjenkjenning på eininga

Rundt koden

Git, EAS, Xcode, Vercel, signering og notarisering på macOS, OTA-oppdateringar, App Store og Play Store

det-eg-ikkje-kan.txt
// Sidan resten av sida er ærleg, så kan denne vere det òg.
 
Eg har ikkje jobba i eit team med kodegjennomgang, sprintar og nokon som seier nei til meg. Det er den største luka mi, og det er den einaste eg ikkje kan tette på eiga hand.
 
Eg har ikkje drifta noko med mange tusen brukarar. Eg kan ikkje Java, C# eller Kubernetes.
 
Alt det vil eg lære, og det går fortare saman med nokon som kan det frå før. Det er heile grunnen til at eg vil inn i eit team og ikkje halde fram åleine.

Kort om meg

Frå Vinje i Telemark, bur i Oslo. Andre året på frontend-utvikling.

Før det var eg lydteknikar: studio, post-produksjon, og opptakslyd på location for reality-TV, med miksar, bom og myggar. Det yrket lærte meg to ting eg brukar kvar einaste dag. At du ikkje kan fikse i etterkant det du ikkje fanga riktig. Og at øyra lyg, så du må måle.

Ser de etter nokon?

Eg ser etter fast jobb, i Oslo eller på avstand. Ta kontakt, så går eg gjerne gjennom koden bak kva som helst av det over.