～Resultシステムの拡張とエラー設計～

# 第17回：エラーハンドリング（前編）
## ～Resultシステムの拡張とエラー設計～

### はじめに

効果的なエラー処理は、堅牢なシステムの基盤となります。今回はResultシステムの拡張とエラー値の設計について解説します。

### Resultシステムの拡張

```rust
// 拡張Result型
pub struct ExtendedResult<T, E> {
    inner: Result<T, E>,
    context: ErrorContext,
    default_handler: Option<Box<dyn ErrorHandler<E>>>,
}

impl<T, E> ExtendedResult<T, E> {
    pub fn new(result: Result<T, E>) -> Self {
        Self {
            inner: result,
            context: ErrorContext::new(),
            default_handler: None,
        }
    }
    
    pub fn with_context(mut self, context: ErrorContext) -> Self {
        self.context = context;
        self
    }
    
    pub fn with_default_handler<H: ErrorHandler<E> + 'static>(
        mut self,
        handler: H,
    ) -> Self {
        self.default_handler = Some(Box::new(handler));
        self
    }
    
    pub fn unwrap_or_handle(self) -> Result<T, E> {
        match self.inner {
            Ok(value) => Ok(value),
            Err(error) => {
                if let Some(handler) = self.default_handler {
                    handler.handle(error, &self.context)
                } else {
                    Err(error)
                }
            }
        }
    }
}

// エラーコンテキスト
#[derive(Clone, Debug)]
pub struct ErrorContext {
    location: Location,
    timestamp: SystemTime,
    trace: Backtrace,
    metadata: HashMap<String, Value>,
}

impl ErrorContext {
    pub fn add_metadata<K, V>(&mut self, key: K, value: V)
    where
        K: Into<String>,
        V: Into<Value>,
    {
        self.metadata.insert(key.into(), value.into());
    }
}
```

### デフォルトエラー値の設計

```rust
// デフォルトエラー値の定義
#[derive(Debug, Clone)]
pub enum SystemDefault<E> {
    Value(E),
    Handler(Box<dyn Fn() -> E + Send + Sync>),
}

// エラー型の拡張トレイト
pub trait ErrorExt: Sized {
    fn with_default(self, default: SystemDefault<Self>) -> DefaultError<Self>;
}

// デフォルトエラーラッパー
pub struct DefaultError<E> {
    inner: Option<E>,
    default: SystemDefault<E>,
}

impl<E> DefaultError<E> {
    pub fn unwrap(self) -> E {
        match self.inner {
            Some(error) => error,
            None => match &self.default {
                SystemDefault::Value(ref value) => value.clone(),
                SystemDefault::Handler(handler) => handler(),
            },
        }
    }
}

// エラー変換機構
pub trait ErrorConverter<From, To> {
    fn convert(&self, from: From) -> To;
}

pub struct DefaultErrorConverter<From, To> {
    converter: Box<dyn Fn(From) -> To + Send + Sync>,
}

impl<From, To> DefaultErrorConverter<From, To> {
    pub fn new<F>(converter: F) -> Self
    where
        F: Fn(From) -> To + Send + Sync + 'static,
    {
        Self {
            converter: Box::new(converter),
        }
    }
}
```

### エラー変換機構

```rust
// エラー変換システム
pub struct ErrorConversionSystem {
    converters: HashMap<(TypeId, TypeId), Box<dyn Any + Send + Sync>>,
}

impl ErrorConversionSystem {
    pub fn register_converter<From, To>(
        &mut self,
        converter: DefaultErrorConverter<From, To>,
    )
    where
        From: 'static,
        To: 'static,
    {
        let key = (TypeId::of::<From>(), TypeId::of::<To>());
        self.converters.insert(key, Box::new(converter));
    }
    
    pub fn convert<From, To>(&self, from: From) -> Result<To, ConversionError>
    where
        From: 'static,
        To: 'static,
    {
        let key = (TypeId::of::<From>(), TypeId::of::<To>());
        
        if let Some(converter) = self.converters.get(&key) {
            if let Some(converter) = converter.downcast_ref::<DefaultErrorConverter<From, To>>() {
                Ok((converter.converter)(from))
            } else {
                Err(ConversionError::InvalidConverter)
            }
        } else {
            Err(ConversionError::NoConverter)
        }
    }
}

// マクロによる便利な構文
#[macro_export]
macro_rules! with_default {
    ($result:expr, $default:expr) => {
        ExtendedResult::new($result).with_default_handler(|e| Ok($default))
    };
}
```

### 実装例：カスタムエラー型の実装

```rust
// カスタムエラー型の実装例
#[derive(Debug, Clone)]
pub enum AppError {
    Database(DatabaseError),
    Validation(ValidationError),
    System(SystemError),
    #[default]
    Unknown,
}

impl AppError {
    pub fn as_database(&self) -> Option<&DatabaseError> {
        match self {
            Self::Database(err) => Some(err),
            _ => None,
        }
    }
    
    pub fn is_critical(&self) -> bool {
        matches!(self, Self::System(_))
    }
}

// エラーハンドリングシステム
pub struct ErrorHandlingSystem {
    conversion_system: ErrorConversionSystem,
    default_handlers: HashMap<TypeId, Box<dyn ErrorHandler<AppError>>>,
}

impl ErrorHandlingSystem {
    pub fn handle_error<E: Into<AppError>>(&self, error: E) -> Result<(), AppError> {
        let app_error = error.into();
        
        // クリティカルエラーの特別処理
        if app_error.is_critical() {
            return Err(app_error);
        }
        
        // デフォルトハンドラーの適用
        if let Some(handler) = self.get_handler(&app_error) {
            handler.handle(app_error, &ErrorContext::new())
        } else {
            Err(app_error)
        }
    }
}

// 使用例
async fn example_usage() -> Result<(), AppError> {
    let mut system = ErrorHandlingSystem::new();
    
    // データベース操作
    let result = database_operation()
        .map_err(AppError::Database)
        .with_default(SystemDefault::Value(AppError::Unknown));
        
    match result {
        Ok(value) => {
            // 正常処理
            Ok(())
        }
        Err(error) => {
            // エラー処理
            system.handle_error(error)
        }
    }
}

// デフォルト値を使用した例
fn process_with_default<T>(
    operation: impl FnOnce() -> Result<T, AppError>,
    default: T,
) -> T {
    with_default!(operation(), default).unwrap_or_handle().unwrap_or(default)
}
```

### 今回のまとめ

1. 柔軟なResultシステムの拡張
2. 効果的なデフォルトエラー値の設計
3. 型安全なエラー変換機構
4. 実用的なエラーハンドリングシステム

### 次回予告

第18回では、エラーハンドリングの後編として、エラーの伝播制御とリカバリーメカニズムについて解説します。

### 参考資料
- Error Handling in Rust
- Type-Safe Error Management
- Error Recovery Patterns
- Resilient System Design