Skip to content

Commit fb9f4e5

Browse files
committed
docs: remove learning objectives, exercises, prerequisites, and time estimates
1 parent 803bd5c commit fb9f4e5

File tree

6 files changed

+6
-391
lines changed

6 files changed

+6
-391
lines changed

src/chapter-01-project-architecture.md

Lines changed: 6 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,6 @@
33

44
# Chapter 1: Project Architecture & Module Organization
55

6-
> **Learning Objectives**: Understand the Pierre codebase structure, Rust module system, and how the project is organized for maintainability and scalability.
7-
>
8-
> **Prerequisites**: Basic Rust syntax, familiarity with `cargo` commands
9-
>
10-
> **Estimated Time**: 2-3 hours
11-
126
---
137

148
## Introduction
@@ -508,12 +502,13 @@ src/
508502
├── mod.rs
509503
└── handlers/
510504
├── mod.rs
511-
├── strava_api.rs
505+
├── fitness_api.rs
512506
├── intelligence.rs
513507
├── goals.rs
514508
├── configuration.rs
515509
├── sleep_recovery.rs
516510
├── nutrition.rs
511+
├── recipes.rs
517512
└── connections.rs
518513
```
519514

@@ -522,21 +517,23 @@ src/
522517
```rust
523518
//! MCP tool handlers for all tool categories
524519

525-
pub mod strava_api;
520+
pub mod fitness_api;
526521
pub mod intelligence;
527522
pub mod goals;
528523
pub mod configuration;
529524
pub mod sleep_recovery;
530525
pub mod nutrition;
526+
pub mod recipes;
531527
pub mod connections;
532528

533529
// Re-export all handler functions
534-
pub use strava_api::*;
530+
pub use fitness_api::*;
535531
pub use intelligence::*;
536532
pub use goals::*;
537533
pub use configuration::*;
538534
pub use sleep_recovery::*;
539535
pub use nutrition::*;
536+
pub use recipes::*;
540537
pub use connections::*;
541538
```
542539

@@ -856,40 +853,6 @@ grep -r "pub struct" src/
856853

857854
---
858855

859-
## Practical Exercises
860-
861-
### Exercise 1: Explore Module Structure
862-
863-
1. Open `src/lib.rs` and count the `pub mod` declarations
864-
2. For each protocol module (`mcp`, `a2a`, `protocols`), open its `mod.rs`
865-
3. Draw a mental map of 3-level deep module hierarchy
866-
867-
**Expected output**: Understanding of how modules nest and relate
868-
869-
### Exercise 2: Trace an Import Path
870-
871-
1. Open `src/bin/pierre-mcp-server.rs`
872-
2. Find the import: `use pierre_mcp_server::mcp::multitenant::MultiTenantMcpServer`
873-
3. Navigate the path:
874-
- `src/lib.rs``pub mod mcp;`
875-
- `src/mcp/mod.rs``pub mod multitenant;`
876-
- `src/mcp/multitenant.rs``pub struct MultiTenantMcpServer`
877-
878-
**Expected output**: Comfortable navigating nested modules
879-
880-
### Exercise 3: Identify Feature Flags
881-
882-
1. Search `Cargo.toml` for `[features]` section
883-
2. Find all `#[cfg(feature = "...")]` in `src/database_plugins/factory.rs`
884-
3. Run build with different features:
885-
```bash
886-
cargo build --no-default-features --features postgresql
887-
```
888-
889-
**Expected output**: Understanding conditional compilation
890-
891-
---
892-
893856
## Rust Idioms Summary
894857

895858
| Idiom | Purpose | Example Location |

src/chapter-02-error-handling.md

Lines changed: 0 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,6 @@
33

44
# Chapter 2: Error Handling & Type-Safe Errors
55

6-
> **Learning Objectives**: Master structured error handling in Rust using `thiserror`, understand why Pierre eliminates `anyhow!()` from production code, and learn error propagation patterns.
7-
>
8-
> **Prerequisites**: Chapter 1, basic understanding of `Result<T, E>` and `Option<T>`
9-
>
10-
> **Estimated Time**: 3-4 hours
11-
126
---
137

148
## Introduction
@@ -803,110 +797,6 @@ async fn get_user_and_validate(id: &str) -> DatabaseResult<User> {
803797

804798
---
805799

806-
## Practical Exercises
807-
808-
### Exercise 1: Define a Custom Error Type
809-
810-
Create a configuration error type with `thiserror`:
811-
812-
```rust
813-
use thiserror::Error;
814-
815-
#[derive(Error, Debug)]
816-
pub enum ConfigError {
817-
// TODO: Add variants for:
818-
// - File not found (with path)
819-
// - Invalid format (with details)
820-
// - Missing required field (with field name)
821-
// - Invalid value (with field and value)
822-
}
823-
```
824-
825-
**Solution**:
826-
```rust
827-
#[derive(Error, Debug)]
828-
pub enum ConfigError {
829-
#[error("Configuration file not found: {path}")]
830-
FileNotFound { path: String },
831-
832-
#[error("Invalid configuration format: {details}")]
833-
InvalidFormat { details: String },
834-
835-
#[error("Missing required field: {field}")]
836-
MissingField { field: String },
837-
838-
#[error("Invalid value for {field}: {value}")]
839-
InvalidValue { field: String, value: String },
840-
}
841-
```
842-
843-
### Exercise 2: Implement Error Conversion
844-
845-
Add `From<std::io::Error>` for `ConfigError`:
846-
847-
```rust
848-
impl From<std::io::Error> for ConfigError {
849-
fn from(err: std::io::Error) -> Self {
850-
// TODO: Convert io::Error to appropriate ConfigError variant
851-
}
852-
}
853-
```
854-
855-
**Solution**:
856-
```rust
857-
impl From<std::io::Error> for ConfigError {
858-
fn from(err: std::io::Error) -> Self {
859-
match err.kind() {
860-
std::io::ErrorKind::NotFound => Self::FileNotFound {
861-
path: "unknown".to_string(), // Could enhance with path tracking
862-
},
863-
_ => Self::InvalidFormat {
864-
details: err.to_string(),
865-
},
866-
}
867-
}
868-
}
869-
```
870-
871-
### Exercise 3: Error Propagation Chain
872-
873-
Write a function that reads and parses a JSON config file:
874-
875-
```rust
876-
async fn load_json_config(path: &str) -> Result<Config, ConfigError> {
877-
// TODO:
878-
// 1. Read file with tokio::fs::read_to_string (returns io::Error)
879-
// 2. Parse JSON with serde_json::from_str (returns serde_json::Error)
880-
// 3. Use ? operator for both operations
881-
// 4. Implement necessary From conversions
882-
}
883-
```
884-
885-
**Solution**:
886-
```rust
887-
async fn load_json_config(path: &str) -> Result<Config, ConfigError> {
888-
let contents = tokio::fs::read_to_string(path)
889-
.await
890-
.map_err(|e| match e.kind() {
891-
std::io::ErrorKind::NotFound => ConfigError::FileNotFound {
892-
path: path.to_string(),
893-
},
894-
_ => ConfigError::InvalidFormat {
895-
details: e.to_string(),
896-
},
897-
})?;
898-
899-
let config: Config = serde_json::from_str(&contents)
900-
.map_err(|e| ConfigError::InvalidFormat {
901-
details: format!("JSON parse error: {}", e),
902-
})?;
903-
904-
Ok(config)
905-
}
906-
```
907-
908-
---
909-
910800
## Rust Idioms Summary
911801

912802
| Idiom | Purpose | Example Location |

src/chapter-03-configuration.md

Lines changed: 0 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,6 @@
33

44
# Chapter 3: Configuration Management & Environment Variables
55

6-
> **Learning Objectives**: Master environment-driven configuration in Rust, understand type-safe config patterns, and learn how Pierre implements the algorithm selection system.
7-
>
8-
> **Prerequisites**: Chapters 1-2, basic understanding of environment variables
9-
>
10-
> **Estimated Time**: 2-3 hours
11-
126
---
137

148
## Introduction
@@ -799,94 +793,6 @@ validated_config.use_in_production();
799793

800794
---
801795

802-
## Practical Exercises
803-
804-
### Exercise 1: Create a Custom Config Enum
805-
806-
Define a `CacheBackend` enum for cache configuration:
807-
808-
```rust
809-
#[derive(Debug, Clone, Serialize, Deserialize)]
810-
pub enum CacheBackend {
811-
// TODO: Add variants for:
812-
// - Memory (in-process LRU cache)
813-
// - Redis (with connection string)
814-
// - Disabled (no caching)
815-
}
816-
817-
impl CacheBackend {
818-
pub fn from_env() -> Self {
819-
// TODO: Parse from CACHE_BACKEND environment variable
820-
// Default to Memory if not set
821-
}
822-
}
823-
```
824-
825-
**Solution**:
826-
```rust
827-
#[derive(Debug, Clone, Serialize, Deserialize)]
828-
pub enum CacheBackend {
829-
Memory,
830-
Redis { connection_string: String },
831-
Disabled,
832-
}
833-
834-
impl CacheBackend {
835-
pub fn from_env() -> Self {
836-
match env::var("CACHE_BACKEND").ok() {
837-
Some(s) if s.starts_with("redis://") => Self::Redis {
838-
connection_string: s,
839-
},
840-
Some(s) if s == "disabled" => Self::Disabled,
841-
_ => Self::Memory, // Default
842-
}
843-
}
844-
}
845-
```
846-
847-
### Exercise 2: Add Validation to Config Struct
848-
849-
Implement validation for algorithm configuration:
850-
851-
```rust
852-
impl AlgorithmConfig {
853-
pub fn validate(&self) -> Result<(), ConfigError> {
854-
// TODO: Validate that algorithm names are known
855-
// Valid TSS algorithms: avg_power, normalized_power, hybrid
856-
// Valid MaxHR algorithms: fox, tanaka, nes, gulati
857-
}
858-
}
859-
```
860-
861-
**Solution**:
862-
```rust
863-
impl AlgorithmConfig {
864-
pub fn validate(&self) -> Result<(), ConfigError> {
865-
// Validate TSS algorithm
866-
match self.tss.as_str() {
867-
"avg_power" | "normalized_power" | "hybrid" => {}
868-
_ => return Err(ConfigError::InvalidValue {
869-
field: "tss".to_string(),
870-
value: self.tss.clone(),
871-
}),
872-
}
873-
874-
// Validate MaxHR algorithm
875-
match self.maxhr.as_str() {
876-
"fox" | "tanaka" | "nes" | "gulati" => {}
877-
_ => return Err(ConfigError::InvalidValue {
878-
field: "maxhr".to_string(),
879-
value: self.maxhr.clone(),
880-
}),
881-
}
882-
883-
Ok(())
884-
}
885-
}
886-
```
887-
888-
---
889-
890796
## Rust Idioms Summary
891797

892798
| Idiom | Purpose | Example Location |

0 commit comments

Comments
 (0)