AI som medprogrammør (uden at du bliver passager i eget repo)

AI som medprogrammør (uden at du bliver passager i eget repo)

Brug AI til at forklare og foreslå, men lad aldrig AI få lov at ændre noget i din kode, før du selv kan forklare hvad der sker linje for linje.

AI til programmering kan være både snydekode og superpower

AI er som en meget ivrig juniorudvikler: hurtig på tasterne, ingen skam i livet og absolut ingen fornemmelse for, hvornår noget er en dårlig idé.

Hvis du bare copy-paster alt, hvad den foreslår, lærer du mindre og importerer bugs og sikkerhedshuller ind i dit repo. Hvis du bruger den som sparringspartner, kan du lære hurtigere, debugge klogere og få bedre tests.

Det her er ikke en reklame for “brug AI til alt”. Jeg er ret enig med mig selv i at blind copy-paste gør dig dummere. Det her handler om, hvordan du kan bruge AI som læringsmakker, ikke som autopilot.

Vi tager det gennem 12 konkrete prompt-mønstre, fordelt på debugging, refactor, tests og code review. Og så slutter vi med en lille validerings-checkliste og et par tricks til ikke at blive afhængig.

1. Hvornår AI faktisk hjælper dig (og hvornår den saboterer dig)

Du kan mærke at AI hjælper dig, når:

  • Du forstår mere bagefter end før du spurgte.
  • Du selv skriver, omskriver eller tilpasser koden efterfølgende.
  • Du kan forklare outputtet for en ven uden at kigge på prompten.

AI skader din læring og din kodebase, når:

  • Du kopierer 20-50 linjer kode uden at ændre noget.
  • Du ikke kan forklare, hvad der sker, men “det virker jo”.
  • Du stopper med at bruge din debugger og bare spørger chatten.

En simpel tommelfingerregel: AI skal øge din nysgerrighed, ikke erstatte den.

2. Debugging prompts: få AI til at tænke som en god fejlfinder

Debugging er et perfekt sted at bruge AI, hvis du gør det rigtigt. Målet er ikke “giv mig en løsning”, men „hjælp mig med at tænke klart“.

2.1 Reproducer prompten: “hjælp mig med at genskabe fejlen”

I stedet for at sende hele dit projekt, så send et minimalt snippet med fejl og spørg:

Jeg har denne kode i JavaScript:
function divide(a, b) {
  return a / b
}

console.log(divide("10", 2)) // forventede 5, får 5 men det føles forkert
console.log(divide(10, 0))   // forventede en fejl, får Infinity
Fejlen er ikke et crash, men at funktionen opfører sig anderledes
end jeg forventer. Genskab problemet, forklar hvad der sker, og
stil mig 3 opklarende spørgsmål om hvad funktionen burde gøre.

Det vigtige her er de tre ting:

  • “Genskab problemet” tvinger AI til at forstå eksemplet.
  • “Forklar hvad der sker” lærer dig sprogets opførsel.
  • “Stil mig 3 spørgsmål” gør det til dialog, ikke bare svar.

2.2 Hypotese prompten: “giv mig teorier, ikke færdige fixes”

Når du har en stack trace eller en mærkelig opførsel:

Jeg har denne fejl i mit React-projekt:

"Cannot read properties of undefined (reading 'map')"

Her er komponenten, hvor det sker (forkortet):

const UserList = ({ users }) => {
  return (
    <ul>
      {users.map(user => <li key={user.id}>{user.name}</li>)}
    </ul>
  )
}

Giv mig 3 mulige hypoteser på hvorfor users kan være undefined,
uden at skrive ny kode endnu. Forklar for hver hypotese, hvad jeg
selv bør tjekke i koden for at be- eller afkræfte den.

Pointen er, at du stadig selv går ud og tjekker tingene i koden. AI hjælper dig med at tænke systematisk, ikke med at skyde i blinde.

2.3 Minimerings prompten: “hjælp mig med at skære alt unødigt væk”

Et klassisk debugging-trick er at lave et “minimal reproducible example”. Du kan bede AI om hjælp til at barbere din kode ned:

Her er en fil fra mit projekt, hvor der sker en fejl.
Fejlen er markeret i en kommentar.

[indsæt kode]

Hjælp mig med at omskrive det til det mindst mulige eksempel,
der stadig giver samme fejl. Fjern alt der ikke er nødvendigt,
men behold samme sprog, samme bibliotek og samme fejltype.

Typisk fejl med sådan en prompt: AI “retter lige” fejlen for dig. Skriv eksplicit at fejlen skal bevares.

2.4 Stack trace forklarings prompten

Stack traces kan se ubehagelige ud, især i fejlfinding og debugging som begynder. Brug AI som oversætter:

Her er min stack trace. Oversæt den til almindeligt dansk for
hver linje og forklar, hvad jeg burde kigge på i min kode:

[indsæt stack trace]

Svar i denne struktur:
- Kort opsummering af hvor fejlen starter
- Linje-for-linje forklaring
- Hvilken fil og linje jeg højst sandsynligt skal starte med

Så kan du selv gå ind og debugge i editoren, i stedet for at håbe på et magisk fix.

3. Refactor prompts: gør koden pænere uden at ændre adfærd

Her går det ofte galt med AI. Den elsker at “forbedre” alting og kommer til at ændre logik. Du skal styre den ret hårdt.

3.1 Bevar-adfærd prompten

Når du beder om refactor, så gør kravet om samme adfærd ekstremt tydeligt:

Her er en funktion i Python:

[indsæt funktion]

Refactor den, så den bliver mere læsbar, men bevar præcis samme
adfærd, inklusive følgende edge cases:
- [beskriv 2-3 edge cases du kender]

Lav kun ændringer inden i funktionen, ikke på dens interface.
Forklar hvad du har ændret og hvorfor.

Hvis AI ændrer signaturen, så afvis svaret og sig direkte hvad den brød. Tænk på det som code review.

3.2 Små-commits prompten: del refactoren op

Største problem med AI-refactors: de er for store. Bed den om at tænke i små skridt:

Jeg vil gerne refactor denne funktion i små, sikre skridt:

[indsæt kode]

Forslå en liste af 3-5 meget små refactor-trin.
For hvert trin:
- Beskriv ændringen
- Forklar hvorfor det er sikkert
- Vis diff-lignende pseudo-kode for lige præcis det trin

Vi implementerer kun ét trin ad gangen.

Bagefter kan du vælge et af de små trin, lave det selv i editoren og bruge diff i git til at tjekke, at du ikke ændrede for meget.

3.3 Før/efter prompten: få AI til at sammenligne sin egen ændring

Hvis du alligevel lader den foreslå en ny version:

Her er gammel version A og din nye version B af den samme funktion.
Sammenlign dem uden at skrive ny kode.

A:
[indsæt gammel]

B:
[indsæt ny]

Svar i denne struktur:
- Hvilke linjer i B har ændret logik ift. A?
- Hvilke antagelser om input/typer er anderledes?
- Ser du nogen scenarier, hvor A ville virke og B vil fejle?

Det er en ret god træning i at tænke i “diff”, som du også skal bruge i rigtige code reviews.

3.4 Risiko-listen: “hvad kan gå galt med denne refactor”

Når du har en refactor klar, men er lidt nervøs:

Her er min før/efter refactor af denne funktion.

Før:
[indsæt]

Efter:
[indsæt]

Lav en punktliste over mulige risici ved refactoren.
Tænk på:
- Edge cases
- Performance
- Typer og null/undefined
- Integration med andre funktioner

Skriv ingen ny kode, kun risici og ting jeg skal teste.

Så har du en lille to-do til dine egne manuelle tests.

4. Test prompts: brug AI til at tænke i cases, ikke til at “eje” dine tests

AI er virkelig god til at finde på scenarier. Brug den til det, men skriv så vidt muligt selve testkoden selv.

4.1 Edge case prompten

Eksempel i JavaScript:

Jeg har denne funktion, som jeg vil skrive tests til:

function normalizeEmail(email) {
  return email.trim().toLowerCase()
}

Giv mig en tabel med 2 kolonner:
- "input" (forskellige strenge jeg bør teste)
- "forventet output"

Fokuser især på edge cases som tomme strenge, spaces,
upper/lowercase og mærkelige mellemrum.
Skriv ingen testkode, kun tabel med cases.

Bagefter kan du selv omsætte det til tests i f.eks. Vitest eller Jest. Hvis du er usikker på tests, er den her intro til tests i Vite-projekter et fint sted at starte.

4.2 “Property light” prompten

Du behøver ikke kende alt om property based testing for at tænke lidt i samme retning:

Her er en funktion i Python:

[indsæt funktion]

I stedet for konkrete input/outputs vil jeg gerne have 3-5
"regler" som altid bør være sande om denne funktion.
Fx: "output-længden er altid lig med input-længden" eller
"output er altid sorteret stigende".

Foreslå sådanne regler, ikke kode.

De regler kan du så selv omsætte til assertions i dine tests.

4.3 Hvad skal ikke mocks prompten

Mocks er et rabbit hole. Brug AI til at holde igen:

Jeg er ved at skrive tests til denne funktion:

[indsæt kode med f.eks. API-kald eller database]

Forklar først hvad der er "min egen logik" og hvad der er
"eksterne ting" (som netværk eller database).

Foreslå derefter hvilke dele jeg bør mocke i unit tests, og
hvilke dele jeg bør lade være ægte i integration tests.
Ingen kode, kun anbefalinger.

Du lærer samtidig at skelne mellem din forretningslogik og alt det andet støj.

5. Code review prompts: brug AI som ekstra sæt øjne

Her skal du især være opmærksom på sikkerhed. AI kan foreslå mønstre, der er direkte farlige, f.eks. manglende validering, dårlige passwords, SQL injection osv.

5.1 Sikkerheds-check prompten (med tydelig advarsel)

Brug det som et ekstra filter, ikke som sandheden:

Her er et uddrag af min backend-kode i Node/Express:

[indsæt kode]

Analyser den for typiske sikkerhedsproblemer i webapps.
Fokuser på:
- Inputvalidering
- Auth og sessions
- Håndtering af secrets
- SQL/NoSQL injection

Peg kun på mulige problemer og spørgsmål, skriv ingen
færdige løsninger.

AI kan overse ting eller foreslå for simple fixes, så tag det som inspiration til dit eget sikkerhedsreview. Hvis du vil mere ned i sikkerhedens verden, har vi en hel kategori om it sikkerhed for udviklere.

5.2 Performance-fælder prompten

Her er målet ikke at micro-optimere, men at spotte de helt oplagte fælder:

Her er et udsnit af min JavaScript-kode:

[indsæt]

Kan du pege på steder, hvor performance kan blive et problem
hvis datasæt eller antal brugere vokser?

Fokuser på:
- Unødige loops
- Gentagne beregninger
- O(n^2)-mønstre

Skriv ingen ny kode, kun konkrete linjer/områder der bør
undersøges nærmere.

5.3 Læsbarhed og navne prompten

AI er faktisk ret god til at spotte uklare navne:

Her er et lille modul:

[indsæt modul]

Vurder læsbarheden. Peg på:
- Variabel- og funktionsnavne der er uklare
- For lange funktioner
- Steder hvor en kommentar ville hjælpe

Kom med forslag i tekst, ikke som ændret kode.

Så kan du selv gå ind og omdøbe og kommentere i dit eget tempo.

6. Validerings-checkliste: sådan tjekker du AI-kode, før du stoler på den

Når du alligevel ender med, at AI har foreslået noget kode, du vil bruge, så kør mindst denne lille loop:

6.1 Kør koden, mål noget konkret

Ikke “det føles hurtigt”. Mål med:

  • Log statements
  • En simpel timer omkring funktionen
  • Et tal for hvor mange requests/iterationer/rows der håndteres

6.2 Læs diffen langsomt

Brug git:

git diff

Læse hver ændring og stil dig selv tre spørgsmål:

  • Forstår jeg hvad der sker her?
  • Kan jeg forklare hvorfor det er bedre end før?
  • Hvad sker der, hvis input er null/tomt/meget stort?

6.3 Skriv mindst 2 tests selv

Selv hvis AI har lavet tests, så skriv mindst 2 selv. Gerne for en edge case AI ikke nævnte. Det tvinger dig til at forstå funktionen.

6.4 Tænk et minut i “threat model light”

Især til backend og login-flows:

  • Hvad hvis en bruger sender ondsindet input her?
  • Hvad hvis nogen aflurer denne request?
  • Hvor ligger mine secrets, og er de lækket i logs eller klientkode?

Det behøver ikke være formelt, bare en ærlig lille sikkerhedsrunde.

7. Anti-afhængighed: hvordan du undgår at AI sluger hele din læring

Hvis du lige er startet med at lære at kode, er fristelsen stor: “AI kan jo bare skrive det hele”. Det kan den ikke, og selv hvis den kunne, ville du ikke lære noget.

7.1 Lav et AI-budget

En helt lavpraktisk regel, du kan sætte for dig selv:

  • Maks 3 AI-spørgsmål pr. dag, eller
  • Maks 1 AI-svar pr. feature, eller
  • Ingen AI før du har forsøgt selv i 30 minutter.

Det lyder barnligt, men det virker. Du bliver tvunget til at prøve selv først.

7.2 Øvelser der tvinger forståelse

Nogle simple øvelser hvor du må bruge AI, men på en stram måde:

  • Få AI til at forklare et stykke kode du selv har skrevet, og ret den hvis den misforstår.
  • Bed AI om at beskrive en opgave i steps, men skriv al kode selv.
  • Brug AI kun til at generere testcases, ikke selve funktionerne.

Det minder lidt om at bruge Vite som en elcykel til frontend: du får hjælp, men du skal stadig træde i pedalerne.

8. Eksempelsession: fra fejl til fix uden at miste ejerskab

Lad os tage et lille flow igennem, som jeg selv kunne finde på at bruge.

8.1 Udgangspunktet

Du har en Express-route:

app.post('/api/users', async (req, res) => {
  const user = await db.insertUser(req.body)
  res.json(user)
})

Nogle brugere får 500-fejl, og en ven nævner ordet “sikkerhed” med det der blik.

8.2 Step 1: forstå fejlen med debugging-prompter

Du smider din stack trace og route ind i AI med en stack trace forklaringsprompt. Den forklarer, at fejlen sker, når databasen afviser input, og foreslår at tjekke felt-typer og manglende felter.

Du tjekker din databasefunktion og opdager, at den forventer et felt “email”, men nogle requests kommer uden.

8.3 Step 2: hypoteser og minimering

Du beder om hypoteser på hvorfor email mangler i nogle requests. AI foreslår bl.a. at frontend ikke sender det med i alle flows.

Du laver et minimalt eksempel af route + insert-funktion og bruger minimeringsprompen til at fjerne alt unødigt. Nu kan du genskabe fejlen i en simpel test.

8.4 Step 3: refactor med bevar-adfærd og risiko-liste

Du vil tilføje validering og bedre fejlbeskeder. Du beder AI om en risiko-liste for at ændre denne route til at lave inputvalidering og returnere 400 i stedet for 500.

AI peger bl.a. på:

  • Frontend forventer måske stadig 200 selv ved ugyldigt input.
  • Du skal passe på ikke at lække databasefejl i responses.

Du skriver selv en første version af validering, og beder så AI om en bevar-adfærd refactor, hvor eneste ændring er bedre struktur, ikke ny logik.

8.5 Step 4: tests og review

Du bruger edge case prompten til at få en tabel med:

  • Manglende email
  • Tom email
  • Email uden @
  • Ekstra felter i body

Du omsætter selv tabellen til tests. Bagefter kører du en lille sikkerheds-check prompt på din route og får øje på, at du måske bør whiteliste felter fra req.body i stedet for at sende alt videre til databasen.

Det implementerer du selv, kører tests igen, læser diff og tænker et minut i “hvad hvis en ond bruger sender X”.

Nu har AI hjulpet dig, men du har stadig 100 % ejerskab over koden og forståelsen.

9. Det vigtigste: stil bedre spørgsmål end “skriv koden for mig”

Hvis du kun ændrer én ting efter den her artikel, så lad det være din standard: spørg AI om forklaring, hypoteser, edge cases og risici, og skriv så selve koden og testsene selv.

Send aldrig hele repoet eller secrets til en offentlig model. Anonymiser eller lav et minimalt reproducerbart snippet, brug client-side redigering af prompts, og overvej private eller on-prem modeller hvis data er følsomt. Tjek også leverandørens vilkår for dataanvendelse og logning før du uploader noget.
Kør unit- og integrationstests lokalt, kontroller typechecks og linters, og kør sikkerheds- og dependency-scanning (SCA). Gennemgå ændringen linje for linje for forståelse, kør performance-smoke tests hvis relevant, og sørg for at mindst én reviewer godkender manuelt.
Brug pre-commit hooks til formatering og simple checks, og en CI-pipeline der kører tests, typechecking, statisk analyse og SCA ved pull requests. Kombiner det med branch protection, krav om code-owners og automatisk test-dækning som konkret stopbremse før merge.
Indfør ritualer som 'explain-back' hvor du forklarer AI-løsningen uden at se prompten, tidsbegræns brugen til hypoteser og tests, og lav regelmæssige kodningsøvelser uden AI. Brug AI som sparringspartner til idéer, ikke som førsteudkast-forfatter; kræv altid et manuelt review før accept.

Lasse Falkenberg er typen, der begyndte at rode med HTML og CSS for at lave en simpel bandside – og opdagede, at det var langt sjovere at få knapperne til at virke end at stå på scenen. Siden har han kastet sig over alt fra små JavaScript-snippets til Python-scripts, der kan spare ham for kedeligt, manuelt arbejde i hverdagen.

Han har lært det meste ved at bygge ting, der lige præcis løser hans egne problemer: en lille webapp til at holde styr på brætspilsaftener, et script til at rydde op i rodede mapper, eller en enkel side til at dele noter med venner. Undervejs har han kæmpet sig gennem alle de klassiske fejl – semikolon, forkerte indrykninger og variabler, der hedder noget helt andet end man tror – og det er præcis den rejse, han deler på Coding Class.

På Coding Class skriver Lasse praktiske, jordnære guides, der tager udgangspunkt i små, konkrete opgaver: noget du kan se, teste og bygge videre på med det samme. Han elsker at bryde en opgave ned i små bidder, vise den fulde kode og forklare linje for linje, hvad der sker – inklusive de typiske bugs, du med stor sandsynlighed også støder på.

For Lasse handler kodning ikke om flotte titler eller store ord, men om følelsen af at få noget til at virke – og om at du som læser kan gå derfra med noget, du selv har bygget. Hvis du kan kende glæden ved at få en fejl til endelig at forsvinde, er du lige på bølgelængde med hans måde at lære fra sig på.

Send kommentar

You May Have Missed