Teknisk dokumentasjon, README og vedlikeholdsstrategier.
God dokumentasjon er nøkkelen til langsiktig vedlikehald av programvare. Kode blir lesen langt oftare enn han blir skriven, og godt dokumentert kode gjer det enklare for andre (og deg sjølv om 6 månader!) å forstå kva som skjer.
I dette kapittelet skal vi sjå på ulike former for dokumentasjon – frå kodekommentarar og docstrings til README-filer og teknisk dokumentasjon. Vi skal også diskutere teknisk gjeld og refaktorering.
1. Kodekommentarar
Inline-kommentarar forklarer kvifor, ikkje kva:
# 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 kommentarar:
- Kompleks logikk eller algoritmar
- Workarounds for kjende bugs
- Forklare business logic
- TODOs og FIXMEs
Når IKKJE bruke kommentarar:
- I staden for god namngiving
- Forklare sjølvforklarande kode
- Gammal, utdatert kode (slett i staden!)
2. Docstrings
Docstrings dokumenterer funksjonar, klassar og modular:
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-format:
- Google style (mest lesbar)
- NumPy style (for vitskapeleg kode)
- reStructuredText (Sphinx-dokumentasjon)
3. README.md
Kvar repository bør ha ein 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 bibliotek og API-ar:
- Sphinx (Python) – Genererer HTML frå docstrings
- JSDoc (JavaScript)
- Swagger/OpenAPI (REST APIs)
Teknisk gjeld (Technical Debt)
Teknisk gjeld er kompromiss i koden som gjer framtidig utvikling vanskelegare:
Typar teknisk gjeld:
- Forsetteleg: "Vi fiksar dette etter lansering" (men gløymer det)
- Uforsetteleg: Dårleg design pga manglande erfaring
- Miljømessig: Verktøy/bibliotek som blir utdaterte
Konsekvensar:
- Lengre tid på nye features
- Fleire bugs
- Vanskeleg å onboarde nye utviklarar
- Låg motivasjon i teamet
Handtere teknisk gjeld:
- Aller tid til "refactor sprints"
- Boy Scout Rule: "Leave the code better than you found it"
- Dokumenter kjend gjeld i TECH_DEBT.md
- Prioriter gjeld som blokkerer nye features
Refaktorering
Refaktorering er å forbetre kodestrukturen utan å endre funksjonalitet:
Vanlege refaktoreringar:
- Endre variabelnamn
- Trekkje ut metodar (Extract Method)
- Flytte kode til rett klasse (Move Method)
- Fjerne duplikat kode (DRY principle)
- Forenkle komplekse if-setningar
Gylne regel: Ha testar 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 (teikn på dårleg kode):
- Long Method – Funksjonar over 50 linjer
- God Class – Klassar som gjer for mykje
- Duplicate Code – Copy-paste mellom filer
- Magic Numbers – Hardkoda tal utan forklaring
- Long Parameter List – Funksjonar med > 5 parameter
def calc(a, b, c):
# Beregner noe
x = a * b
if c:
return x * 1.25
return xProblem:
- Uklare parameternamn (a, b, c)
- Uklar kommentar ("noe")
- Ingen docstring
- Magisk tal (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 totalForbetringar:
- Mindre funksjonar med tydelege namn
- Konstantar i staden for magiske tal
- Enklare å teste kvar del isolert
- Enklare å forstå kva som skjer
Kva er hovudformålet med docstrings?
A) Å forklare kvar einaste linje kode
B) Å dokumentere kva funksjonar, klassar og modular gjer
C) Å gjere koden lengre
D) Å erstatte variabelnamn
Oppgåve 2 (Flerval)
Kva er teknisk gjeld?
A) Pengar ein skuldar til utviklarar
B) Kompromiss i koden som gjer framtidig utvikling vanskelegare
C) Talet på bugs i systemet
D) Tid brukt på testing
Oppgåve 3
Forklar skilnaden mellom kommentarar og docstrings i Python.
Oppgåve 4
Skriv ein 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]Oppgåve 5
Kva er "Boy Scout Rule" i programmering?
Oppgåve 6
Nemn tre "code smells" (teikn på dårleg kode).
Oppgåve 7
Refaktorer denne funksjonen for betre lesbarheit:
def x(a, b):
r = []
for i in a:
if i > b:
r.append(i * 2)
return rOppgåve 8
Kva bør ei god README.md-fil innehalde?
// --- Samleoppgåver ---
Samleoppgåve 1
Du overtek eit 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 kva koden gjer (gjett basert på logikken).
b) Refaktorer koden med betre namn, konstantar og struktur.
c) Legg til passande docstrings.
d) Kva for "code smells" fann du i originalkoden?
Samleoppgåve 2
Du leier eit team som vedlikeheld ein 5 år gammal webapplikasjon. Teamet rapporterer:
- Ny funksjonalitet tek 3x lengre tid enn før
- Mange bugs dukkar opp etter kvar deploy
- Ingen tør å endre visse delar av koden
- Inga dokumentasjon finst
a) Kva for teikn på teknisk gjeld ser du her?
b) Lag ein plan for å adressere problemet over 3 månader.
c) Kva for typar dokumentasjon bør prioriterast først?
d) Korleis kan teamet unngå å samle opp ny teknisk gjeld framover?
Oppsummering
I dette kapittelet har du lært:
- Dokumentasjon: gjer koden forståeleg for andre.
- Kodekommentarar: forklar kvifor, ikkje kva.
- README: skildrar prosjektet og bruk.
- Vedlikehald: halde koden oppdatert over tid.
- Refaktorering: forbetre kodestruktur utan å endre funksjon.
Nøkkelomgrep
| Omgrep | Forklaring |
|---|---|
| Dokumentasjon | Skriftleg info som forklarer prosjektet |
| Refaktorering | Forbetre kodestruktur utan å endre åtferd |
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.