Skip to content

Conversation

@tall-vase
Copy link
Collaborator

Includes most of chapter 1 of foundations of API Design for Idiomatic Rust. Brought in from the gdoc. Tests have not been run locally yet, formatting has.

@gribozavr
Copy link
Collaborator

gribozavr commented Dec 5, 2025

src/idiomatic/foundations-api-design/clarity-readability.md is being added, but it is empty and it is not linked from SUMMARY.md. Delete it?

(GitHub does not allow me to leave a comment on an empty file)

@@ -0,0 +1,3 @@
---
minutes: 2
---
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you intend to add something here?

Compare: https://github.com/google/comprehensive-rust/blob/main/src/idiomatic/leveraging-the-type-system.md?plain=1

At the very least, a title and {{%segment outline}} are needed.

Comment on lines +21 to +23
It's important to write doc comments that developers will appreciate reading,
that gives them the information they are looking for and doesn't just re-state
the obvious.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
It's important to write doc comments that developers will appreciate reading,
that gives them the information they are looking for and doesn't just re-state
the obvious.
Good doc comments provide information that the code, names, and types
cannot, without restating the obvious information.

More concise wording; more actionable ("information they are looking for" - not very actionable); more common spelling ("restate");.

Comment on lines +7 to +8
Function names and type signatures already document some information, avoid
repeating them!
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Function names and type signatures already document some information, avoid
repeating them!
Names and type signatures communicate a lot of information, don't repeat it in comments!

/// Parses an ipv4 from a str. Returns an option for failure modes.
fn parse_ip_addr_v4(input: &str) -> Option<IpAddrV4> { ... }

// TODO: couple more of these, for the instructor to go through with students.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My favorite:

struct BusinessAsset {
  /// The customer id.
  let customer_id: u64,
}

```

<details>
- Motivation: Documentation that repeats name/signature information provides nothing new to the API user.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Motivation: Documentation that repeats name/signature information provides nothing new to the API user.
- Motivation: Documentation that merely repeats name/signature information provides nothing new to the API user.

```

<details>
- Motivation: It can be easy to fall into a pattern of writing only for you, but most documentation is for people coming in with a different perspective.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Motivation: It can be easy to fall into a pattern of writing only for you, but most documentation is for people coming in with a different perspective.
- Background: The [curse of knowledge](https://en.wikipedia.org/wiki/Curse_of_knowledge) is a cognitive bias where experts assume that others have the same level of expertise and perspective.
- Motivation: Your reader does not have the same level of expertise and the same perspective as you. Don't write for people like yourself, write for others.


```rust
// TODO: What's a good illustration here?
```
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// expert writes for experts
/// Canonicalizes the MIR for the borrow checker.
///
/// This pass ensures that all borrows conform to the NLL-Polonius constraints
/// before we proceed to MIR-to-LLVM-IR translation.
pub fn canonicalize_mir(mir: &mut Mir) {
    // ...
}

// expert writes for newcomers
/// Prepares the Mid-level IR (MIR) for borrow checking.
///
/// The borrow checker operates on a simplified, "canonical" form of the MIR.
/// This function performs that transformation. It is a prerequisite for the
/// final stages of code generation.
///
/// For more about Rust's intermediate representations, see the
/// [rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/mir/index.html).
pub fn canonicalize_mir(mir: &mut Mir) {
    // ...
}

much information.
- Always ask: Is this documentation making it difficult for the API user? Are
they able to quickly grasp what they need or find out where they could need
it?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also say something like "Experts also read API level documentation. Doc comments might not be the right place to educate your audience about the basics of your domain. In that case, signpost and namedrop - divert people to long-form documentation."


# Predictable API

Keep your APIs predictable through naming conventions and implementing common
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Keep your APIs predictable through naming conventions and implementing common
Keep your APIs predictable by following naming conventions and implementing common

Parallel sentence structure.

Keep your APIs predictable through naming conventions and implementing common
traits.

<!-- TODO -->
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some speaker notes would be nice. What is the framing for this section?

Copy link
Collaborator

@gribozavr gribozavr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(misclick, I meant to simply "comment", but clicked "approve"; for clarity switching to "request changes")

# Naming Conventions

<details>
- One core component of readability and predictability is the way function names are composed.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- One core component of readability and predictability is the way function names are composed.
- One core component of API readability and predictability is the way function names are composed.

Rust's community developed naming conventions early, making them mostly
consistent in places like the standard library.

- Here we'll learn common components of rust method names, giving examples from
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Here we'll learn common components of rust method names, giving examples from
- In this section we'll learn common components of Rust method names, giving examples from

like a domain-specific language and quickly understand the functionality and use
cases of a method.

Rust's community developed naming conventions early, making them mostly
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Rust's community developed naming conventions early, making them mostly
- Rust community developed naming conventions early, making them mostly

<details>
- One core component of readability and predictability is the way function names are composed.

A formal and consistently-applied naming convention lets developers treat names
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A formal and consistently-applied naming convention lets developers treat names
- Formal and consistently-applied naming conventions let developers treat names

@@ -0,0 +1,31 @@
---
minutes: 2
---
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are great slides about naming conventions, but I have a couple of comments. I have left the comments on the "get" and "push" slides, but please apply them everywhere. All slides in this section should follow the same structure.

<details>
- Method for getting a reference-style value from an owned or borrowed value.

- Often used for getting something internal to a type.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Often used for getting something internal to a type.
- The type implementing an "as" method should contain one primary piece of data that is being borrowed out.
- The "as" naming convention does not work if the data type is an aggregate of many fields without an obvious primary one. Think about the call site:
```rust
my_vec.as_ptr() // OK
my_person.as_first_name() // does not read right, don't use "as_"
my_person.first_name() // OK
```
- If you want to have two getters that you need to distinguish, one that returns first name by value, and another one that returns it by reference, use `_ref` suffix:
```rust
impl Person {
fn first_name(&self) -> String
fn first_name_ref() -> &str
fn first_name_mut() -> &mut String
}
```

"Something internal" is quite unspecific. Here's my attempt at making it concrete. The "as" pattern is not applicable in every case, we need to have a type that wraps one specific thing that is being borrowed out.

Given the number of code examples, could you make a separate slide for this point that has all the necessary code snippets on the slide?

Comment on lines +13 to +14
Slice::get // ?
Slice::get_unchecked_mut // ?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Slice::get // ?
Slice::get_unchecked_mut // ?
slice::get // ?
slice::get_unchecked_mut // ?

2. What should we name these signatures?

```rust,compile_fail
// What are the types for these methods?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// What are the types for these methods?
// What are the types of these methods?

Option::is_some // ?
Slice::get // ?
Slice::get_unchecked_mut // ?
Option::as_ref // ?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Option::as_ref // ?
Option::as_ref // ?
str::from_utf8_unchecked_mut // ?
Rc::get_mut // ?
Vec::dedup_by_key // ?

types of the functions should be.

- Go through the unnamed methods and brainstorm what names those methods should
have.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add expected answers to the speaker notes (for both Qs).

Comment on lines +11 to +12
PathBuf::with_extension
PathBuf::with_file_name
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two methods are actually defined on Path (they are callable through PathBuf because PathBuf: Deref<Target=Path>)

@@ -0,0 +1,29 @@
---
Minutes: 2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Minutes: 2
minutes: 2

Prefix to a function that takes a borrowed value and creates an owned value

```rust
String::to_owned // &str -> String (&str is not consumed)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
String::to_owned // &str -> String (&str is not consumed)
str::to_owned // &str -> String (&str is not consumed)

minutes: 10
---

Mini-exercise
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Mini-exercise
# Exercise

minutes: 10
---

Mini-exercise
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename the file as well to remove "mini".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants