rust-trait-api-design について
Trait ベースの API を設計する Rust 開発者向けスキルです。具体型、ジェネリクス、トレイトオブジェクトの使い分けに加え、境界条件、変換、オブジェクト安全性、API テストを案内します。
主な機能
- 01具体型・ジェネリクス・動的ディスパッチを選択
- 02必要な箇所に境界条件を置く
- 03下流実装の境界を設計
- 04標準の変換トレイトを利用
- 05トレイトオブジェクトの安全性を確認
- 06公開 API の利用方法をテスト
活用シーン
- 01公開 Rust Trait API の設計
- 02ジェネリクスと dyn Trait の選択
- 03変換実装のレビュー
- 04下流ユーザー向け API 呼び出しのテスト
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ lvtd-llc/ skills --skill rust-trait-api-designインストール後、Claude Code で/rust-trait-api-designを入力して読み込まれたか確認します。
同梱ファイルagents/openai.yamlreferences/trait-api-patterns.md
詳細
Rust Trait API 設計
このスキルは、必要に応じて Rust API をジェネリックにし、シンプルにできる場合は具体的な型を使い、動的ディスパッチが設計の一部である場合はオブジェクトセーフにするために使用します。呼び出し側と実装者が理解できる、最小限の能力コントラクトを目指します。
基本的なワークフロー
- API が振る舞いを消費、借用、返却、保持、またはディスパッチするかを特定します。
- ローカルコードでは具体的な型から始めます。少なくとも 2 つの呼び出し元または実装で柔軟性が必要な場合にのみ、汎用化します。
- コンパイル時のポリモーフィズムとインライン化にはジェネリック境界を使用します。異種の値、プラグインのような拡張ポイント、または実行時ディスパッチには
dyn Traitを使用します。 - 境界は必要な箇所に配置します。境界が長い場合や関連型を含む場合は、
where句を優先します。 - トレイトを下流で実装できるようにするかを判断します。不変条件を外部から実装できないようにする必要がある場合は、トレイトをシールするか、フィールドを非公開にするか、コンストラクターを使用します。
- 標準の変換トレイトが要件に完全に合う場合は、それを使用します。
From、TryFrom、AsRef、AsMut、Borrow、ToOwned、Cowを確認する前に、独自の変換トレイトを作らないでください。 - スキルが想定する方法で将来のユーザーが公開 API を呼び出せることを証明する、コンパイルテスト、単体テスト、または例を追加します。
API 設計ルール
- 呼び出し側が多様な具体型を渡せるようにする場合、パラメーターには
impl Traitまたは名前付きジェネリックを使用します。 - 具体的な戻り値の型を隠す場合は
impl Traitを返します。具体的な型が実行時に変わる場合はBox<dyn Trait>を返します。 - 各実装に自然な関連型が 1 つある場合は、関連型を優先します。1 つの実装が複数の対象型をサポートする場合は、ジェネリックなトレイトパラメーターを優先します。
- 失敗しない変換には
From、失敗する可能性がある変換にはTryFromを実装します。これらを実装すると、呼び出し側はIntoとTryIntoを使用できます。 - 参照から参照への低コストな変換には
AsRefを使用します。借用形式と所有形式でEq、Hash、Ordの動作が同等である場合にのみ、Borrowを使用します。 - アルゴリズム上、ビット単位のコピーが必要な場合を除き、
Copy境界は避けます。
トレイトオブジェクトの確認
ジェネリックと dyn Trait のどちらを選ぶか決めるとき、または公開トレイトがオブジェクトセーフのチェックに失敗するときは、references/trait-api-patterns.md を読んでください。
公開トレイトをオブジェクトセーフにする前に、次の点を確認してください。
- メソッドがジェネリック型パラメーターを使用していない。
- メソッドが
where Self: Sizedで制約されていない限り、Selfを返さない。 - 必要に応じて、トレイトオブジェクトで関連型が指定されている。
- オブジェクトが
&dyn Trait、Box<dyn Trait>、Arc<dyn Trait + Send + Sync>などのポインターで保持されている。
よくある問題点
- イテレーションだけが必要なのに、公開関数が
&Vec<T>を受け取る。 - API が
Stringを受け取り、すぐに&strとして借用する。 - API が
FromではなくIntoを直接実装する。 - トレイトに多くの包括的な境界があるが、それを必要とするのは 1 つのメソッドだけである。
- 実行時ディスパッチが必要だからではなく、ライフタイムがわかりにくいという理由でトレイトオブジェクトを使っている。
- トレイトにおけるネイティブな
async fn、trait-variant、またはボックス化されたフューチャーが、ディスパッチとSendの要件により適合するか確認せずに、公開トレイトでasync-traitを使用している。
コメント
Markdown 対応