The "Go the Extra Mile" Pattern
📖 EXPLANATION | Learn the three-idea framework for design decisions
The "Go the Extra Mile" pattern demonstrates progressive enhancement from simple solutions to maximum-value solutions.
The Three Ideas Framework
1st Idea: Solve the Problem
Minimal scope, just solves the immediate need:
#![allow(unused)] fn main() { // 1st Idea: Parse u32 only pub fn parse_u32(input: &str) -> Result<u32, String> { input.parse().map_err(|e| format!("Parse error: {e}")) } }
Characteristics:
- Single type (
u32only) - No telemetry
- No validation
- Solves the problem ✓
2nd Idea: 80/20 Sweet Spot
Generic version with significant value added:
#![allow(unused)] fn main() { // 2nd Idea: Generic parser pub fn parse_number<T: FromStr>(input: &str) -> Result<T, String> where T::Err: Display, { input.parse().map_err(|e| format!("Parse error: {e}")) } }
Characteristics:
- Works for all number types (
u32,i32,f64, etc.) - Minimal additional effort
- 80% more value
- 20% more work
When to use: Most of the time (best cost/benefit ratio)
3rd Idea: Maximum Value
Full-featured solution with complete correctness:
#![allow(unused)] fn main() { // 3rd Idea: Type-validated with OTEL instrumentation pub struct ValidatedNumber<T> { value: T, span: Span, // OTEL instrumentation } impl<T: FromStr> ValidatedNumber<T> { pub fn parse(input: &str, span_name: &str) -> Result<Self, String> { // Type-level validation prevents errors // OTEL spans provide observability // Weaver validation ensures compliance } } }
Characteristics:
- Type-level validation (prevents entire classes of errors)
- OTEL instrumentation (observability)
- Weaver validation (schema compliance)
- Maximum value
- Significant additional effort
When to use: For critical code where correctness is paramount
Decision Framework
Does the code need:
├─ Basic functionality only?
│ └─ 1st Idea ✓
├─ Works for multiple types + some observability?
│ └─ 2nd Idea ✓ (usually best choice)
└─ Type safety + full observability + validation?
└─ 3rd Idea ✓ (for critical paths)
Real-World Example: Configuration Loader
1st Idea: Load from ENV
#![allow(unused)] fn main() { pub fn load_config() -> Result<Config, String> { let host = std::env::var("DB_HOST") .map_err(|e| format!("Missing DB_HOST: {e}"))?; let port = std::env::var("DB_PORT") .map_err(|e| format!("Missing DB_PORT: {e}"))? .parse::<u16>() .map_err(|e| format!("Invalid port: {e}"))?; Ok(Config { host, port }) } }
✅ Works ❌ Only ENV, no file support, no validation
2nd Idea: ENV + File Support
#![allow(unused)] fn main() { pub fn load_config(source: &str) -> Result<Config, String> { match source { "env" => load_from_env(), "file" => load_from_file(), _ => Err("Invalid source".to_string()), } } fn load_from_env() -> Result<Config, String> { /* ... */ } fn load_from_file() -> Result<Config, String> { /* ... */ } }
✅ Works for multiple sources ✅ 80% more value (supports files, ENV) ✓ Best choice for most cases
3rd Idea: Type-Safe with Validation + OTEL
#![allow(unused)] fn main() { pub struct ValidatedConfig { config: Config, span: Span, // OTEL span } impl ValidatedConfig { pub fn load(source: &str, span_name: &str) -> Result<Self, String> { let start = SystemTime::now(); // Load config let config = load_config(source)?; // Validate validate_config(&config)?; // Create OTEL span let mut span = create_span(span_name); span.attributes.insert("source".to_string(), source.to_string()); let end = SystemTime::now(); span.complete(end.duration_since(start).ok()?)?; Ok(Self { config, span }) } } }
✅ Type-safe configuration ✅ OTEL instrumentation ✅ Validation enforcement ✓ For mission-critical systems
Applying the Pattern: Step by Step
Step 1: Start Simple
Write the simplest thing that works:
#![allow(unused)] fn main() { pub fn process_user(id: u32) -> Result<User, String> { // Query database let user = query_db(id)?; Ok(user) } }
Step 2: Consider 80/20
Does adding a feature provide disproportionate value?
#![allow(unused)] fn main() { // 2nd Idea: Support both ID and email lookup pub fn get_user(identifier: &str) -> Result<User, String> { if let Ok(id) = identifier.parse::<u32>() { query_db_by_id(id) } else { query_db_by_email(identifier) } } }
Cost: +10 lines Value: 80% more functionality
Step 3: Evaluate Going Further
Is maximum value worth the effort?
#![allow(unused)] fn main() { // 3rd Idea: Type-safe, validated, instrumented pub struct ValidatedUser { user: User, span: Span, } impl ValidatedUser { pub fn get(identifier: &str) -> Result<Self, String> { // Validation + OTEL + error handling } } }
Cost: +50 lines Value: Type safety + observability
Decision: Only go to 3rd idea if the value justifies the effort.
When to Stop at 1st Idea
✅ For utilities that are:
- Well-isolated
- Simple logic
- Low risk
- Rarely changed
#![allow(unused)] fn main() { // 1st idea is fine here - simple utility pub fn format_currency(amount: f64) -> String { format!("${:.2}", amount) } }
When to Use 2nd Idea (Most Common)
✅ For code that is:
- Reused in multiple places
- Needs flexibility
- Not mission-critical
- Has room for improvements
#![allow(unused)] fn main() { // 2nd idea - generic, flexible, good value pub fn parse<T: FromStr>(input: &str) -> Result<T, String> { input.parse().map_err(|e| format!("Parse error: {e}")) } }
When to Use 3rd Idea
✅ For code that is:
- Mission-critical (payments, security, core logic)
- Needs full observability
- Must prevent errors at compile time
- Complex enough to benefit from type system
#![allow(unused)] fn main() { // 3rd idea - type-safe, critical path pub struct ValidatedPayment { amount: PositiveAmount, currency: ValidatedCurrency, span: Span, } }
Combining Ideas in One System
A production system uses all three:
#![allow(unused)] fn main() { // 1st Idea: Simple utilities fn format_time(secs: u64) -> String { /* simple */ } // 2nd Idea: Core operations (most code) fn parse_config(source: &str) -> Result<Config, String> { /* generic */ } // 3rd Idea: Mission-critical operations struct ValidatedPayment { /* type-safe, instrumented */ } }
Benefits of This Pattern
- Clear thinking: Forces you to consider scope and value
- Cost-benefit: Justified effort for each level
- Flexibility: Easy to upgrade later
- Clarity: Team understands why certain code is complex
Common Mistakes
❌ Always using 3rd idea
- Over-engineered simple code
- Too much complexity
- Slower development
✅ Use appropriate idea level
❌ Stuck at 1st idea
- Limited by narrow scope
- Duplicate code
- Poor reusability
✅ Identify when 2nd idea helps
❌ Skipping evaluation
- Random complexity levels
- Inconsistent codebase
✅ Evaluate intentionally
Practical Checklist
For each piece of code, ask:
-
Does 1st idea solve the problem?
- If no → Can't proceed
- If yes → Consider 2nd idea
-
Would 2nd idea add 80% value with 20% effort?
- If no → Stop at 1st idea
- If yes → Consider 2nd idea
-
Does 3rd idea add critical value?
- If mission-critical → Use 3rd idea
- If improved but not critical → Use 2nd idea
- If over-engineering → Use 1st or 2nd idea
Real-World Example: Web Service
GET User Endpoint
1st Idea (minimal):
#![allow(unused)] fn main() { pub fn get_user(id: u32) -> Result<User, String> { query_database(id) } }
2nd Idea (flexible, instrumented):
#![allow(unused)] fn main() { pub fn get_user(id: u32) -> Result<(User, Span), String> { let span = create_span("get_user"); let user = query_database(id)?; Ok((user, span)) } }
3rd Idea (type-safe, fully instrumented):
#![allow(unused)] fn main() { pub struct ValidatedUserResponse { user: ValidatedUser, span: Span, } impl ValidatedUserResponse { pub fn get(id: ValidUserId) -> Result<Self, String> { // Type-safe, instrumented, validated } } }
Recommendation: Use 2nd idea for most endpoints. Only use 3rd for sensitive data (auth, payments).
Next Steps
- Observability & Quality - Implement 2nd and 3rd ideas
- Real-World Applications - See complete examples
Summary
The "Go the Extra Mile" pattern:
1st Idea: Minimal, solves the problem 2nd Idea: 80% more value, 20% more effort (usually best) 3rd Idea: Maximum value, significant effort (for critical paths)
Use this framework to make intentional design decisions.