Lev som du lär

En 47 år gammal kostnadsmodell prissätter min helg till $492 788.

Ankaret

En 47 år gammal kostnadsmodell prissätter min helg till $492 788.

Jag körde scc (ett verktyg som räknar rader kod) på ett multi-player quizspel jag byggde solo på en helg. Det spottade ut COCOMO-skattningen nedan. Cost inringad i magenta, för säkerhets skull:

COCOMO-skattning från scc: uppskattad kostnad, tidsåtgång och antal personer, med kostnaden inringad.

Nästan en halv miljon dollar. 10,51 månader. 4,17 personer. För en helg, ensam.

Innan vi går vidare: lägg märke till vad den siffran just gjorde med dig. Du har nu en referenspunkt. Allt jag säger härnäst kommer du omedvetet att mäta mot en halv miljon dollar. Det är inget olycksfall: det är ett ankare (Kahneman & Tversky: vi klamrar oss fast vid det första talet vi ser, hur godtyckligt det än är). Jag namnger det med flit, så att jag är med på skämtet och inte offer för det. Siffran är fel. Men titta på vad den gör med din förväntan.

Och innan någon ingenjör i baksätet sätter sitt eget mot-ankare ("pfft, ett vibe-codat helgleksak, värt typ $0"): nej. Det är lika fel, åt andra hållet. Den här texten handlar om vad som ligger emellan, och varför avståndet inte mäts i rader kod.

Ankaret ljuger åt två håll

COCOMO (Constructive Cost Model, Barry Boehm, 1981) skattar kostnad ur en enda ingång: antal rader kod, körda genom en takt kalibrerad mot vattenfallsprojekt på stordatorer. Den ljuger på två sätt samtidigt.

Den inflaterar. Av de 18 988 raderna scc räknade är massor inte handskriven applikationslogik: 5 306 rader CSV-frågedata, 4 542 rader Markdown (specs, ADR:er, den här sortens dokument), genererad och konfigurerad kod. Och även den äkta koden prissätts i 1981 års takt, en epok utan ramverk, pakethanterare eller en standardbibliotek som gör det tunga lyftet.

Skala ner till enbart ren kod (C#, Razor, CSS), och modellen säger:

$126 384 · 6,27 månader · 1,79 personer (4 347 rader kod)

Mer ärligt. Fortfarande absurt för en solo-helg.

Den är blind. Det COCOMO inte kan se är där allt arbete faktiskt ligger: specifikationen som är sanningskälla, de sju arkitekturbesluten, testdesignen, agent-pipelinen som granskar frågedatan. Och inte bara det osynliga tankearbetet, utan också det konkreta arbete som inte är applikationskod alls. 1 085 frågekort, vart och ett författat, faktagranskat mot källa och språkputsat: modellen ser 5 306 textrader att prissätta som om de vore kod, men inte timmarna av kurering bakom dem. Och allt som krävdes för att det här ens skulle finnas på en adress: köpa domänen, konfigurera DNS, skriva CI/CD-pipelinen i GitHub Actions, deploya till fly.io. Noll rader, i modellens ögon. Den största delen av arbetet väger ingenting.

Det är pudelns kärna: modellen mäter skuggan, inte det som kastar den. Rader kod är skuggan. Det som kastar skuggan (övad metod) syns inte i en SLOC-räknare.

Vad som faktiskt gjorde det snabbt: övad metod, inte AI-typing

Hävstången var inte att jag skrev fort, och inte att en AI skrev åt mig. Den var att besluten redan var fattade, av en uppsättning seniora discipliner jag har övat tills de blivit reflex. Tre av dem är ryggraden, och de landar alla i samma form: Given–When–Then.

Vertical Slice Architecture

Bygg en funktion åt gången, hela vägen genom: en self-contained slice. Ingen kod delas spekulativt mellan funktioner: varje slice är ett oberoende verifierbart Given–When–Then-kontrakt.

Diagram över Vertical Slice Architecture: varje funktion byggs hela vägen genom lagren som en oberoende skiva.

För ledaren: du kan leverera och verifiera en funktion utan att rota i tio andra. För ingenjören: ingen prematur abstraktion, inga lager-för-lagrets-skull, koppling hålls inom slicen.

Functional Core / Imperative Shell

All beslutslogik bor i en ren kärna: inga databaser, ingen klocka, inget nätverk, helt deterministisk. Allt stökigt (I/O, tid, anrop) trycks ut i ett tunt yttre skal.

Diagram över Functional Core / Imperative Shell: ren kärna i mitten, stökigt I/O-skal runtom.

Konsekvensen står i bilden: beteendet är simulerbart: kör tusentals scenarier utan databas, verifierbart innan det ens är byggt. Du behöver inte starta något för att veta att logiken stämmer. Det är därför testerna är bombsäkra (mer om det strax).

Decider + Event Sourcing

Spelet är en Decider: två totala funktioner.

decide:  (State, Command)  →  Result<Event[]>
evolve:  (State, Event)    →  State
Diagram över Decider-mönstret: decide tar tillstånd och kommando till events, evolve viktar events till nytt tillstånd.

Loopen är Given–When–Then: Given ett tillstånd (vikta tidigare events via evolve), When ett kommando, Then events, eller en avvisning. Samma form som slicen, samma form som testet. Designen och testet talar samma språk. (Inledande och slutliga tillstånd utelämnade för läsbarhet.)

Alla tre mönstren härleds ur en enda källa: en emlang event modeling-spec som ritar hela spelets flöde (trigger, kommando, event, vy) innan en rad kod skrivs.

Event modeling-spec över hela spelets flöde: triggers, kommandon, events och vyer i tidsordning.

Stödbalkarna

Det här är inte tre lösryckta mönster. De hänger på en gemensam ställning:

Inget av det här är talang. Det är övad ingenjörsdisciplin. Det är repetition tills besluten sitter i ryggmärgen och beslutskostnaden går mot noll.

Kvalitet påstås inte: den upprätthålls

"Snabbt och billigt" betyder ingenting om det går sönder. Så det här är inte ett påstående om kvalitet: det är en mekanism för den.

Och inte bara kod, content också

Frågedatan är inte hopkastad. Varje kort passerar en pipeline av specialiserade agenter innan det når det live-paketet:

Diagram över agent-pipelinen: frågesättare, faktagranskare, språkgranskare och kurator i följd.

frågesättare författar batchar mot svårighetsbanden → faktagranskare verifierar varje värde och riktning mot källa och pinnar årtalet (overifierbart = förkastat) → språkgranskare putsar svenskan utan att röra en enda siffra → kurator (tools/pack.cs merge) dedupar och kontrollerar bandhistogrammet in i live-paketet.

Hög kvalitet, stor människa/AI-insats, och noll rader kod. Lika osynligt för COCOMO som arkitekturen. Content är hantverk på samma villkor som mjukvaran.

Lev som du lär

Skickligheten är det jag lär ut, och läran är övad. Det var aldrig AI:n och aldrig tangenttrycken: det var att besluten redan var fattade, av discipliner jag tränat tills de blivit billiga. Metoden är multiplikatorn.

Och här är meta-beviset: den här artikeln är själv ett exempel på tesen. Argumentet, illustrationerna (hämtade ur mitt eget mönsterbibliotek, samma visuella språk som spelets diagram) och draftandet följde exakt samma övade metod som koden.

Ankaret var aldrig poängen. Disciplinen är det. Jag lever som jag lär.

Spela

Nog teori: spelet är till för att spelas. Samla gänget, öppna kvissig.se och se vem som gissar närmast. Mer eller mindre?

Välj kviss och spela ← Tillbaka till kvissarna