Documentation as Code adalah pendekatan dimana dokumentasi diperlakukan seperti kode: di-version control, di-review, dan diupdate bersama kode yang berubah.
Masalah dengan dokumentasi tradisional:
- Dokumen Word/PDF terpisah dari kode → cepat kadaluarsa
- Tidak ada review process → kualitas tidak terjaga
- Tidak terlihat di IDE → developer tidak membacanya
Level dokumentasi — dari dalam ke luar:
Level 1: Self-documenting Code
// Tidak perlu komentar kalau kode sudah jelas
// BURUK + komentar yang tidak perlu
function calc(a, b) { // hitung jumlah a dan b
return a + b; // kembalikan hasil
}
// BERSIH — nama menjelaskan segalanya
function calculateTotalPrice(basePrice, shippingCost) {
return basePrice + shippingCost;
}
Level 2: JSDoc / TSDoc
/**
* Menghitung skor kredit pengguna berdasarkan riwayat transaksi.
*
* @param {Object} user - Data pengguna
* @param {string} user.id - ID unik pengguna
* @param {Transaction[]} transactions - Daftar transaksi 12 bulan terakhir
* @returns {Object} Objek berisi skor (0-100) dan kategori risiko
* @throws {ValidationError} Jika user.id tidak valid
*
* @example
* const result = calculateCreditScore(user, transactions);
* // { score: 750, category: "good", approved: true }
*/
function calculateCreditScore(user, transactions) {
// implementasi
}
Level 3: README yang berguna
# Payment Service
Menangani semua transaksi pembayaran di platform.
## Quick Start
npm install && npm run dev
## Environment Variables
DATABASE_URL=postgresql://...
STRIPE_SECRET_KEY=sk_...
## API Endpoints
POST /payments/charge - Memproses pembayaran baru
GET /payments/:id - Mengambil detail transaksi
## Architecture Decision
Kami menggunakan event sourcing untuk audit trail lengkap.
Lihat docs/adr/0003-event-sourcing.md untuk konteks.
Level 4: ADR (Architecture Decision Record)
# ADR-0003: Menggunakan Event Sourcing untuk Payment
## Status
Accepted — 2024-03-15
## Konteks
Tim perlu audit trail untuk setiap mutasi data pembayaran
demi compliance regulasi keuangan.
## Keputusan
Menggunakan event sourcing: setiap perubahan disimpan
sebagai event immutable, bukan update record langsung.
## Konsekuensi
✅ Audit trail lengkap
✅ Bisa replay state ke titik waktu mana pun
❌ Kompleksitas lebih tinggi dari CRUD biasa
❌ Butuh event store terpisah
Level 5: OpenAPI / Swagger
# Dokumentasi API yang bisa langsung di-test
paths:
/products/{id}:
get:
summary: Mengambil detail produk
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
"200":
description: Data produk berhasil diambil
"404":
description: Produk tidak ditemukan
Prinsip Docs as Code:
- Simpan dokumentasi di repo yang sama dengan kode
- Review dokumentasi bersama kode — PR tidak merged kalau docs belum diupdate
- Generate dokumentasi dari kode saat memungkinkan (JSDoc → HTML, OpenAPI → UI)
- Test dokumentasi — contoh kode di docs harus bisa dijalankan
Yang perlu didokumentasikan:
- Keputusan arsitektur yang tidak obvious (pakai ADR)
- API publik yang dipakai tim lain (pakai JSDoc/OpenAPI)
- Cara setup project (README)
- Workaround dan "gotchas" yang sering membingungkan
🎭 Analogi sehari-hari
Documentation as Code itu kayak buku petunjuk yang nempel di belakang furniture IKEA. Ada di tempat yang sama dengan benda yang dirujuk, di-update kalau benda berubah, gak hilang gara-gara confluence space yang lupa di-share. Versus: dokumentasi terpisah di tools yang gak ke-track (Word di Google Drive, Notion page yang lupa diupdate) — sering DIVERGE dari kode aktual. Lebih buruk dari NO docs: docs yang OUTDATED (misleading). Aturan kunci: docs di repo, di-PR-review bareng kode, gagal merge kalau docs gak update. Same workflow as code = same maintenance hygiene as code.
⚠️ Jebakan yang sering ditemui
- Docs di Confluence/Notion terpisah — divergent dari kode dalam 3 bulan. Pindahin ke repo.
- Skip docs "biar cepet ship" — short-term win, long-term mahal (onboarding 3 minggu instead of 3 hari).
- Docs panjang yang gak dibaca — README 50 halaman = nobody reads. Pendek, scannable, runnable example.
- Generate docs sekali, lupa update — dokumentasi yang outdated lebih buruk dari no docs (misleading).
- Comment doc untuk fungsi private — overkill. JSDoc cuma untuk public API.
- Docs tanpa runnable example — copy-paste contoh yang gak jalan = frustasi. Pasang CI yang test snippet code.
- ADR setelah keputusan ditetapkan — gak guna. ADR ditulis SAAT keputusan, capture konteks + alternatives + trade-offs.
Struktur Dokumentasi Standar
project/
├── README.md # Overview + setup + quick start
├── CONTRIBUTING.md # How to contribute (style guide, PR process)
├── CHANGELOG.md # Per-release changes
├── docs/
│ ├── architecture/
│ │ ├── overview.md
│ │ └── adr/
│ │ ├── 0001-pakai-postgres.md
│ │ └── 0002-event-sourcing-payment.md
│ ├── api/
│ │ └── openapi.yaml
│ └── runbook/
│ ├── deploy.md
│ └── incident-response.md
└── src/
└── ... (kode dengan inline JSDoc)
Tools
- JSDoc/TSDoc — inline comments untuk function signature
- Storybook — component documentation untuk UI
- OpenAPI/Swagger — REST API documentation
- Mermaid — diagram dalam markdown (di-render GitHub)
- MkDocs / Docusaurus / VitePress — static site dari markdown
- ADR Tools — template + numbering ADR
🎯 Apa yang perlu didokumentasikan?
- Setup project (clone → run) → README ✓ wajib
- Decision arsitektur non-obvious → ADR ✓
- Public API untuk tim lain → JSDoc + OpenAPI ✓
- Component UI shared → Storybook ✓
- Onboarding flow → docs/onboarding.md ✓
- Runbook (deploy, rollback, incident) → docs/runbook ✓
- Workaround / gotchas → inline comment + docs/troubleshooting
- Internal helper function → JSDoc opsional, nama jelas cukup
- Private implementation detail → SKIP, hanya bikin noise
Aturan: dokumentasi yang dibaca > dokumentasi yang lengkap. Pendek + actionable + di-tempat-yang-tepat menang dari panjang lebar tapi gak dibaca.
TL;DR: Documentation as Code = docs di-treat seperti kode (version control, PR review, update barengan kode). Simpan di repo (BUKAN Confluence/Notion terpisah). Levels: README → JSDoc → ADR → OpenAPI. Pakai tools yang generate dari kode (JSDoc → HTML, OpenAPI → UI). PR yang ubah API tanpa update docs = ditolak. Test docs (runnable example). Outdated docs > no docs (misleading). Pendek + scannable > panjang lebar.