Dokumentasi yang hadir belum tentu dokumentasi yang membalas pertanyaan pembaca. Satu fungsi didokumentasikan dengan dua contoh, fungsi lain hanya satu kalimat, fungsi ketiga menyebut syarat panic tersembunyi di paragraf tengah — pembaca tidak pernah tahu di mana mencari informasi tertentu. Ekosistem Rust mengatasinya dengan konvensi section yang disepakati lintas crate: # Examples, # Arguments, # Panics, # Errors, dan # Safety. Konvensi ini membuat dokumentasi terprediksi: siapa pun yang membaca dokumentasi crate mana pun tahu bahwa section # Panics selalu berisi kondisi yang memicu panic. Chapter penutup section ini merangkai kelima section tersebut menjadi dokumentasi fungsi publik yang lengkap, sekaligus memasang penjaga agar crate kita tidak pernah kembali ke kondisi tanpa dokumentasi.
Masalah: Dokumentasi yang Acak Arahnya #
Tanpa struktur, doc comment cenderung menulis apa yang kebetulan terpikir penulisnya. Informasi penting justru yang paling sering tercecer: fungsi yang panic pada masukan kosong tidak menyebutnya, fungsi yang mengembalikan Result tidak menjelaskan arti error-nya, dan contoh pemakaian absen karena penulis menganggap tanda tangan fungsinya sudah “jelas”. Pembaca yang tidak tahu kontrak fungsi akan menemukannya dengan cara paling mahal — lewat program yang crash di production. Konvensi section membalik keadaan: penulis mendapat daftar periksa bawaan, pembaca mendapat tempat yang pasti untuk tiap jenis informasi.
Lima Section Konvensional #
Komunitas Rust mengenal lima section standar berikut, ditulis sebagai heading level satu di dalam doc comment:
| Section | Isi | Wajib untuk |
|---|---|---|
# Examples | Contoh pemakaian yang bisa dijalankan sebagai doc test | Semua fungsi publik bila memungkinkan |
# Arguments | Makna tiap parameter, satu entri per parameter | Fungsi dengan parameter yang maknanya tidak langsung terbaca |
# Panics | Kondisi masukan yang membuat fungsi panic | Fungsi yang bisa panic, bukan cuma mengembalikan Result |
# Errors | Makna tiap variasi Err yang dikembalikan | Fungsi yang mengembalikan Result |
# Safety | Kontrak keamanan yang harus dipenuhi pemanggil | Fungsi atau blok unsafe |
Nama section memakai bahasa Inggris sesuai konvensi ekosistem — sama seperti nama identifier, istilah ini dipertahankan agar dokumentasi kita seragam dengan dokumentasi crate lain dan dengan dokumentasi standar Rust sendiri. Pada Chapter Doc Test kita sempat memakai heading # Contoh; kini kita naik ke bentuk bakunya.
Mekanisme: Heading yang Dikenali, Contoh yang Dijalankan #
Rustdoc merender heading # di dalam doc comment sebagai judul section di halaman item, dan seluruh isi section ditampilkan di bawahnya berurutan. Blok kode berpagar di dalam # Examples diperlakukan seperti blok di doc comment mana pun: dibungkus menjadi program eksternal, dikompilasi, dan dijalankan oleh cargo test. Section # Panics dan # Errors tidak diperiksa otomatis oleh compiler — kejujurannya dijaga oleh dua hal: doc test yang mendemonstrasikan kontrak, dan review. Justru karena tidak dijaga mesin, kedisiplinan menulis section ini menjadi pembeda dokumentasi yang dipercaya dari yang sekadar hadir.
Contoh: Fungsi dengan Arguments, Panics, dan Examples #
Buat proyek cargo new parkir --lib, lalu isi src/lib.rs dengan fungsi biaya parkir berikut:
//! Crate `parkir` untuk penghitungan biaya parkir.
/// Menghitung biaya parkir mobil dengan tarif bertingkat.
///
/// Jam pertama dikenakan `tarif_jam_pertama`, sedangkan setiap jam
/// berikutnya dikenakan `tarif_jam_berikutnya`.
///
/// # Arguments
///
/// * `jam_parkir` — lama parkir dalam jam, harus lebih dari `0`
/// * `tarif_jam_pertama` — tarif untuk jam pertama, dalam rupiah
/// * `tarif_jam_berikutnya` — tarif per jam setelah jam pertama
///
/// # Panics
///
/// Fungsi ini panic bila `jam_parkir` bernilai `0`, karena durasi
/// parkir tidak mungkin nol jam.
///
/// # Examples
///
/// ```
/// let biaya = parkir::hitung_biaya(3, 5_000, 3_000);
/// assert_eq!(biaya, 11_000);
/// ```
pub fn hitung_biaya(jam_parkir: u32, tarif_jam_pertama: u32, tarif_jam_berikutnya: u32) -> u32 {
if jam_parkir == 0 {
panic!("jam parkir tidak boleh 0");
}
tarif_jam_pertama + (jam_parkir - 1) * tarif_jam_berikutnya
}Jalankan cargo test untuk memastikan contohnya benar:
cargo testOutput yang Dihasilkan:
running 2 tests
test src/lib.rs - hitung_biaya (line 21) ... ok
test src/lib.rs - cari_karcis (line 47) ... ok
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00sLaporan di atas diambil setelah fungsi kedua ditambahkan ke file yang sama — dua doc test dari dua fungsi. Mari kita bedah struktur doc comment hitung_biaya:
- Baris 3-6 (
/// Menghitung biaya parkir ... tarif bertingkat.): paragraf pembuka menjelaskan perilaku fungsi tanpa menyebut kata “Returns” — itu tugas paragraf ini, dan ringkasannya tampil di daftar item. - Baris 8-12 (
# Argumentsbeserta daftar bertitik): satu baris per parameter, menjelaskan satuan dan makna. Parameterjam_parkirdiberi catatanharus lebih dari 0— bibit dari kontrak yang nanti ditegaskan di# Panics. - Baris 14-17 (
# Panics): menyatakan kondisi panic secara eksplisit: masukan0. Tanpa section ini, pemanggil hanya mengetahui kontrak tersebut setelah program crash; dengan section ini, kontraknya bisa dibaca sebelum kode ditulis. - Baris 26-28 (
if jam_parkir == 0 { panic!(...) }): implementasi yang menepati section# Panics— dokumentasi dan kode menyebut kondisi yang sama. Bila kondisi panic diubah tanpa memperbarui doc comment, kedua-duanya berbohong. - Baris 19-24 (
# Examplesbeserta blok kode): contoh dengan angka nyata: 3 jam, tarif jam pertama5_000, tarif lanjutan3_000, hasil11_000— yaitu5_000 + 2 × 3_000. Blok ini dijalankan sebagai doc test, sehingga contoh dan implementasi saling menjaga. - Baris laporan
test src/lib.rs - hitung_biaya (line 21) ... ok: angkaline 21menunjuk pagar blok contoh — baris 21 pada file adalah pembuka ``` di dalam# Examples.
Contoh Kedua: Fungsi Result dengan Section Errors #
Fungsi yang mengembalikan Result menukar section # Panics dengan # Errors. Tambahkan ke src/lib.rs:
/// Mencari nomor karcis pelanggan di daftar parkir hari ini.
///
/// # Arguments
///
/// * `nomor_karcis` — nomor karcis yang dicari
/// * `daftar_karcis` — daftar nomor karcis yang masih aktif
///
/// # Errors
///
/// Mengembalikan `Err(String)` bila `nomor_karcis` tidak ditemukan
/// di `daftar_karcis`.
///
/// # Examples
///
/// ```
/// let daftar = vec![1024, 2048, 4096];
///
/// assert!(parkir::cari_karcis(2048, &daftar).is_ok());
/// assert!(parkir::cari_karcis(999, &daftar).is_err());
/// ```
pub fn cari_karcis(nomor_karcis: u32, daftar_karcis: &[u32]) -> Result<(), String> {
if daftar_karcis.contains(&nomor_karcis) {
Ok(())
} else {
Err(format!("karcis {} tidak ditemukan", nomor_karcis))
}
}Bagian yang patut dicermati: section # Errors menyebut tipe Err(String) dan kondisi kemunculannya, bukan sekadar “mengembalikan error bila gagal”. Contoh di # Examples pun sengaja menguji dua sisi kontrak — is_ok() untuk karcis yang ada dan is_err() untuk yang tidak. Kedua assertion inilah yang menjadi doc test cari_karcis (line 47) pada laporan di atas. Aturan praktisnya: setiap variasi Err yang bisa keluar dari fungsi wajib punya satu kalimat penjelasan di section # Errors.
Section Safety dan Menjaga Kehadiran Dokumentasi #
Section # Safety berlaku untuk API unsafe: dokumentasi wajib menyebut invarian yang harus dipenuhi pemanggil sebelum menyentuh fungsi tersebut — misalnya pointer harus valid, atau buffer harus berukuran cukup. Karena materi unsafe baru dibahas tuntas pada section lanjutan, cukup kita tanamkan aturannya sekarang: API unsafe tanpa # Safety dianggap tidak lengkap secara konvensi.
Terakhir, kehadiran dokumentasi bisa dijaga mesin lewat lint missing_docs. Tambahkan atribut crate-level berikut di src/lib.rs:
#![warn(missing_docs)]
/// Menghitung biaya parkir.
pub fn hitung_biaya() {}
pub fn tanpa_dokumentasi() {}Output yang Dihasilkan:
warning: missing documentation for a function
--> src/lib.rs:8:1
|
8 | pub fn tanpa_dokumentasi() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> src/lib.rs:1:9
|
1 | #![warn(missing_docs)]
| ^^^^^^^^^^^^Atribut #![warn(missing_docs)] di baris pertama mengaktifkan lint untuk seluruh crate, dan setiap item pub tanpa doc comment menimbulkan warning yang menunjuk lokasinya — fungsi tanpa_dokumentasi tertangkap, sedangkan hitung_biaya lolos karena didokumentasikan.
Ringkasan #
Konvensi section memberi struktur pada doc comment: # Examples memuat doctest yang dijalankan cargo test, # Arguments menjelaskan parameter, # Panics dan # Errors menyatakan kontrak kegagalan untuk dua model error yang berbeda, dan # Safety mengikat invarian API unsafe. Lint missing_docs menjaga agar tidak ada item pub yang telanjang dokumentasi. Documentation section selesai — dan bab berikutnya berpindah ke disiplin lain: menjaga bentuk kode itu sendiri dengan formatter rustfmt.