| name | klabnik-teaching-rust |
| description | Write Rust code in the style of Steve Klabnik, author of "The Rust Programming Language." Emphasizes clear, idiomatic code that teaches as it goes. Use when writing example code, documentation, or code that others will learn from. |
| tags | documentation, learning, idioms, traits, generics, error-handling, cargo, crates, beginner-friendly, practical |
Steve Klabnik Style Guide
Overview
Steve Klabnik is the author of "The Rust Programming Language" (The Book) and was Rust's documentation lead. His gift: explaining complex concepts clearly. His code is designed to be read and understood, not just executed.
Core Philosophy
"Documentation is a love letter to your future self."
"The best code is code that teaches."
Klabnik believes that code should be approachable. Clever code that confuses readers is worse than simple code that everyone understands.
Design Principles
-
Teach Through Code: Every example should illuminate, not obscure.
-
Progressive Complexity: Start simple, add complexity as needed.
-
Explicit Over Implicit: Show what's happening, don't hide it.
-
Documentation as Code: Docs are as important as implementation.
When Writing Code
Always
- Write doc comments for public items (
/// for items, //! for modules)
- Include examples in documentation that compile and run
- Use descriptive variable names that explain purpose
- Prefer explicit types when teaching,
impl Trait when not
- Include error messages that help users understand what went wrong
Never
- Write "clever" one-liners that sacrifice clarity
- Skip documentation for public APIs
- Use abbreviations in public interfaces
- Leave users guessing about failure modes
Prefer
match over if let chains for exhaustiveness
- Named structs over tuples for public APIs
Result with descriptive error types
- Explicit lifetimes in teaching code
Code Patterns
Documentation That Teaches
pub struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
pub fn new(width: u32, height: u32) -> {
(width > , );
(height > , );
Rectangle { width, height }
}
(&) {
.width * .height
}
(&, other: &Rectangle) {
.width > other.width && .height > other.height
}
}
Descriptive Error Types
use std::fmt;
use std::error::Error;
#[derive(Debug)]
pub enum ConfigError {
FileNotFound { path: String },
ParseError { line: usize, message: String },
MissingField { field: &'static str },
InvalidValue { field: &'static str, value: String, expected: &'static str },
}
impl fmt::Display for ConfigError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ConfigError::FileNotFound { path } => {
write!(f, "configuration file not found: {}", path)
}
ConfigError::ParseError { line, message } => {
write!(f, "parse error on line {}: {}", line, message)
}
ConfigError::MissingField { field } => {
write!(f, "missing required field: {}", field)
}
ConfigError::InvalidValue { field, value, expected } => {
write!(f, "invalid value for {}: got '{}', expected {}",
field, value, expected)
}
}
}
}
{}
Progressive API Design
let client = Client::new();
let response = client.get("https://example.com").send()?;
let client = Client::builder()
.timeout(Duration::from_secs(10))
.build()?;
let client = Client::builder()
.timeout(Duration::from_secs(10))
.pool_max_idle_per_host(10)
.danger_accept_invalid_certs(true)
.build()?;
pub struct ClientBuilder {
timeout: Option<Duration>,
max_idle: usize,
accept_invalid_certs: bool,
}
impl ClientBuilder {
pub fn new() -> Self {
ClientBuilder {
timeout: None,
max_idle: 5,
accept_invalid_certs: ,
}
}
( , timeout: Duration) {
.timeout = (timeout);
}
( , accept: ) {
.accept_invalid_certs = accept;
}
() <Client, ClientError> {
}
}
Teaching Ownership Through Examples
fn takes_ownership(s: String) {
println!("{}", s);
}
fn borrows(s: &String) {
println!("{}", s);
}
fn modifies(s: &mut String) {
s.push_str(" world");
}
fn main() {
let s1 = String::from("hello");
takes_ownership(s1);
let s2 = String::from("hello");
borrows(&s2);
println!("{}", s2);
let mut s3 = String::from("hello");
(& s3);
(, s3);
}
Module Organization
pub use self::widget::Widget;
pub use self::error::{Error, Result};
mod widget;
mod error;
mod internal;
Mental Model
Klabnik writes code by asking:
- Who will read this? Write for them, not for the compiler.
- What might confuse them? Address it in docs or code structure.
- What's the simplest version? Start there.
- Does the error help? Errors should guide, not frustrate.
The Rust Book's Teaching Method
- Introduce concepts one at a time
- Show concrete examples before abstractions
- Explain the "why" behind the "what"
- Build complexity gradually
- Always provide working code