Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,17 @@ enum ParseError {
- `# Panics`: If your function may panic, you must document the specific
conditions when that might happen. Callers need to know what to avoid.

- `# Errors`: For functions returning a `Result`, this section explains what
kind of errors can occur and under what circumstances. Callers need this
information to write robust error handling logic.

- **Question:** Ask the class why documenting panics is so important in a
language that prefers returning `Result`.
- **Question:** Ask the class why documenting panics is so important in a
language that prefers returning `Result`.

- **Answer:** Panics are for unrecoverable, programming errors. A library
should not panic unless a contract is violated by the caller. Documenting
these contracts is essential.

- `# Errors`: For functions returning a `Result`, this section explains what
kind of errors can occur and under what circumstances. Callers need this
information to write robust error handling logic.

- `# Safety` comments document safety preconditions on unsafe functions that
must be satisfied, or else undefined behavior might result. They are discussed
in detail in the Unsafe Rust deep dive.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ fn sync_to_server(...)
- Motivation: Documentation that merely repeats name/signature information
provides nothing new to the API user.

Additionally, signature information may change over time without the
documentation being updated accordingly!
Additionally, signature information may change over time without the
documentation being updated accordingly!

- This is an understandable pattern to fall into!

Expand Down Expand Up @@ -83,20 +83,13 @@ documentation being updated accordingly!
Rule of Thumb: What information is missing from a user's perspective? Other
than name, signature, and irrelevant details of the implementation.

- Don't explain the basics of Rust or the standard library. Assume the reader of
doc comments has an intermediate understanding of the language itself. Focus
on documenting your API.
- Don't explain the basics of Rust or the standard library. Assume the reader
has an intermediate understanding of the language itself. Focus on documenting
your API.

For example, if your function returns `Result`, you don't need to explain how
`Result` or the question mark operators work.

- If there is a complex topic involved with the functions and types you're
documenting, signpost to a "source of truth" if one exists such as an internal
document, a paper, a blog post etc.

- Collaborate with Students: Go through the methods in the slide and discuss
what might be relevant to an API user.

## More to Explore

- The `#![warn(missing_docs)]` lint can be helpful for enforcing the existence
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@ fn sort_quickly<T: Ord>(to_sort: &mut [T]) { ... }

<details>

- Consider the example here, we discussed in
[what and why, not how and where](what-why-not-how-where.md) that internal
details are unlikely relevant to someone reading documentation.

Here we're discussing a counterexample.

- Ask the class: Is this comment necessary for this function?

- Narrative: Playing the part of an intermediary between the class and the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ a positive RoI.
who wrote it, for whom, and what material it is covering, and what resources
did they have.

- Fundamental library code often has Elaborate documentation, for example, the
standard library, highly reusable frameworks like serde and tokio. Teams
- Fundamental library code often has elaborate documentation, for example, the
standard library, highly reusable frameworks like Serde and Tokio. Teams
responsible for this code often have appropriate resources to write and
maintain elaborate documentation.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ pub enum MarcError {}
- Motivation: Readers of documentation will not be closely reading most of your
doc comments like they would dialogue in a novel they love.

Users will most likely be skimming and scan-reading to find the part of the
documentation that is relevant to whatever problem they're trying to solve in
the moment.
Users will most likely be skimming and scan-reading to find the part of the
documentation that is relevant to whatever problem they're trying to solve in
the moment.

Once a user has found a keyword or potential signpost that's relevant to them
they will begin to search for context surrounding what is being documented.
Once a user has found a keyword or potential signpost that's relevant to them
they will begin to search for context surrounding what is being documented.

- Ask the class: What do you look for in documentation? Focus on the
moment-to-moment searching for information here, not general values in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ fn sync_to_server() -> Future<Bool>;
/// Sends local edits to the server, overwriting concurrent edits
/// if any happened.
fn sync_to_server() -> Future<Bool>;

// bad
/// Returns an error if sending the email fails.
fn send(&self, email: Email) -> Result<(), Error>;

// good
/// Queues the email for background delivery and returns immediately.
///
/// Returns an error immediately if the email is malformed.
fn send(&self, email: Email) -> Result<(), Error>;
```
Expand All @@ -36,31 +38,19 @@ fn send(&self, email: Email) -> Result<(), Error>;
- Motivation: API designers can over-commit to the idea that a function name and
signature is enough documentation.

It's better than nothing, but it's worse than good documentation.

- Again, names and types are _part_ of the documentation. They are not always
the full story!

- Consider the behavior of functions that are not covered by the name, parameter
names, or signature of that function.

In the example on the slide it is not obvious that `sync_to_server()` could
overwrite something (leading to a data loss), so document that.
- It is not obvious that `sync_to_server()` could overwrite something (leading
to a data loss), so document that.

In the email example, it is not obvious that the function can return success
and still fail to deliver the email.
- In the email example, it is not obvious that the function can return success
and still fail to deliver the email.

- Use comments to disambiguate. Nuanced behaviors, behaviors that users of an
API could trip up on, should be documented.

For example, consider a remove() method on a business entity: There are many
ways to remove an entity!

Is it removing the entity from the database? From the parent collection in
memory (unlink vs erase)?

If it is removing the data in the database, is the data actually being
deleted, or merely marked as deleted, but still recoverable (soft vs hard
delete)?

</details>
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,6 @@ Avoid documenting irrelevant details that may frequently change.
# // Copyright 2025 Google LLC
# // SPDX-License-Identifier: Apache-2.0
#
/// Sorts a slice. Implemented using recursive quicksort.

fn sort_quickly<T: Ord>(to_sort: &mut [T]) { /* ... */
}

// bad
/// Saves a `User` record to the Postgres database.
///
Expand Down Expand Up @@ -55,31 +50,20 @@ pub fn save_user(user: &User) -> Result<(), db::Error> {
faster than comments that explain the contract.

Internal information is likely irrelevant to a user. Imagine explaining in a
doc comment for a function that you're using for loops to solve a problem,
doc comment for a function that you're using `for` loops to solve a problem,
what is the point of this information?

- Consider the `sort_quickly` function above. Its documentation calls out that
it uses quicksort, but is this necessary?

It could be that another sorting function is used in the future, if that were
the case then this comment would need to be updated too. This is a point of
failure in documentation.

- It could be that the implementation is necessary to explain, but this is
likely due to whatever effects or invariants the user of that API needs to be
aware of instead.

Focus on those effects and invariants instead of instead of the implementation
details themselves.
Focus on those effects and invariants instead of the implementation details
themselves.

Reiterate: Implementation details can and will change, so do not explain these
details.

- Don't talk about where something is used for the sake of it.

This is another instance where this information can become stale quickly.

- Focus on what the function does (not how it is implemented) for a user trying
to reach this practical information as quickly as possible.
- Don't talk about where something is used, this is another instance where this
information can become stale quickly.

</details>