Teknisk dokumentasjon, README og vedlikeholdsstrategier.
God dokumentasjon er nøkkelen til langsiktig vedlikehold av programvare. Kode leses langt oftere enn den skrives, og godt dokumentert kode gjør det enklere for andre (og deg selv om 6 måneder!) å forstå hva som skjer.
I dette kapittelet skal vi se på ulike former for dokumentasjon – fra kodekommentarer og docstrings til README-filer og teknisk dokumentasjon. Vi skal også diskutere teknisk gjeld og refaktorering.
1. Kodekommentarer
Inline-kommentarer forklarer hvorfor, ikke hva:
# DÅRLIG: Forklarer det åpenbare
x = x + 1 # Øk x med 1
# BRA: Forklarer hvorfor
x = x + 1 # Kompenserer for zero-indexed arraysNår bruke kommentarer:
- Kompleks logikk eller algoritmer
- Workarounds for kjente bugs
- Forklare business logic
- TODOs og FIXMEs
Når IKKE bruke kommentarer:
- Istedenfor god navngiving
- Forklare selvforklarende kode
- Gammel, utdatert kode (slett i stedet!)
2. Docstrings
Docstrings dokumenterer funksjoner, klasser og moduler:
def calculate_discount(price, discount_percent, customer_tier):
"""
Beregner rabattert pris basert på kundekategori.
Args:
price (float): Opprinnelig pris i NOK
discount_percent (float): Rabattprosent (0-100)
customer_tier (str): Kundekategori ('bronze', 'silver', 'gold')
Returns:
float: Rabattert pris
Raises:
ValueError: Hvis discount_percent er utenfor 0-100
Example:
>>> calculate_discount(1000, 10, 'gold')
850.0
"""
if not 0 <= discount_percent <= 100:
raise ValueError("Discount må være mellom 0 og 100")
base_discount = price * (discount_percent / 100)
# Ekstra rabatt basert på tier
tier_bonus = {'bronze': 0, 'silver': 0.05, 'gold': 0.10}
extra = price * tier_bonus.get(customer_tier, 0)
return price - base_discount - extraDocstring-formater:
- Google style (mest lesbar)
- NumPy style (for vitenskapelig kode)
- reStructuredText (Sphinx-dokumentasjon)
3. README.md
Hver repository bør ha en README med:
# Prosjektnavn
Kort beskrivelse av hva prosjektet gjør.
## Funksjoner
- Feature 1
- Feature 2
## Installasjon
\`\`\`bash
pip install -r requirements.txt
\`\`\`
## Bruk
\`\`\`python
from myapp import MyClass
obj = MyClass()
\`\`\`
## Bidra
Se CONTRIBUTING.md
## Lisens
MIT License4. API-dokumentasjon
For biblioteker og APIer:
- Sphinx (Python) – Genererer HTML fra docstrings
- JSDoc (JavaScript)
- Swagger/OpenAPI (REST APIs)
Teknisk gjeld (Technical Debt)
Teknisk gjeld er kompromisser i koden som gjør fremtidig utvikling vanskeligere:
Typer teknisk gjeld:
- Forsettlig: "Vi fikser dette etter lansering" (men glemmer det)
- Uforsettlig: Dårlig design pga manglende erfaring
- Miljømessig: Verktøy/biblioteker som blir utdaterte
Konsekvenser:
- Lengre tid på nye features
- Flere bugs
- Vanskelig å onboarde nye utviklere
- Lav motivasjon i teamet
Håndtere teknisk gjeld:
- Alloker tid til "refactor sprints"
- Boy Scout Rule: "Leave the code better than you found it"
- Dokumenter kjent gjeld i TECH_DEBT.md
- Prioriter gjeld som blokkerer nye features
Refaktorering
Refaktorering er å forbedre kodestrukturen uten å endre funksjonalitet:
Vanlige refaktoreringer:
- Endre variabelnavn
- Trekke ut metoder (Extract Method)
- Flytte kode til riktig klasse (Move Method)
- Fjerne duplikat kode (DRY principle)
- Forenkle komplekse if-setninger
Gylne regel: Ha tester før refaktorering!
# FØR refaktorering
def process(data):
result = []
for item in data:
if item['status'] == 'active' and item['age'] > 18:
result.append(item['name'].upper())
return result
# ETTER refaktorering
def process(data):
return [
item['name'].upper()
for item in data
if is_eligible(item)
]
def is_eligible(item):
"""Sjekk om item er eligible for processing."""
return item['status'] == 'active' and item['age'] > 18Code smells (tegn på dårlig kode):
- Long Method – Funksjoner over 50 linjer
- God Class – Klasser som gjør for mye
- Duplicate Code – Copy-paste mellom filer
- Magic Numbers – Hardkodede tall uten forklaring
- Long Parameter List – Funksjoner med > 5 parametere
def calc(a, b, c):
# Beregner noe
x = a * b
if c:
return x * 1.25
return xProblemer:
- Uklare parameternavn (a, b, c)
- Uklar kommentar ("noe")
- Ingen docstring
- Magisk tall (1.25)
GOD dokumentasjon:
TAX_RATE = 1.25 # Moms 25%
def calculate_price(quantity, unit_price, include_tax):
"""
Beregner totalpris for en bestilling.
Args:
quantity (int): Antall varer
unit_price (float): Pris per vare i NOK
include_tax (bool): Om moms skal inkluderes
Returns:
float: Totalpris i NOK
Example:
>>> calculate_price(5, 100, True)
625.0
"""
subtotal = quantity * unit_price
if include_tax:
return subtotal * TAX_RATE
return subtotaldef process_order(order):
# Valider ordre
if 'items' not in order or len(order['items']) == 0:
return {'status': 'error', 'msg': 'Ingen varer'}
if 'customer' not in order or 'email' not in order['customer']:
return {'status': 'error', 'msg': 'Ugyldig kunde'}
# Beregn total
total = 0
for item in order['items']:
if 'price' not in item or 'qty' not in item:
return {'status': 'error', 'msg': 'Ugyldig vare'}
total += item['price'] * item['qty']
# Sjekk lager
for item in order['items']:
if item['qty'] > item.get('stock', 0):
return {'status': 'error', 'msg': f"{item['name']} ikke på lager"}
# Rabatt hvis over 1000kr
if total > 1000:
total = total * 0.9
return {'status': 'success', 'total': total}ETTER refaktorering:
BULK_DISCOUNT_THRESHOLD = 1000
BULK_DISCOUNT_RATE = 0.10
def process_order(order):
"""Prosesserer ordre og returnerer resultat."""
validation_error = validate_order(order)
if validation_error:
return {'status': 'error', 'msg': validation_error}
total = calculate_total(order['items'])
total = apply_bulk_discount(total)
return {'status': 'success', 'total': total}
def validate_order(order):
"""Validerer ordre, returnerer feilmelding eller None."""
if not order.get('items'):
return 'Ingen varer'
customer = order.get('customer', {})
if not customer.get('email'):
return 'Ugyldig kunde'
for item in order['items']:
if 'price' not in item or 'qty' not in item:
return 'Ugyldig vare'
if item['qty'] > item.get('stock', 0):
return f"{item['name']} ikke på lager"
return None
def calculate_total(items):
"""Beregner totalpris for alle varer."""
return sum(item['price'] * item['qty'] for item in items)
def apply_bulk_discount(total):
"""Gir rabatt på store ordrer."""
if total > BULK_DISCOUNT_THRESHOLD:
return total * (1 - BULK_DISCOUNT_RATE)
return totalForbedringer:
- Mindre funksjoner med tydelige navn
- Konstanter istedenfor magiske tall
- Enklere å teste hver del isolert
- Enklere å forstå hva som skjer
Hva er hovedformålet med docstrings?
A) Å forklare hver eneste linje kode
B) Å dokumentere hva funksjoner, klasser og moduler gjør
C) Å gjøre koden lengre
D) Å erstatte variabelnavn
Oppgave 2 (Flervalg)
Hva er teknisk gjeld?
A) Penger man skylder til utviklere
B) Kompromisser i koden som gjør fremtidig utvikling vanskeligere
C) Antall bugs i systemet
D) Tid brukt på testing
Oppgave 3
Forklar forskjellen mellom kommentarer og docstrings i Python.
Oppgave 4
Skriv en god docstring for denne funksjonen:
def filter_users(users, min_age, country):
return [u for u in users if u['age'] >= min_age and u['country'] == country]Oppgave 5
Hva er "Boy Scout Rule" i programmering?
Oppgave 6
Nevn tre "code smells" (tegn på dårlig kode).
Oppgave 7
Refaktorer denne funksjonen for bedre lesbarhet:
def x(a, b):
r = []
for i in a:
if i > b:
r.append(i * 2)
return rOppgave 8
Hva bør en god README.md-fil inneholde?
// --- Samleoppgaver ---
Samleoppgave 1
Du overtar et prosjekt med denne koden:
def f(d):
t = 0
for i in d:
if i['s'] == 'a' and i['p'] > 100:
t += i['p'] * i['q']
elif i['s'] == 'b':
t += i['p'] * i['q'] * 0.8
if t > 5000:
t = t * 0.95
return ta) Forklar hva koden gjør (gjett basert på logikken).
b) Refaktorer koden med bedre navn, konstanter og struktur.
c) Legg til passende docstrings.
d) Hvilke "code smells" fant du i originalkoden?
Samleoppgave 2
Du leder et team som vedlikeholder en 5 år gammel webapplikasjon. Teamet rapporterer:
- Ny funksjonalitet tar 3x lengre tid enn før
- Mange bugs dukker opp etter hver deploy
- Ingen tør å endre visse deler av koden
- Ingen dokumentasjon finnes
a) Hvilke tegn på teknisk gjeld ser du her?
b) Lag en plan for å adressere problemet over 3 måneder.
c) Hvilke typer dokumentasjon bør prioriteres først?
d) Hvordan kan teamet unngå å samle opp ny teknisk gjeld fremover?
Oppsummering
I dette kapittelet har du lært:
- Dokumentasjon: gjør koden forståelig for andre.
- Kodekommentarer: forklar hvorfor, ikke hva.
- README: beskriver prosjektet og bruk.
- Vedlikehold: holde koden oppdatert over tid.
- Refaktorering: forbedre kodestruktur uten å endre funksjon.
Noekkelbegreper
| Begrep | Forklaring |
|---|---|
| Dokumentasjon | Skriftlig info som forklarer prosjektet |
| Refaktorering | Forbedre kodestruktur uten å endre oppførsel |
Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.