cpp について
明確な所有権、強い型によるモデル化、保守しやすいファイル境界、予測可能なネイティブ連携を重視するC++開発向けスキルです。ネイティブコードやNitro ModuleのC++部分を扱う開発者を対象としています。
主な機能
- 01型安全な状態モデリング
- 02RAIIと明示的な所有権の指針
- 03非同期処理とスレッド境界の指針
- 04ヘッダーと実装ファイルの整理
- 05Nitro HybridObjectの指針
活用シーン
- 01ネイティブAPIの状態モデリング
- 02所有権とライフタイム方式の選定
- 03C++実装とヘルパーの整理
- 04C++ Nitroコンポーネントの実装
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ margelo/ react-native-skills --skill cppインストール後、Claude Code で/cppを入力して読み込まれたか確認します。
同梱ファイルagents/openai.yaml
詳細
C++
明確な所有権、堅牢な型モデリング、保守しやすいファイル境界、予測可能なネイティブ連携が必要な C++ コードには、このスキルを使用してください。コードが Nitro Module の一部である場合は、生成された仕様、Promise のマッピング、CMake、HybridObject の制約に対応するため、build-nitro-modules と併用してください。
ワークフロー
- 編集する前に、生成されたヘッダー、公開 API の構成、ローカルの所有権パターンを確認します。
- 動作を実装する前に、型を使って有効な状態をモデル化します。
- ヘッダーは小さく安定させ、実装の詳細は
.cppファイルに移します。 - 中心となる実装ファイルを大きくするのではなく、責務ごとにヘルパーを分割します。
- 所有権、ライフタイム、スレッド処理、非同期処理の境界を明示します。
型安全な API 設計
- 状態のバリエーションは、
std::variant、継承、または個別の具象型で表現します。多数のstd::optionalフィールドを持つ 1 つの構造体でバリエーションを表現しないでください。 - 関連する値は、有効な状態ではオプションにしないでください。
barcodeとbarcodeTypeが常に組になっている必要がある場合は、両方をScannedBarcodeに持たせます。 std::optionalは、1 つの状態内におけるドメイン上の真の不在に使用し、「このオブジェクトが別の種類のものかもしれない」ことの表現には使いません。- 呼び出し側でオプションの有無を調べるより、コンパイル時にフローを決定する方法を優先します。
ファイル構成
- ファイル名はスコープの契約として扱います。
HybridDataScanner.cppはHybridDataScannerを実装するものであり、無関係なジオメトリ変換、UI ヘルパー、プラットフォームアダプター、拡張スタイルのユーティリティまで定義しないでください。 - 原則として、1 つのファイルには主要なクラス、構造体のファミリー、または一貫性のあるアルゴリズムを 1 つだけ置きます。デリゲート、アダプター、コンバーター、プラットフォーム用シム、再利用可能なヘルパーは、
GeometryConversions.cpp、DataScannerDelegate.cpp、PlatformViewController.cppのような名前付きファイルに分割します。 - プライベートヘルパーを匿名名前空間に置くのは、小規模で、そのファイルの主要な型だけに使用される場合に限ります。再利用可能なヘルパーや大規模なヘルパーは、
detail名前空間または内部フォルダーにある別ファイルへ移します。 - 行数はレビュー時の判断材料にします。おおむね 300 行未満のファイルであれば通常は問題ありません。それを超える場合は、まとまりのある 1 つの責務に結びついた明確な理由が必要です。無関係なヘルパー、変換、プラットフォーム連携が原因でファイルが大きくなっている場合は、設計上の問題です。
- 大きな実装本体をヘッダーに隠さないでください。ヘッダーには宣言、可視である必要があるテンプレート、小規模なインライン関数だけを置きます。
- 変換が 1 つの要素だけを読み取る場合は、要素型に変換を実装するか、その要素用の名前付きコンバーター関数を使います。この 1 要素用コンバーターは複数の値を返してもかまいません。呼び出し側では、標準のループ、
std::transform、集合への挿入、またはstd::accumulateを使って組み合わせます。 - コレクション全体にわたる検証、重複排除、順序付け、バッチ処理、キャッシュ、空でないことの確認、エラーの集約など、コレクションに実際のドメイン上の振る舞いがある場合に限り、コレクションレベルのヘルパーを追加します。
所有権と非同期処理
- RAII と明示的な所有権を優先し、値を使用してください。
std::unique_ptrとstd::shared_ptrは、実際に共有ライフタイムが必要な場合にのみ使用してください。 - 所有権を持つ生ポインターは避けてください。生ポインターと参照は非所有とし、周囲のライフタイムによってそのことが明確になるようにしてください。
- 文字列で型付けした状態ではなく、
std::variant、std::optional、強い型付けの構造体を使用して API のフローを表現してください。 - 短時間で決定的なローカル処理は同期的に実行してください。単純な値の構築、キャッシュ済みメタデータ、純粋な変換のために、エグゼキューター、Promise、コールバックの配線を導入しないでください。
- I/O、長時間の CPU 処理、プラットフォームのコールバックのために呼び出し元のスレッドをブロックしないでください。処理が待機する可能性がある場合は、プロジェクトの非同期抽象化、所有するエグゼキューター/スレッド、または Nitro
Promise<T>を使用してください。 - プラットフォーム API が要求する場合を除き、プラットフォームのメインスレッド/UI スレッドは避けてください。メインスレッド上のブロック処理は小さく保ち、パース、変換、I/O、セッションネゴシエーション、CPU 処理は、所有するエグゼキューター/スレッドまたは非同期 API に移してください。
- スレッドに依存する状態は、明確な所有者の管理下に置いてください。境界を文書化せずに、ミューテックス、キュー、コールバック、共有所有権を混在させないでください。
- エグゼキューター、キュー、スレッド、コールバックを繰り返し経由することは、アーキテクチャ上の問題として扱ってください。コンポーネントは、処理に使うエグゼキューター/スレッドを所有するか、公開非同期境界またはネイティブコールバック境界で一度だけその所有者へ処理を渡すようにしてください。
- ワークフローがプラットフォーム、ワーカー、JS/Nitro、コールバックスレッドの間を複数のネストした箇所で行き来する場合は、いったん停止し、オブジェクト/ライフサイクル/API を再設計してください。過剰なスレッド間の受け渡しはレイテンシを見えにくくし、順序の把握を難しくし、将来的なパフォーマンスの問題を引き起こします。
sleep_for、usleep、タイマー、追加のエグゼキューター経由、同じメソッドの二度呼び出しで、競合状態や準備完了に関する不具合を修正しないでください。所有権、状態マシン、ライフサイクルイベント、コールバックの契約、または非同期境界を修正してください。再試行は、ハードウェア、OS サービス、リモートサービス、ネットワークなど、外部の非決定性に対してのみ行い、回数を制限し、キャンセル可能かつ冪等にしてください。std::mutexは、デフォルトのリスナーやコールバックの配線ではなく、最終手段の同期機構として扱ってください。追加する前に、共有される可変値、並行して呼び出す処理、単一の所有者スレッド/キュー、不変スナップショット、メッセージパッシングでは不十分な理由を明確にしてください。- コールバックの呼び出し中、JS/Nitro への移行中、再入可能性が不明なプラットフォーム API の呼び出し中、またはユーザー提供コードの呼び出し中に、ミューテックスを保持しないでください。ディスパッチに必要なデータをコピー/スナップショットし、ロックを解除してから呼び出してください。
Nitro に関する注意事項
- C++ HybridObject は、生成された
Hybrid*Specクラスを継承し、生成されたシグネチャを完全にコピーしてください。 - 生成された非同期メソッドには
std::shared_ptr<Promise<T>>を使用してください。 - 生成された仕様の実装ファイルは HybridObject に専念させてください。変換ヘルパー、OpenCV ユーティリティ、プラットフォームアダプター、CMake 専用の接着コードは別ファイルに置いてください。
- JS に公開する基底 HybridObject は、C++ から Swift/Kotlin ベースのプラットフォームサービスを扱う必要がある場合、ネイティブインターフェースまたはアダプタークラスと組み合わせてください。
コメント
Markdown 対応