m12-lifecycle について
m12-lifecycleは、Rust開発者向けのリソースライフサイクル設計スキルです。リソースの作成時期、使い方、後片付けの責任を検討し、Rustの仕組みに結び付けます。
主な機能
- 01リソースのコストとスコープの評価
- 02RAII、遅延初期化、プールの比較
- 03後片付けの責任とエラー処理の説明
- 04ライフサイクルパターンのテンプレート
- 05よくあるリソース管理エラーの提示
活用シーン
- 01データベース接続の再利用または作成方針の選択
- 02スコープ終了時の自動クリーンアップ設計
- 03遅延初期化とトランザクション境界の処理
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ actionbook/ rust-skills --skill m12-lifecycleインストール後、Claude Code で/m12-lifecycleを入力して読み込まれたか確認します。
詳細
リソースのライフサイクル
レイヤー 2:設計上の選択
中心となる問い
このリソースはいつ作成し、使用し、クリーンアップすべきですか?
ライフサイクルを実装する前に:
- リソースのスコープは何ですか?
- クリーンアップの責任者は誰ですか?
- エラーが発生した場合、どうなりますか?
ライフサイクルのパターン → 実装
| パターン | 場面 | 実装 |
|---|---|---|
| RAII | 自動クリーンアップ | Drop トレイト |
| 遅延初期化 | 作成の先送り | OnceLock、LazyLock |
| プール | 高コストなリソースの再利用 | r2d2、deadpool |
| ガード | スコープ内のアクセス | MutexGuard パターン |
| スコープ | トランザクション境界 | カスタム構造体 + Drop |
考えるための問い
ライフサイクルを設計する前に:
-
リソースのコストはどの程度ですか?
- 低コスト → 使用のたびに作成
- 高コスト → プールまたはキャッシュ
- グローバル → 遅延シングルトン
-
スコープは何ですか?
- 関数内 → スタック割り当て
- リクエスト単位 → 渡すか、抽出する
- アプリケーション全体 → static または Arc
-
エラーについてはどうしますか?
- クリーンアップが必須 → Drop
- クリーンアップは任意 → 明示的な close
- クリーンアップが失敗する可能性がある → close から Result を返す
上へたどる ↑
ドメインの制約(レイヤー 3)へ:
"How should I manage database connections?"
↑ Ask: What's the connection cost?
↑ Check: domain-* (latency requirements)
↑ Check: Infrastructure (connection limits)
| 問い | たどり先 | 確認事項 |
|---|---|---|
| コネクションプーリング | domain-* | 許容できるレイテンシはどの程度ですか? |
| リソース制限 | domain-* | インフラの制約は何ですか? |
| トランザクションのスコープ | domain-* | 何をアトミックにする必要がありますか? |
下へたどる ↓
実装(レイヤー 1)へ:
"Need automatic cleanup"
↓ m02-resource: Implement Drop
↓ m01-ownership: Clear owner for cleanup
"Need lazy initialization"
↓ m03-mutability: OnceLock for thread-safe
↓ m07-concurrency: LazyLock for sync
"Need connection pool"
↓ m07-concurrency: Thread-safe pool
↓ m02-resource: Arc for sharing
クイックリファレンス
| パターン | 型 | ユースケース |
|---|---|---|
| RAII | Drop トレイト | スコープ終了時の自動クリーンアップ |
| 遅延初期化 | OnceLock、LazyLock | 初期化の先送り |
| プール | r2d2、deadpool | コネクションの再利用 |
| ガード | MutexGuard | スコープ終了時のロック解放 |
| スコープ | カスタム構造体 | トランザクション境界 |
ライフサイクルイベント
| イベント | Rust の仕組み |
|---|---|
| 作成 | new()、Default |
| 遅延初期化 | OnceLock::get_or_init |
| 使用 | &self、&mut self |
| クリーンアップ | Drop::drop() |
パターンテンプレート
RAII ガード
struct FileGuard {
path: PathBuf,
_handle: File,
}
impl Drop for FileGuard {
fn drop(&mut self) {
// Cleanup: remove temp file
let _ = std::fs::remove_file(&self.path);
}
}
遅延シングルトン
use std::sync::OnceLock;
static CONFIG: OnceLock<Config> = OnceLock::new();
fn get_config() -> &'static Config {
CONFIG.get_or_init(|| {
Config::load().expect("config required")
})
}
よくあるエラー
| エラー | 原因 | 修正方法 |
|---|---|---|
| リソースリーク | Drop を忘れた | Drop または RAII ラッパーを実装する |
| 二重解放 | 手動でのメモリ管理 | Rust に任せる |
| drop 後の使用 | ダングリング参照 | ライフタイムを確認する |
| E0509 Drop 型からの移動 | 所有するフィールドの移動 | Option::take() |
| プールの枯渇 | リソースが返却されない | Drop によって返却されることを確認する |
アンチパターン
| アンチパターン | 問題点 | より良い方法 |
|---|---|---|
| 手動クリーンアップ | 忘れやすい | RAII/Drop |
lazy_static! | 外部依存 | std::sync::OnceLock |
| グローバルな可変状態 | スレッド安全ではない | OnceLock または適切な同期 |
| close を忘れる | リソースリーク | Drop を実装する |
関連スキル
| 場面 | 参照先 |
|---|---|
| スマートポインター | m02-resource |
| スレッドセーフな初期化 | m07-concurrency |
| ドメインのスコープ | m09-domain |
| クリーンアップ時のエラー | m06-error-handling |
コメント
Markdown 対応