In this lesson, you will learn how to design flexible Rust APIs that allow users to inject their own custom logic without you needing to modify your original source code.
The Open-Closed Principle in Rust
The goal of "Designing for Extension" is to make your library "open for extension but closed for modification." In Rust, we achieve this by using Traits as extension points. Instead of hardcoding logic inside your structs, you define an interface (a trait) that describes what the behavior should look like, and let the user define how it works for their specific needs.
Using Generic Constraints as Hooks
Imagine you are writing a data processor. If you hardcode the processing logic, your users are stuck with your implementation. By using a generic type parameter with a trait bound, you turn your struct into a template that accepts any type satisfying that interface.
// This trait is our "Extension Hook"
pub trait DataProcessor {
fn process(&self, data: &str) -> String;
}
// Our library struct is open to any type that implements the trait
pub struct Engine<T: DataProcessor> {
processor: T,
}
impl<T: DataProcessor> Engine<T> {
pub fn run(&self, input: &str) {
let result = self.processor.process(input);
println!("Processed: {}", result);
}
}
By structuring your code this way, a user can create their own struct, implement DataProcessor for it, and plug it into your Engine without ever touching your library files. They could, for instance, create a LoggingProcessor or a DatabaseSaverProcessor, and your Engine will execute them perfectly.
Why this matters
When you design for extension, you stop acting as a gatekeeper for functionality. Instead, you act as an orchestrator. You provide the structure and the flow, while your users provide the specialized behavior. This leads to cleaner, more maintainable code that grows in utility the more users add their own custom implementations.
Key Takeaway: By using generic trait bounds as extension points, you allow users to plug their own custom logic into your codebase, keeping your library stable while enabling endless functionality.