このドキュメントは、この RDBMS 学習プロジェクトで共通に守るコーディングルールを定義する。 Rust の一次情報と、このリポジトリの構成・目的を踏まえて、実装判断がぶれないことを目的とする。
- ワークスペース配下の全クレートに適用する。
Cargo.tomlのedition = "2024"とrust-version = "1.94"を前提にする。- フォーマットと lint の最終的な設定ソースは
rustfmt.tomlとclippy.tomlとする。
- まず正しさを優先し、その上で可読性と拡張性を確保する。
- 学習用コードであっても、後続の
storage/sql/query/catalogが再利用しやすい境界を維持する。 - 実装前にテスト方針を決め、失敗するテストから着手する。
- 設計判断が今後の構造や公開 API に影響する場合は
docs/decisions.mdに記録する。
- 新しい構文・標準ライブラリ API・依存ライブラリの使用は、
rust-version = "1.94"で成立するものに限る。 - MSRV を引き上げる必要がある変更は、理由を明記したうえで
Cargo.tomlと関連ドキュメントを同時に更新する。 - 依存追加は「標準ライブラリでは不足する理由」「このプロジェクトでの用途」「MSRV への影響」を説明できる場合だけ行う。
- Rust の標準命名規約に従う。
- 型・トレイト・ enum variant は
UpperCamelCase - 関数・メソッド・モジュール・ローカル変数は
snake_case - 定数は
SCREAMING_SNAKE_CASE
- 型・トレイト・ enum variant は
- 略語は Rust で一般的な綴りを使う。既存の標準ライブラリやエコシステムの名前に寄せる。
- getter は原則
value()/value_mut()とし、不必要にget_を付けない。 - 変換系メソッドはコストと所有権に応じて
as_/to_/into_/into_innerを使い分ける。 - 公開 API では、意味の曖昧な bool 引数や引数過多を避ける。設定が増える場合は専用型へ切り出す。
- 構造体フィールドは必要最小限だけ公開し、まず
pub(crate)や専用メソッドで表現できないか検討する。
- 1 モジュール 1 責務を基本とする。パーサー、AST、カタログ、ページ管理などの関心を混在させない。
- crate をまたぐ公開型は、その crate の責務境界を表すものに限定する。
- 不変条件を持つ値は、生のフィールド公開よりもコンストラクタや専用メソッドで生成させる。
- 循環参照的な依存が見えたら、その場しのぎで回避せず、責務分割を見直す。
- 回復可能な失敗は
Resultで返し、呼び出し側へ判断を委ねる。 - エラー伝播は
?を優先し、深いmatchのネストで意図を埋もれさせない。 - ライブラリ crate では文脈を表す独自エラー型を優先し、
thiserrorで表現する。 - 実行境界や CLI などの集約層では
anyhowを使ってよいが、下位レイヤーの公開 API では濫用しない。 unwrap/expectはテストコード、到達不能な不変条件、プロトタイプを除いて使わない。panic!は「利用者が回復できない内部バグ」または「安全性の前提が破られた状態」に限定する。
- 実装前に失敗するテストを書く。正常系と異常系を最低 1 つずつ用意する。
- 単体テストはモジュール内部の振る舞いと不変条件を検証する。
- 統合テストは
tests/配下に置き、公開 API を外部利用者と同じ形で検証する。 - パーサーや式評価のような分岐が多い領域では、テーブルドリブンテストを優先する。
- バグ修正時は、再発防止のために失敗を再現するテストを先に追加する。
- テスト名は期待する振る舞いが読める文章にする。
- コメントは「何をしているか」の説明ではなく、「なぜその設計・分岐・順序が必要か」を書く。
- 非自明なロジック、所有権制約、並行処理の前提、不変条件には意図コメントを付ける。
- 公開 API には rustdoc を付け、要約を 1 文目で述べる。
- fallible な公開 API には
# Errors、panic しうる API には# Panics、unsafe API には# Safetyを記述する。 - rustdoc のサンプルで失敗しうる処理を書く場合は
unwrapではなく?を使う。 - コメント言語は日本語でよいが、
Safetyなど rustdoc の見出し名は標準的な英語表記を使う。
unsafeは、計測された必要性があるか、安全な代替手段では表現できない場合に限る。unsafeブロックは最小範囲に閉じ込め、直前に// Safety:コメントで成立条件を書く。unsafe fn/unsafe trait/unsafe implを追加する場合は、呼び出し側または実装側が守る条件を明記する。Send/Syncの手動実装は極力避ける。必要な場合は、保持フィールド・公開メソッド・破棄処理まで含めて安全性を説明する。- 並行処理は正しさが先で、性能最適化は後に行う。ロック順序や共有状態の所有者はコメントで残す。
- 変更後は少なくとも
cargo fmtとcargo clippy --workspaceを通す。 - 警告は放置せず修正を優先する。
allowを入れる場合は理由をコメントで残す。 rustfmt.tomlのmax_width = 100を前提に、行長よりも意味のまとまりを優先して整形する。clippy.tomlの閾値は設計の補助線として扱い、引数数・型複雑性・認知的複雑性が大きい場合は分割を検討する。
sqlcrate では AST は構文表現に徹し、実行時都合の情報を混ぜない。storagecrate ではページ ID、スロット番号、オフセットなどの生整数を長く持ち回さず、意味を持つ型で包むことを優先する。querycrate ではアルゴリズム最適化より先に、正しさを検証できる中間表現とテストを整える。- 途中実装で
TODOを残す場合は、何が未実装で何が前提か分かるようにする。曖昧なTODO: implementだけを残さない。
- Rust API Guidelines: Naming
- Rust API Guidelines: Documentation
- The Rust Programming Language: Error Handling
- The Rust Programming Language: Recoverable Errors with Result
- The Rust Programming Language: Test Organization
- Cargo Book: Rust Version
- Clippy documentation
- The Rustonomicon: Send and Sync
- Rust Reference: The
unsafekeyword