rust-best-practices について
rust-best-practicesは、Apollo GraphQLのRustベストプラクティスハンドブックに基づく、Rustコードの作成とレビュー向けスキルです。イディオム、エラー処理、性能、テスト、型、ドキュメントを扱います。
主な機能
- 01所有権と借用の指針
- 02エラー処理の規約
- 03性能とlintの助言
- 04テストの推奨事項
- 05ジェネリクスと型状態の指針
- 06ドキュメント作成の実践
活用シーン
- 01Rustのイディオムに沿ったコードレビュー
- 02エラー処理方法の選択
- 03性能とClippyの懸念点の確認
- 04テストとAPIドキュメントの計画
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ apollographql/ skills --skill rust-best-practicesインストール後、Claude Code で/rust-best-practicesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/chapter_01.mdchapter_02.mdchapter_03.mdchapter_04.mdchapter_05.mdchapter_06.mdchapter_07.mdchapter_08.mdchapter_09.md詳細
Rust のベストプラクティス
Rust コードを記述またはレビューする際は、以下のガイドラインを適用してください。Apollo GraphQL の[Rust ベストプラクティスハンドブック](https://github.com/apollographql/rust-best-practices)に基づいています。
ベストプラクティスの参照資料
レビューの前に、Apollo の Rust ベストプラクティスを確認してください。同じターン内に、該当するすべての章を並行して読んでください。フィードバックを提供する際は、以下のファイルを参照してください。
- [第 1 章 - コーディングスタイルとイディオム](references/chapter_01.md):借用とクローンの使い分け、Copy トレイト、Option/Result の扱い、イテレーター、コメント、関数を切り出すタイミング(重複か、不適切な抽象化か)
- [第 2 章 - Clippy とリンティング](references/chapter_02.md):Clippy の設定、重要な lint、ワークスペースでの lint 設定
- [第 3 章 - パフォーマンスを意識した考え方](references/chapter_03.md):プロファイリング、冗長なクローンの回避、スタックとヒープ、ゼロコスト抽象化
- [第 4 章 - エラー処理](references/chapter_04.md):Result と panic の使い分け、thiserror と anyhow の使い分け、エラー階層
- [第 5 章 - 自動テスト](references/chapter_05.md):テストの命名、テストごとに 1 つのアサーション、スナップショットテスト
- [第 6 章 - ジェネリクスとディスパッチ](references/chapter_06.md):静的ディスパッチと動的ディスパッチ、トレイトオブジェクト
- [第 7 章 - 型状態パターン](references/chapter_07.md):コンパイル時の状態安全性、使用するタイミング
- [第 8 章 - コメントとドキュメント](references/chapter_08.md):コメントを付けるタイミング、ドキュメントコメント、rustdoc
- [第 9 章 - ポインターを理解する](references/chapter_09.md):スレッド安全性、Send/Sync、ポインターの型
クイックリファレンス
借用と所有権
- 所有権の移動が必要でない限り、
.clone()よりも&Tを優先します - 関数の引数には、
Stringよりも&strを、Vec<T>よりも&[T]を使います - 小さな
Copy型(≤24 bytes)は、値渡しにできます - 所有権が明確でない場合は、
Cow<'_, T>を使います
エラー処理
- 失敗する可能性のある処理では
Result<T, E>を返し、本番コードでのpanic!は避けます - テスト以外では
unwrap()/expect()を使わないでください - ライブラリのエラーには
thiserrorを、バイナリに限ってanyhowを使います - エラーの伝播には、match の連鎖よりも
?演算子を優先します
パフォーマンス
- ベンチマークは必ず
--releaseフラグを付けて実行します - パフォーマンスに関するヒントを得るには、
cargo clippy -- -D clippy::perfを実行します - ループ内でのクローンは避けます。Copy 型では
.into_iter()よりも.iter()を使います - 手動のループよりもイテレーターを優先し、中間の
.collect()呼び出しは避けます
リンティング
定期的に実行します:cargo clippy --all-targets --all-features --locked -- -D warnings
注意すべき主な lint:
redundant_clone- 不要なクローンlarge_enum_variant- 大きすぎるバリアント(ボックス化を検討)needless_collect- 早すぎるコレクション化
正当化するコメントを添えて、#[allow(...)] よりも #[expect(clippy::lint)] を使います。
テスト
- わかりやすい名前を付けます:
process_should_return_error_when_input_empty() - 可能な限り、テストごとにアサーションは 1 つにします
- 公開 API の例にはドキュメントテスト(
///)を使います - 生成された出力のスナップショットテストには、
cargo instaの使用を検討します
ジェネリクスとディスパッチ
- パフォーマンスが重要なコードでは、ジェネリクス(静的ディスパッチ)を優先します
- 異種コレクションが必要な場合に限り、
dyn Traitを使います - 内部ではなく、API の境界でボックス化します
型状態パターン
型システムで有効な状態を表現し、無効な操作をコンパイル時に検出します:
struct Connection<State> { /* ... */ _state: PhantomData<State> }
struct Disconnected;
struct Connected;
impl Connection<Connected> {
fn send(&self, data: &[u8]) { /* only connected can send */ }
}
ドキュメント
//コメントでは「なぜ」を説明します(安全性、回避策、設計上の根拠)///ドキュメントコメントでは、公開 API の「何を」と「どのように」を説明します- すべての
TODOには、関連する issue をリンクします:// TODO(#42): ... - ライブラリでは
#![deny(missing_docs)]を有効にします
コメント
Markdown 対応