Back to all reviewers

Design flexible APIs

tokio-rs/tokio
Based on 5 comments
Rust

When designing APIs, prioritize flexibility, ergonomics, and intuitiveness to create better user experiences. APIs should accept the most general parameter types appropriate for the functionality, handle edge cases gracefully, and provide methods that align with user expectations.

API Rust

Reviewer Prompt

When designing APIs, prioritize flexibility, ergonomics, and intuitiveness to create better user experiences. APIs should accept the most general parameter types appropriate for the functionality, handle edge cases gracefully, and provide methods that align with user expectations.

Key practices:

  1. Accept general parameter types (e.g., impl Into<String> instead of String)
  2. For asynchronous operations, consider returning values directly from awaited functions
  3. Provide inspection methods that allow users to query object state
  4. Handle edge cases explicitly in your API design

Example of flexible parameter types:

// Instead of this:
pub fn name(&mut self, name: String) -> &mut Self {
    // implementation
}

// Prefer this:
pub fn name(&mut self, name: impl Into<String>) -> &mut Self {
    let name = name.into();
    // implementation
}

Example of intuitive async API design:

// Instead of requiring separate calls:
pub async fn wait(&self) {
    // implementation that just waits
}
pub fn get(&self) -> Option<&T> {
    // implementation
}

// Consider this more ergonomic design:
pub async fn wait(&self) -> &T {
    // implementation that returns the value directly
}

Example of providing inspection methods:

impl<T> Receiver<T> {
    /// Checks if this receiver is finished.
    ///
    /// Returns true if this receiver has been polled and yielded a result.
    pub fn is_finished(&self) -> bool {
        self.inner.is_none()
    }
    
    // Additional inspection methods to query other aspects of state
}
5
Comments Analyzed
Rust
Primary Language
API
Category

Discussion Thread