Web Artisan

Tema

Font

Ukuran teks

DOCS · PICTO

Documentation that outlives the team

Kebanyakan dokumentasi membusuk karena semua jenis ditumpuk di satu tempat dengan satu siklus hidup. Pisahkan berdasarkan tujuan dan laju pembusukannya, enam jenis, dan masing-masing bertahan melampaui orang yang menulisnya.

14 menit bacaJun 2026

Setiap tim punya wiki. Pada hari ia dibuat, semuanya terlihat bertanggung jawab: satu ruang, sidebar yang rapi, satu halaman untuk segalanya. Dua tahun kemudian, ia jadi kuburan. Panduan setup merujuk ke service yang sudah dihapus. Halaman API memuat tiga endpoint yang sudah tidak ada dan melewatkan dua belas yang sebenarnya ada. Engineer baru membaca semuanya, tidak memercayai satu pun, lalu tetap bertanya di Slack, dan itulah sinyal mahal yang sebenarnya bahwa dokumentasimu gagal.

Penjelasan yang biasa muncul adalah “tidak ada yang memperbarui dokumentasi”. Itu gejala, bukan akar masalah. Akarnya: kita memperlakukan dokumentasi sebagai satu hal, di satu tempat, dengan satu siklus hidup yang tersirat. Kita menaruh panduan setup, keputusan arsitektur, runbook insiden, dan kontrak API di wiki yang sama, berdampingan, seolah-olah semuanya menua dengan cara yang sama. Padahal tidak.

Panduan setup hanya benar sampai refactor berikutnya. Keputusan arsitektur benar selamanya, karena ia mencatat pilihan yang dibuat pada hari tertentu dengan trade-off tertentu, dan pilihan itu tidak berhenti pernah terjadi. Taruh keduanya di ember yang sama dan kamu dapat sisi terburuk masing-masing: dokumen hidup membusuk karena tidak ada yang mengeceknya ulang, dan dokumen historis terus “diperbarui dengan niat baik” sampai ia tidak lagi mencatat apa yang sebenarnya diputuskan.

Dokumentasi yang berumur panjang bukan soal menulis lebih banyak. Ia soal memilah apa yang kamu tulis berdasarkan tujuan dan seberapa cepat ia membusuk, lalu memberi tiap jenis rumahnya sendiri, aturan pembaruannya sendiri, dan pemiliknya sendiri.

MASALAH SEBENARNYA Kegagalannya bukan karena terlalu sedikit menulis. Tapi karena mencampur dokumen dengan siklus hidup berbeda ke dalam satu ember, sehingga seluruh ember membusuk secepat halaman yang paling cepat basi.

Pilah dokumen berdasarkan siklus hidup, bukan topik

Sebelum memutuskan ke mana sebuah dokumen ditaruh, tanyakan satu hal: apakah ini menggambarkan yang berlaku sekarang, atau yang dulu pernah berlaku? Satu sumbu itu, hidup versus historis, melakukan lebih banyak pengorganisasian daripada struktur folder mana pun.

Dokumen hidup melacak keadaan sistem saat ini dan harus berubah setiap kali sistem berubah. Kalau ia melenceng, ia aktif salah, dan salah lebih buruk daripada tidak ada. Dokumen historis adalah snapshot: ia menangkap sebuah keputusan, insiden, atau usulan pada satu momen waktu. Ia tidak boleh diedit agar cocok dengan masa kini, karena justru nilainya ada pada menjaga masa lalu.

Ini insting yang sama di balik Diátaxis, kerangka dokumentasi yang membagi tulisan menjadi tutorial, how-to guide, reference, dan explanation di sepanjang dua sumbu: belajar versus bekerja, dan tindakan versus pengetahuan. Pelajarannya identik di level engineering: sebuah dokumen punya tugas, dan dokumen dengan tugas berbeda tidak pantas ditumpuk jadi satu hanya karena menggambarkan proyek yang sama.

PERTANYAAN PEMILAH Tanyakan “apakah ini berlaku sekarang, atau dulu pernah berlaku?” Dokumen hidup menjawab “sekarang” dan harus terus sinkron. Dokumen historis menjawab “dulu” dan harus dibekukan.

Enam jenis, enam siklus hidup

Dalam praktik, dokumentasi engineering mengerucut menjadi enam jenis. Masing-masing menjawab pertanyaan berbeda, dan masing-masing membusuk dengan laju berbeda.

teks
Living docs - "apa yang berlaku sekarang" Historical docs - "kenapa dulu diputuskan begini" Runbook - "cara menanganinya saat rusak" Architecture map - "bagaimana semua bagian terhubung" Contract - "apa yang dijanjikan tiap sistem ke sistem lain" Data lineage - "dari mana data ini berasal"

Menamai enam jenis bukan demi taksonomi itu sendiri. Intinya, tiap jenis punya aturan pembaruan berbeda. Dokumen hidup ditulis ulang terus-menerus. Dokumen historis tidak pernah ditulis ulang. Runbook diuji secara berkala. Contract diberi versi. Lineage ditangkap otomatis. Kalau kamu tidak bisa menyebutkan bagaimana sebuah dokumen seharusnya dijaga tetap mutakhir, berarti kamu belum selesai memutuskan ia jenis apa. Sisa artikel ini membahasnya satu per satu.

Living docs: apa yang berlaku sekarang

Dokumentasi hidup menggambarkan keadaan saat ini: README, API reference, komentar inline di kode, entri service catalog. Sifat khasnya, begitu kode berubah dan dokumennya tidak, dokumen itu berbohong. Karena ia membusuk begitu kamu memalingkan muka, satu-satunya dokumen hidup yang bertahan adalah yang tidak kamu rawat dengan tangan.

Maka, generate. API reference seharusnya dihasilkan dari sumber yang sama yang dilayani kode: OpenAPI yang dipancarkan framework, pkgsite untuk package Go, TypeDoc atau JSDoc dari signature bertipe, Swagger UI yang dirender dari spec. Daftar perintah di README bisa di-generate dari package manifest. Patokannya tegas: kalau seorang manusia harus ingat untuk memperbarui dokumen hidup, ia sudah usang.

Lalu jaga di CI. Perlakukan dokumen basi seperti test yang gagal. Satu langkah pipeline bisa men-diff file OpenAPI yang di-commit dengan yang dipancarkan aplikasi yang berjalan, dan menggagalkan build saat keduanya berbeda. Link checker bisa gagal saat referensi internal mengembalikan 404. Gerbang docs-coverage bisa mewajibkan tiap endpoint publik membawa deskripsi sebelum di-merge.

ATURAN DOKUMEN HIDUP Kalau akurasinya bergantung pada ingatan manusia, ia akan salah dalam sebulan. Generate dari sumber kebenaran, dan biarkan CI gagal saat ia melenceng.

Historical docs: kenapa jadinya begini

Dokumentasi paling berharga yang dimiliki tim biasanya paling murah ditulis dan paling gampang dilewati: catatan tentang kenapa. Enam bulan dari sekarang, seseorang akan melihat keputusan aneh, sebuah queue padahal panggilan langsung sudah cukup, kolom yang didenormalisasi, vendor yang tidak disukai siapa pun, lalu bertanya kenapa itu ada. Tanpa catatan, mereka akan cargo-cult meneruskannya atau mencabutnya lalu menemukan ulang alasan aslinya dengan cara yang sulit.

Bentuk kanoniknya adalah Architecture Decision Record. ADR itu pendek, immutable, dan mengikuti bentuk baku yang dipopulerkan Michael Nygard.

teks
Title: frasa benda pendek bernomor (0007-use-outbox-pattern) Status: proposed | accepted | superseded by 0012 Context: gaya-gaya yang berperan (batasan, kebutuhan, tekanan) Decision: apa yang kita pilih, ditulis dalam kalimat aktif Consequences: apa yang jadi lebih mudah, dan apa yang jadi lebih sulit

Disiplin yang membuat ADR berhasil: kamu tidak pernah mengedit sebuah keputusan agar mencerminkan keputusan yang lebih baru. Saat pilihan berubah, kamu menulis ADR baru dan menandai yang lama “superseded by”, meninggalkan rantai yang bisa ditelusuri pembaca di masa depan. Immutability yang sama berlaku untuk RFC (usulan yang mendahului keputusan) dan post-mortem (catatan tentang apa yang diajarkan sebuah insiden). Simpan di repo sebagai Markdown agar ia berversi seiring kode yang mewujudkannya.

JANGAN EDIT SEJARAH Dokumen historis yang “diperbarui” berhenti jadi sejarah. Gantikan dengan catatan baru dan biarkan yang lama tetap berdiri.

Runbook: cara menanganinya jam 3 pagi

Runbook adalah dokumentasi yang kamu baca di bawah tekanan, saat ada yang terbakar dan orang yang membangun sistemnya sedang tidur. Audiensnya engineer on-call yang lelah, jadi ia tidak boleh berupa esai. Ia harus jadi prosedur: lakukan ini, amati itu, kalau kamu lihat satu hal pergi ke sini, kalau lihat hal lain pergi ke sana.

Kebenaran pahit soal runbook: yang belum diuji lebih buruk daripada tidak ada, karena ia menjanjikan jaring pengaman yang sebenarnya tidak ada. Langkah deploy merujuk ke script yang sudah pindah. Prosedur rollback mengasumsikan flag yang sudah dihapus. Satu-satunya cara memercayai runbook adalah menjalankannya secara berkala, dalam game day, latihan failover, atau cukup dengan mengikutinya apa adanya saat situasi yang ia cakup benar-benar terjadi, sambil memperbaiki tiap baris yang berbohong.

Tulis langkah-langkahnya sebagai prosedur dengan titik keputusan eksplisit dan perintah persis, bukan prosa yang harus ditafsirkan jam 3 pagi.

teks
GEJALA p99 latency checkout di atas 2s, error rate naik 1. Buka dashboard orders. Apakah connection pool DB jenuh? 2. Pool habis → scale deployment orders ke 6 replica kubectl scale deploy/orders --replicas=6 3. Pool sehat → cek hit rate cache Redis 4. Redis mati → aktifkan flag cache-bypass, page tim data 5. Pulih → catat pemicunya di channel insiden, buka tiket

ATURAN RUNBOOK Runbook yang belum diuji itu fiksi. Latih, atau ikuti betulan saat insiden dan perbaiki tiap baris yang salah selagi ingatannya masih segar.

Architecture map: bagaimana semua bagian terhubung

Engineer baru tidak berpikir dalam file. Mereka berpikir dalam kotak dan panah. Architecture map adalah gambaran tingkat tinggi, service apa saja yang ada, apa berbicara dengan apa, di mana data melewati batas kepercayaan, yang memungkinkan seseorang memegang sistem di kepalanya sebelum membaca satu baris kode pun.

Jebakannya ada di detail. Diagram yang menampilkan tiap class dan tiap queue sama tak bergunanya dengan tanpa diagram, karena ia basi dalam seminggu dan tetap tak terbaca siapa pun. Model C4 menanganinya dengan level zoom: diagram System Context untuk seluruh lanskap, diagram Container untuk unit yang dideploy, dan diagram Component hanya di tempat sebuah service cukup rumit untuk layak digambar. Kamu jarang butuh level keempat.

teks
Level zoom C4 Context - sistemmu sebagai satu kotak di antara user dan sistem luar Container - app, service, datastore, dan panggilan di antaranya Component - bagian utama di dalam satu container (hanya bila perlu) Code - detail level class, hampir tak pernah layak digambar tangan

Jaga peta di level yang hanya berubah saat arsitektur benar-benar berubah, saat kamu menambah service, bukan saat menambah endpoint. Tool diagram-as-code (Mermaid yang hidup di repo, Structurizr atau C4-PlantUML, Excalidraw untuk nuansa papan tulis) menjaga gambar di version control, tepat di sebelah ADR yang menjelaskan kenapa bentuknya begitu.

PETAKAN, JANGAN FOTOKOPI Gambar level yang berubah saat arsitektur berubah. Diagram yang ikut berubah tiap kali ada endpoint adalah diagram yang tak akan ada yang memperbaruinya.

Contract: apa yang dijanjikan tiap sistem

Begitu dua service saling bicara, bentuk pesan di antara keduanya menjadi sebuah contract, dan contract yang hidup hanya di ingatan seseorang adalah insiden produksi yang menunggu sebuah deploy. Dokumentasi contract adalah definisi setiap interface yang eksplisit dan berversi: payload REST dalam OpenAPI, schema event dalam JSON Schema atau Avro, pesan RPC dalam Protobuf.

Yang membedakan contract dari dokumen hidup biasa: tim lain membangun di atasnya, jadi kamu tidak bisa seenaknya mengubahnya. Aturan utamanya backward compatibility: kamu boleh menambah field opsional, tapi tidak boleh menghapus field, mengganti namanya, atau memperketat tipe tanpa rencana versioning dan deprecation. Merusak contract diam-diam berarti merusak semua consumer sekaligus.

teks
AMAN (backward compatible) MERUSAK (perlu naik versi) tambah field opsional hapus atau ganti nama field tambah endpoint baru ubah tipe sebuah field longgarkan aturan validasi perketat aturan validasi tambah nilai enum baru, hati-hati jadikan field opsional wajib

Buat contract dapat dieksekusi agar ia tidak melenceng dari kenyataan. Consumer-driven contract testing dengan tool seperti Pact membuat tiap consumer mempublikasikan apa yang benar-benar ia andalkan, lalu menggagalkan build provider saat sebuah perubahan akan merusak mereka. Itu mengubah “kita sudah mendokumentasikan API” menjadi “build membuktikan API masih menepati janjinya”.

ATURAN CONTRACT Tambah, jangan hapus, tanpa versi. Lalu buat sebuah test menegakkannya, karena contract yang didokumentasikan tapi tak diverifikasi cuma komentar penuh harapan.

Data lineage: dari mana angka ini berasal

Di sistem apa pun yang punya data pipeline, pertanyaan yang akhirnya menghentikan semua orang adalah “dari mana angka ini berasal?” Sebuah angka di dashboard terlihat salah, atau regulator bertanya bagaimana sebuah nilai diturunkan, dan kamu harus menelusurinya mundur lewat tiap join, filter, dan transformasi sampai ke sumber mentah. Penelusuran itu adalah data lineage, dan ia satu-satunya jenis dokumentasi yang hampir tidak pernah boleh kamu tulis dengan tangan.

Lineage gambar tangan usang begitu sebuah pipeline berubah, yang terjadi terus-menerus. Pendekatan modern adalah memancarkan lineage saat pipeline berjalan. OpenLineage adalah standar terbuka untuk ini, proyek LF AI & Data yang mendefinisikan format event bersama untuk run, job, dan dataset, dengan produser native untuk Airflow, dbt, dan Spark. Event-nya mengalir ke sebuah backend: Marquez, implementasi rujukannya, atau katalog seperti DataHub atau OpenMetadata, dengan Apache Atlas yang masih umum di lingkungan Hadoop. Lineage jadi graph yang bisa di-query alih-alih gambar basi.

teks
raw.orders ──▶ dbt: stg_orders ──▶ dbt: fct_revenue ──▶ dashboard: MRR raw.refunds ──────────────────────────────────┘ (ditangkap otomatis sebagai event OpenLineage, bukan digambar tangan)

ATURAN LINEAGE Kalau kamu menggambar lineage dengan tangan, ia sudah salah. Pancarkan dari pipeline sebagai event standar dan biarkan graph-nya membangun dirinya sendiri.

Menjaganya tetap hidup: kepemilikan, ritme, pembusukan

Memilah dokumen jadi enam jenis tidak ada gunanya kalau tidak ada yang memiliki hasilnya. Praktik yang menjaga dokumentasi tetap hidup sama dengan yang menjaga kode tetap hidup, karena ide paling tahan lama di seluruh bidang ini adalah docs-as-code: tulis dokumen dalam teks polos (Markdown, MDX, AsciiDoc), simpan di repo bersama kode, review di pull request yang sama, dan publikasikan dari CI.

Docs-as-code memberimu empat hal yang tidak akan pernah diberikan wiki. Version control, sehingga sebuah dokumen berubah di commit yang sama dengan kode yang ia gambarkan. Review, sehingga dokumen basi tertangkap seperti bug tertangkap. Satu sumber kebenaran, sehingga fakta yang sama tidak disalin ke empat halaman yang akan saling bertentangan dalam sebulan. Dan otomasi, sehingga static-site generator (Docusaurus, MkDocs Material, VitePress, atau Starlight untuk yang memakai Astro) mengubah repo jadi situs yang bisa dicari, dengan Algolia DocSearch atau Typesense di atasnya.

Tata kelolanya ringan tapi tidak bisa ditawar. Tiap dokumen butuh pemilik bernama, bukan sebuah tim, karena tim tidak memiliki apa-apa. Dokumen hidup diberi ritme review, dan kuartalan sudah cukup untuk kebanyakan. Dan ada kebijakan deprecation: saat sebuah dokumen menggambarkan sesuatu yang sudah tidak ada, kamu mengarsipkannya dengan nisan alih-alih membiarkannya menyesatkan. Tanggal “terakhir ditinjau” di tiap halaman hidup mengubah kebasian dari tak terlihat jadi angka yang bisa kamu taruh di dashboard.

MINIMUM TATA KELOLA Satu pemilik bernama per dokumen. Ritme review untuk dokumen hidup. Kebijakan arsip untuk yang mati. Selebihnya opsional; tiga ini tidak.

Anti-pattern yang diam-diam membunuh dokumentasi

Kebanyakan dokumentasi tidak gagal dengan ribut. Ia merosot lewat segelintir pola yang mudah dikenali, dan menamainya adalah separuh dari obatnya.

Wiki graveyard adalah kondisi akhir default: halaman menumpuk, tidak ada yang dihapus, dan rasio konten benar terhadap salah terus merosot sampai pembaca belajar untuk tidak memercayai satu pun. Copy-paste docs adalah fakta yang sama ditempel di empat tempat, yang menjamin setidaknya tiga di antaranya salah setelah perubahan berikutnya, dan obatnya selalu satu sumber kebenaran plus tautan ke sana. Over-documentation mengubur satu paragraf yang penting di bawah empat puluh yang tidak, sehingga halaman itu lengkap secara teknis tapi praktis tak terbaca. Under-documentation adalah cerminannya: hanya README dan tidak ada yang lain, tanpa catatan kenapa segalanya jadi begini. Dan orphan doc tidak punya pemilik dan tidak punya audiens, yang berarti tidak akan ada yang menyadari saat ia jadi salah.

teks
wiki graveyard → arsipkan agresif; menghapus itu perawatan copy-paste docs → satu sumber kebenaran, tautkan dari tempat lain over-documentation → pangkas ke yang dibutuhkan pembaca, tautkan sisanya under-documentation → minimal, tangkap "kenapa"-nya dalam ADR orphan docs → tanpa pemilik berarti adopsi atau hapus

TANDANYA Kalau engineer baru membaca dokumentasimu dan tetap bertanya di Slack, dokumentasinya gagal, sebanyak apa pun halaman yang ada.

Perlakukan dokumentasi sebagai produk

Pergeseran yang membuat semua ini melekat adalah berhenti menganggap dokumentasi sebagai tugas tempelan pada kode dan mulai memperlakukannya sebagai produk dengan pengguna. Developer yang membaca README-mu adalah pengguna. Engineer on-call yang membuka runbook-mu jam 3 pagi adalah pengguna. Mereka punya pekerjaan yang harus selesai, anggaran perhatian yang terbatas, dan toleransi rendah terhadap dibohongi.

Pola pikir produk mengubah pertanyaan yang kamu ajukan. Bukan “apakah kita sudah menuliskannya” melainkan “apakah pembaca bisa menemukannya, memercayainya, dan menindaklanjutinya”. Kamu berinvestasi pada dokumentasi seperti kamu berinvestasi pada kode, dengan kepemilikan, review, test, dan penghapusan, karena imbalannya sama: beban kognitif lebih kecil, onboarding lebih cepat, lebih sedikit interupsi, dan sistem yang tidak hidup atau mati bersama orang yang kebetulan membangunnya.

Dokumentasi yang berumur lebih panjang dari timnya bukan dokumentasi yang paling banyak bicara. Ia dokumentasi yang penulisnya memilah apa yang ditulis berdasarkan tujuan, men-generate yang bisa di-generate, membekukan yang historis, menguji yang operasional, dan memberi tiap halaman seorang pemilik.

POLA PIKIRNYA Dokumentasi adalah produk dan developer adalah penggunanya. Investasikan padanya seperti pada kode, dan ia akan bertahan lebih lama dari orang yang menulisnya.