Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Idiomatic Rust code guidance based on Apollo GraphQL's best practices handbook for ownership, errors, and performance.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/chapter_08.md
1# Chapter 8 - Comments vs Documentation23> Clear code beats clear comments. However, when the why isn't obvious, comment it plainly - or link to where you can read more context.45## 8.1 Comments vs Documentation: Know the Difference67| Purpose | Use `// comment` | Use `/// doc` or `//! crate doc` |8|-------------- |------------------------------------------- |---------------------------------------------------------------- |9| Describe Why | โ Yes - explains tricky reasoning | โ Not for documentation |10| Describe API | โ Not useful | โ Yes - public interfaces, usage, details, errors, panics |11| Maintainable | ๐จ Often becomes obsolete and hard to reason | โ Tied to code, appears in generated docs and can run test cases |12| Visibility | Local development only | Exported to users and tools like `cargo doc` |1314## 8.2 When to use comments1516Use `//` comments (double slashed) when something can't be expressed clearly in code, like:17* **Safety Guarantees**, some of which can be better expressed with code conditionals.18* Workarounds or **Optimizations**.19* Legacy or **platform-specific** behaviors. Some of them can be expressed with `#[cfg(..)]`.20* Links to **Design Docs** or **ADRs**.21* Assumptions or **gotchas** that aren't obvious.2223> Name your comments! For example, a comment regarding a safety guarantee should start with `// SAFETY: ...`.2425### โ Good comment:26```rust27// SAFETY: `ptr` is guaranteed to be non-null and aligned by caller28unsafe { std::ptr::copy_nonoverlapping(src, dst, len); }29```3031### โ Design context comment:32```rust33// CONTEXT: Reuse root cert store across subgraphs to avoid duplicate OS calls:34// [ADR-12](link/to/adr-12): TLS Performance on MacOS35```3637## 8.3 When comments get in the way3839Avoid comments that:40* Restate obvious things (`// increment i by 1 for the next loop`).41* Can grow stale over time.42* `TODO`s without actions (links to some versioned issue).43* Could be replaced by better naming or smaller functions.4445### โ Bad comment:46```rust47fn compute(counter: &mut usize) {48// increment by 149*counter += 1;50}51```5253### โ Too long or outdated54```rust55// Originally written in 2028 for some now-defunct platform56```5758## 8.4 Don't Write Living Documentation (living comments)5960Comments as a "living documentation" is a **dangerous myth**, as comments are **not free**:61* They **rot** - nobody compiles comments.62* They **mislead** - readers usually assume they are true with no critique, e.g. "the other developer knows this code better than I do".63* They **go stale** - unless maintained with the code, they become irrelevant.64* They are **noisy** - comments can clutter your code with multiple unnecessary lines.6566If something deserves to live beyond a PR, put it in:67* An **ADR** (Architectural Design Record).68* A Design Document.69* Document it **in code** by using types, doc comments, examples, renaming code blocks into cleaner functions.70* Add tests to cover and explain the change.7172> ### ๐จ If you find a comment, **read it in context**. Does it still make sense? If not, remove or update it, or ask for help. Comments should bother you.7374## 8.5 Replace Comments with Code7576Instead of long commented blocks, break logic into named helper functions:7778#### โ Commented code block:79```rust80fn save_user(&self) -> Result<(), MyError> {81// check if the user is authenticated82if self.is_authenticated() {83// serialize user data84let data = serde_json::to_string(self)?;85// write to file86std::fs::write(self.path(), data)?;87}88}89```90**โ Extract for clarity**:9192```rust93fn save_auth_user(&self) -> Result<PathBuf, MyError> {94if self.is_authenticated() {95let path = self.path();96let serialized_user = serde_json::to_string(self)?;97std::fs::write(path, serialized_user)?;98Ok(path)99} else {100Err(MyError::UserNotAuthenticated)101}102}103```104105## 8.6 `TODO` should become issues106107Don't leave `// TODO:` scattered around the codebase with no owner. Instead:1081. File Github Issue or Jira Ticket. (Prefer github issues on public repositories).1092. Reference the issue in the code:110111```rust112// TODO(issue #42): Remove workaround after bugfix113```114115This makes `TODO`s trackable, actionable and visible to everyone.116117## 8.7 When to use doc comments118119Use `///` doc comments to document:120* All **public functions, structs, traits, enums**.121* Their purpose, their usage and their behaviors.122* Anything developers need to understand how to use it correctly.123* Add context that related to `Errors` and `Panics`.124* Plenty of examples.125126### โ Good doc comment:127128```rust129/// Loads [`User`] profile from disk130///131/// # Error132/// - Returns [`MyError`] if the file is missing [`MyError::FileNotFound`].133/// - Returns [`MyError`] if the content is an invalid Json, [`MyError::InvalidJson`].134fn load_user(path: &Path) -> Result<User, MyError> {...}135```136137**Doc comments can also include examples, links and even tests:**138139```rust140/// Returns the square of the integer part of any number.141/// Square is limited to `u128`.142///143/// # Examples144///145/// ```rust146/// assert_eq!(square(4.3), 16)147/// ```148fn square(x: impl ToInt) -> u128 { ... }149```150151## 8.8 Documentation in Rust: How, When and Why152153Rust provides **first-class documentation tooling** via rustdoc, which makes documenting your code a key part of writing idiomatic and maintainable rust. There are doc specific lints to help with documentation, like:154155| Lint | Description |156|-------------- |------------------------------------------- |157| [missing_docs](https://doc.rust-lang.org/rustdoc/lints.html#missing_docs) | Warns that a public functions, struct, const, enum has missing documentation |158| [broken_intra_doc_links](https://doc.rust-lang.org/rustdoc/lints.html#broken_intra_doc_links) | Detects if an internal documentation link is broken. Specially useful when things are renamed. |159| [empty_docs](https://rust-lang.github.io/rust-clippy/master/#empty_docs) | Disallow empty docs - preventing bypass of `missing_docs` |160| [missing_panics_doc](https://rust-lang.github.io/rust-clippy/master/#missing_panics_doc) | Warns that documentation should have a `# Panics` section if function can panic |161| [missing_errors_doc](https://rust-lang.github.io/rust-clippy/master/#missing_errors_doc) | Warns that documentation should have a `# Errors` section if function returns a `Result` explaining `Err` conditions |162| [missing_safety_doc](https://rust-lang.github.io/rust-clippy/master/#missing_safety_doc) | Warns that documentation should have a `# Safety` section if public facing functions have visible unsafe blocks |163164165### Difference between `///` and `//!`166167| Style | Used for | Scope |Example |168|---------- |------------------------------ |------------------------------------------- |---------------------------------------------------------------- |169| `///` | Line doc comment | Public items like struct, fn, enum, consts | Documenting, giving context and usage to `fn`, `struct`, `enum`, etc |170| `//!` | Module level doc comment | Modules or entire crates | Explaining crate/module purpose with common use cases and quickstart |171172### `///` Item level documentation173174Use `///` for functions, structs, traits, enums, const, etc:175176```rust177/// Adds two numbers together.178///179/// # Examples180///181/// ```182/// let result = my_crate::add(2, 3);183/// assert_eq!(result, 5);184/// ```185pub fn add(a: i32, b: i32) -> i32 {186a + b187}188```189* โ Write clear and descriptive **What it does** and **how to use it**.190* โ Use `# Examples` section to better explain **how to use it**.191* โ Prefer writing examples that can be tested via `cargo test`, even if you have to hide their output with starting `#`:192```rust193/// ```194/// let result = my_crate::add(2, 3);195/// # assert_eq!(result, 5);196/// ```197```198* โ Use `# Panics`, `# Errors` and `# Safety` sections when relevant.199* Add relevant context to the type.200201### `//!` Module/Crate level Documentation202203Use `//!` when you want to document the **purpose of a module or a crate**. It is places at the top of a `lib.rs` or `mod.rs` file, for example `engine/mod.rs`:204```rust205//! This module implements a custom chess engine.206//!207//! It handles board state, move generation and check detection.208//!209//! # Example210//! ```211//! let board = chess::engine::Board::default();212//! assert!(board.is_valid());213//! ```214```215216## 8.9 Checklist for Documentation coverage217218๐ฆ Crate-Level (lib.rs)219- [ ] `//!` doc at top explains **what the crate does**, and **what problems it solves**.220- [ ] Includes crate-level `# Examples` or pointers to modules.221222๐ Modules (mod.rs or inline)223- [ ] `//!` doc explains **what this module is for**, its **exports**, and **invariants**.224- [ ] Avoid repeating doc comments on re-exported items unless clarification is needed.225226๐งฑ Structs, Enums, Traits227- `///` doc explains:228- [ ] The role this type plays.229- [ ] Invariants or expectations.230- [ ] Example construction or usage.231- [ ] Consider using [`#[non_exhaustive]`](https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute) if external users may match on it.232233๐ง Functions and Methods234- `///` doc covers:235- [ ] What it does.236- [ ] Parameters and their meaning.237- [ ] Return value behavior.238- [ ] Edge cases (`# Panics`, `# Errors`).239- [ ] Usage example, `# Examples`.240241๐ Traits242- [ ] Explain the **purpose** of the trait (marker? dynamic dispatch?).243- [ ] Doc for each method โ include **when/why** to implement it.244- [ ] Document clearly default implemented methods and when to override.245246๐ฆ Public Constants247- [ ] Document what they configure and when you'd want to use them.248249### ๐ Best Practices250* โ Use examples generously โ they double as test cases.251* โ Prefer clarity over formality โ it's for humans, not machines.252* โ Prefer doc comments to explain usage, and leave implementation details to code comments if needed.253* โ Use `cargo doc --open` to check your output often.254* โ Add `#![deny(missing_docs)]` and other relevant doc lints in top-level modules if you want to enforce full doc coverage.255